1. About¶
1.1. Abstract¶
This page provides additional background and comparisons for pconfigs. For the canonical high-level motivation and overview, start on the documentation homepage.
1.2. Technical TL;DR¶
You build the whole system in Python: A
pconfigsconfig is a Python dataclass instance that names the pieces of your system and their settings (often by nesting smaller configs).You stop threading options throughout your code: Your classes read settings from
self.config, so call sites don’t grow long lists of optional keyword arguments (Construction).You can print what will run before you run it:
repr(config)orpconfigs.printprints the fully resolved config fields as readable Python that’s easy to diff in code review (Printing).You can compute config fields with real Python: Use
@ppropertyandpinputs()to compute complex derived values (even whole sub-configs) while still keeping the user’s original inputs visible; usePinned[...]/Pin(...)to mark fields users must not set (Properties).You make new experiments by copying and changing a few lines: Create a new Python config file, copy a base config, and override only the fields you want to change (Quickstart).
You can test lots of configs the same way: Use
ptestto import and construct a whole tree of config files, so refactors don’t silently break old experiments (Testing).
1.3. Design principles¶
Experiments and systems should be:
Reproducible: A single, no-parameter command should reproduce a result (Runnables).
Controlled: Creating new experiments should not break old experiments (specialize prior configs instead of rewriting them).
Extensible: It should be possible to modify any part of an existing system (Subconfigs).
Transparent: It should be clear what code does just by reading it (Printing).
Comparable: It should be easy to compare prior experiments in new ways (diff printed configs and derived experiment files).
1.4. Comparison to other configuration systems¶
Gin configs¶
(TL;DR) Practical guidance:
Choose Gin when you want a lightweight way to bind values to callables.
Choose
pconfigswhen you want the experiment/system to be a typed, executable object with standardized running, printing/diffing, and testing workflows.
Key takeaways (high-level):
Global injection vs explicit scope: Gin often sets values globally (load order matters);
pconfigskeeps values in the config object you build.Refactors:
pconfigsuses normal Python names and fields, so IDE renames/find-references work well; Gin uses string keys, so refactors need more care.Built-in workflows:
pconfigsis built around printing, computed fields, and config-tree tests; Gin can support similar habits, but they are not the default workflow.
The table below summarizes common workflow differences.
Capability |
|
Gin |
|---|---|---|
Run an experiment with one standard command (the config fully specifies what runs) |
Built in: |
No standard command: you typically run your program and load one or more |
Print one file you can diff in review (naming types/functions via imports) |
Built in: |
Not the main artifact: Gin can dump an operative config, but it is not designed around producing a single import-explicit Python file for review diffs |
Make “where a value lives” obvious |
Values live on a nested config object (subconfigs, typed fields) |
Values are often global bindings; which value applies can depend on loaded files and override order |
Keep runtime call sites simple (avoid optional kwargs everywhere) |
A common pattern is “read from |
Not a goal: Gin is great at binding optional kwargs, so call sites often still follow that style |
Leverage standard IDE refactors (rename, find references) for config wiring |
Strong: wiring uses Python symbols and typed fields |
Weaker by default: configs are largely string-keyed selectors/bindings; refactors require extra discipline/tooling |
Mark fields users can’t set |
Built in: |
No built-in equivalent: you document and enforce conventions in code |
Compute fields while keeping user inputs visible |
Built in: |
Limited in |
Model environment variables as typed config |
Built in: |
Possible, but usually ad hoc ( |
Test a whole tree of configs |
Built in: |
No built-in convention: teams can add tests, but Gin doesn’t prescribe this workflow |
Configure external libraries without editing them |
Built in: |
Often requires editing/annotating code ( |
Design around readable printed configs |
A design goal (e.g., |
Not a core goal: Gin optimizes for runtime injection, not for a canonical printed artifact |