API Reference¶
Type Aliases¶
StrOrPath:str | os.PathLike[str]- All path parameters accept strings directly, Path objects, or any os.PathLike implementation. Import withfrom rconfig import StrOrPathfor type annotations in your own code.
Common API¶
Core functions for everyday use. These are the primary interfaces most users will interact with.
rc.register(name, target)¶
Register a target class under a unique name for use in config files.
Parameters:
| Parameter | Type | Default | Description |
|---|---|---|---|
name |
str |
required | Unique identifier for the target class. This is the value used in _target_ fields. |
target |
type |
required | The Python class to register. |
Returns: None
Raises:
| Exception | Condition |
|---|---|
ValueError |
If name is already registered |
Examples:
rc.unregister(name)¶
Remove a previously registered configuration reference.
Parameters:
| Parameter | Type | Default | Description |
|---|---|---|---|
name |
str |
required | Identifier of the reference to unregister. |
Returns: None
Raises:
| Exception | Condition |
|---|---|
KeyError |
If no reference with that name exists |
Examples:
rc.validate(path, *, inner_path=None, overrides=None, cli_overrides=True)¶
Validate a config file without instantiating (dry-run). Checks all _required_ values have been satisfied.
Parameters:
| Parameter | Type | Default | Description |
|---|---|---|---|
path |
StrOrPath |
required | Path to the configuration file. Accepts str, Path, or any os.PathLike. |
inner_path |
str \| None |
None |
Dot-notation path to validate only a section (e.g., "model" or "trainer.callbacks[0]"). _required_ markers outside this section are ignored. When specified, the root-level _target_ is optional and types can be inferred from parent's type hints (including list[X], set[X], dict[str, X], Sequence[X], Mapping[K, V], tuple[A, B, C], Optional[container], Annotated[X, ...], NewType, and Union[A, B] via structural matching). |
overrides |
dict[str, Any] \| None |
None |
Dictionary of config overrides using dot notation keys. |
cli_overrides |
bool |
True |
Whether to parse CLI overrides from sys.argv. |
Returns: ValidationResult with fields:
valid(bool):Trueif validation passed with no errorserrors(list[ValidationError]): List of validation errors found
Raises:
| Exception | Condition |
|---|---|
ConfigFileError |
If file cannot be loaded or parsed |
InvalidInnerPathError |
If inner_path doesn't exist or points to a scalar |
Examples:
result = rc.validate(path=Path("config.yaml"))
if result.valid:
print("Config is valid!")
else:
for error in result.errors:
print(error)
# With overrides to satisfy _required_ values
result = rc.validate(
path=Path("config.yaml"),
overrides={"api_key": "secret123"},
)
# Validate only a section
result = rc.validate(path=Path("trainer.yaml"), inner_path="model")
rc.instantiate(path, expected_type=None, *, inner_path=None, overrides=None, cli_overrides=True, lazy=False)¶
Load, compose, validate, and instantiate a configuration file into Python objects.
Parameters:
| Parameter | Type | Default | Description |
|---|---|---|---|
path |
StrOrPath |
required | Path to the configuration file. Accepts str, Path, or any os.PathLike. Supports .yaml, .yml, .json, .toml. |
expected_type |
type[T] \| None |
None |
Optional type for type-safe returns. Enables IDE autocompletion and type checking. |
inner_path |
str \| None |
None |
Dot-notation path to instantiate only a section (e.g.,"model.encoder" or "trainer.callbacks[0]"). Interpolations are resolved from the full config before extraction. When specified, the root-level _target_ is optional and types can be inferred from parent's type hints (including list[X], set[X], dict[str, X], Sequence[X], Mapping[K, V], tuple[A, B, C], Optional[container], Annotated[X, ...], NewType, and Union[A, B] via structural matching). |
overrides |
dict[str, Any] \| None |
None |
Config overrides using dot notation keys. Applied before CLI overrides. |
cli_overrides |
bool |
True |
Whether to parse CLI overrides from sys.argv. Set to False for tests or library usage. |
lazy |
bool |
False |
If True, all nested configs delay __init__ until first attribute access. |
Returns: T if expected_type provided, otherwise Any
Raises:
| Exception | Condition |
|---|---|
ConfigFileError |
File cannot be loaded or parsed |
TargetNotFoundError |
_target_ value not registered |
ValidationError |
Config structure is invalid |
RequiredValueError |
_required_ value not provided |
CircularRefError |
Circular _ref_ references detected |
CircularInstanceError |
Circular _instance_ references detected |
RefResolutionError |
A _ref_ cannot be resolved |
InstanceResolutionError |
An _instance_ path cannot be resolved |
InvalidInnerPathError |
inner_path doesn't exist in config |
InvalidOverridePathError |
An override path doesn't exist |
InvalidOverrideSyntaxError |
An override string is malformed |
InstantiationError |
Object creation fails |
Examples:
# Basic usage - string paths work directly
model = rc.instantiate(path="config.yaml")
# Type-safe with IDE autocompletion
model = rc.instantiate(path="config.yaml", expected_type=ModelConfig)
# Partial instantiation
encoder = rc.instantiate(path="trainer.yaml", inner_path="model.encoder")
# With overrides, no CLI parsing (for tests)
model = rc.instantiate(
path="config.yaml",
overrides={"learning_rate": 0.001},
cli_overrides=False,
)
# Lazy instantiation
app = rc.instantiate(path="app.yaml", lazy=True)
# Path objects also work
from pathlib import Path
model = rc.instantiate(path=Path("config.yaml"))
rc.instantiate_multirun(path, expected_type=None, *, sweep=None, experiments=None, overrides=None, inner_path=None, cli_overrides=True, lazy=False)¶
Generate and instantiate multiple config combinations from sweep parameters and experiments. See Multirun Support for detailed usage examples.
Parameters:
| Parameter | Type | Default | Description |
|---|---|---|---|
path |
StrOrPath |
required | Path to the base configuration file. Accepts str, Path, or any os.PathLike. |
expected_type |
type[T] \| None |
None |
Optional type for type-safe returns. |
sweep |
dict[str, list[Any]] \| None |
None |
Dict of parameter paths to lists of values. All combinations (cartesian product) are generated. |
experiments |
list[dict[str, Any]] \| None |
None |
List of explicit experiment override dicts. |
overrides |
dict[str, Any] \| None |
None |
Constant overrides applied to all runs (lowest priority). |
inner_path |
str \| None |
None |
Dot-notation path to instantiate only a section (e.g., "model"). Interpolations are resolved from the full config before extraction. |
cli_overrides |
bool |
True |
Whether to parse CLI overrides from sys.argv. |
lazy |
bool |
False |
If True, nested configs delay __init__ until first attribute access. |
Returns: MultirunIterator[T] if expected_type provided, otherwise MultirunIterator[Any]
Raises:
| Exception | Condition |
|---|---|
NoRunConfigurationError |
Neither sweep nor experiments provided |
InvalidSweepValueError |
Sweep values are not lists |
InvalidInnerPathError |
inner_path doesn't exist in config (when accessed) |
Examples:
# Sweep with partial instantiation - string paths work directly
for result in rc.instantiate_multirun(
path="trainer.yaml",
inner_path="model",
sweep={"lr": [0.01, 0.001]},
):
model = result.instance # Only the model section
# Combined sweep and experiments
for result in rc.instantiate_multirun(
path="config.yaml",
experiments=[{"model": "resnet"}, {"model": "vit"}],
sweep={"lr": [0.01, 0.001]},
):
train(result.instance) # 4 runs total
rc.known_targets()¶
Get a read-only view of all registered configuration references.
Parameters: None
Returns: MappingProxyType[str, TargetEntry] - Immutable mapping of name to TargetEntry
TargetEntry has attributes:
name(str): Identifier for the target classtarget_class(type[Any]): The registered classdecisive_init_parameters(MappingProxyType[str, Parameter]): Constructor parameters
Examples:
refs = rc.known_targets()
for name, ref in refs.items():
print(f"{name}: {ref.target_class}")
for param_name, param in ref.decisive_init_parameters.items():
print(f" {param_name}: {param.annotation}")
rc.get_provenance(path, *, inner_path=None, overrides=None, cli_overrides=True)¶
Compose a config file and track the origin of each value.
Parameters:
| Parameter | Type | Default | Description |
|---|---|---|---|
path |
StrOrPath |
required | Path to the entry-point config file. Accepts str, Path, or any os.PathLike. |
inner_path |
str \| None |
None |
If specified, returns provenance only for this section. Uses lazy loading. |
overrides |
dict[str, Any] \| None |
None |
Dictionary of config overrides using dot notation keys. |
cli_overrides |
bool |
True |
Whether to parse CLI overrides from sys.argv. Set to False for tests or library usage. |
Returns: Provenance object with methods:
get(path: str) -> ProvenanceEntry | None: Get entry for a specific config pathitems() -> Iterator[tuple[str, ProvenanceEntry]]: Iterate all (path, entry) tuplestrace(path: str) -> ProvenanceNode | None: Get full tree for a pathto_dict() -> dict: Export as dictionary
Use rc.format(prov) for customized output formatting.
Examples:
# String paths work directly
prov = rc.get_provenance(path="trainer.yaml")
print(prov) # Default formatting
entry = prov.get("model.layers")
print(f"Defined at: {entry.file}:{entry.line}")
# Custom formatting
print(rc.format(prov).minimal())
print(rc.format(prov).for_path("/model.*"))
# Partial provenance - only loads files needed for model section
prov = rc.get_provenance(path="trainer.yaml", inner_path="model")
# With overrides
prov = rc.get_provenance(
path=Path("config.yaml"),
overrides={"model.lr": 0.01}
)
# Disable CLI parsing (for tests/library usage)
prov = rc.get_provenance(path=Path("config.yaml"), cli_overrides=False)
rc.diff(left, right, *, left_inner_path=None, right_inner_path=None, left_overrides=None, right_overrides=None, cli_overrides=False)¶
Compare two configurations and report differences.
Parameters:
| Parameter | Type | Default | Description |
|---|---|---|---|
left |
StrOrPath \| Provenance |
required | Left (base) config. Path or existing Provenance object. |
right |
StrOrPath \| Provenance |
required | Right (new) config. Path or existing Provenance object. |
left_inner_path |
str \| None |
None |
Dot-notation path to compare only a section of the left config. |
right_inner_path |
str \| None |
None |
Dot-notation path to compare only a section of the right config. |
left_overrides |
dict[str, Any] \| None |
None |
Overrides for left config (ignored if left is Provenance). |
right_overrides |
dict[str, Any] \| None |
None |
Overrides for right config (ignored if right is Provenance). |
cli_overrides |
bool |
False |
Whether to parse CLI overrides from sys.argv. |
Returns: ConfigDiff - Immutable object with added, removed, changed, unchanged views. Each view is a MappingProxyType[str, DiffEntry].
Use rc.format(diff) for customized output formatting.
Examples:
# Compare two config files
diff = rc.diff(Path("config_v1.yaml"), Path("config_v2.yaml"))
# Compare same file with different overrides
diff = rc.diff(
Path("config.yaml"),
Path("config.yaml"),
left_overrides={"model.lr": 0.001},
right_overrides={"model.lr": 0.01},
)
# Reuse existing provenance for efficiency
prov_v1 = rc.get_provenance(path="v1.yaml")
prov_v2 = rc.get_provenance(path="v2.yaml")
diff = rc.diff(prov_v1, prov_v2)
# Compare specific sections
diff = rc.diff(
Path("v1.yaml"), Path("v2.yaml"),
left_inner_path="model",
right_inner_path="model",
)
rc.format(obj, layout=None)¶
Format a Provenance or ConfigDiff object for display. Returns a fluent builder for configuring output via method chaining.
Parameters:
| Parameter | Type | Default | Description |
|---|---|---|---|
obj |
Provenance \| ConfigDiff |
required | The object to format. |
layout |
ProvenanceLayout \| None |
None |
Optional custom layout (Provenance only). Ignored for ConfigDiff. |
Returns: ProvenanceFormat when given Provenance, DiffFormat when given ConfigDiff. Both support method chaining for presets, show/hide toggles, filtering, and layout selection.
Raises:
| Exception | Condition |
|---|---|
TypeError |
If obj is not a Provenance or ConfigDiff |
Examples:
# Provenance formatting
prov = rc.get_provenance(path="config.yaml")
print(rc.format(prov).minimal())
print(rc.format(prov).for_path("/model.*").tree())
print(rc.format(prov).full().flat())
# Diff formatting
diff = rc.diff(Path("v1.yaml"), Path("v2.yaml"))
print(rc.format(diff).terminal())
print(rc.format(diff).show_provenance().markdown())
print(rc.format(diff).changes_only().tree())
rc.set_cache_size(size)¶
Configure the LRU cache for loaded config files.
Parameters:
| Parameter | Type | Default | Description |
|---|---|---|---|
size |
int |
required | Cache size. Use 0 for unlimited (default behavior). |
Returns: None
Examples:
rc.clear_cache()¶
Clear the config file cache.
Parameters: None
Returns: None
Examples:
rc.is_lazy_proxy(obj)¶
Check if an object is an uninitialized lazy proxy.
Parameters:
| Parameter | Type | Default | Description |
|---|---|---|---|
obj |
Any |
required | Object to check. |
Returns: bool - True if object is a lazy proxy that hasn't been initialized yet
Examples:
model = rc.instantiate(path=Path("config.yaml"), lazy=True)
print(rc.is_lazy_proxy(obj=model)) # True
_ = model.hidden_size # Triggers initialization
print(rc.is_lazy_proxy(obj=model)) # False
rc.force_initialize(obj)¶
Force initialization of a lazy proxy without accessing attributes. No-op for regular objects.
Parameters:
| Parameter | Type | Default | Description |
|---|---|---|---|
obj |
Any |
required | Lazy proxy or regular object. |
Returns: None
Examples:
model = rc.instantiate(path=Path("config.yaml"), lazy=True)
rc.force_initialize(obj=model) # model.__init__ called now
print(rc.is_lazy_proxy(obj=model)) # False
rc.to_dict(path, *, overrides=None, cli_overrides=True, exclude_markers=False)¶
Export resolved config as a Python dictionary.
Parameters:
| Parameter | Type | Default | Description |
|---|---|---|---|
path |
StrOrPath |
required | Path to config file. Accepts str, Path, or any os.PathLike. |
overrides |
dict[str, Any] \| None |
None |
Dictionary of config overrides. |
cli_overrides |
bool |
True |
Whether to parse CLI overrides. |
exclude_markers |
bool |
False |
If True, remove internal markers (_target_, _ref_, _instance_, _lazy_). |
Returns: dict[str, Any] - Resolved config as a dictionary
Examples:
config = rc.to_dict(path=Path("config.yaml"))
clean = rc.to_dict(path=Path("config.yaml"), exclude_markers=True)
rc.to_yaml(path, *, overrides=None, cli_overrides=True, exclude_markers=False)¶
Export resolved config as a YAML string.
Parameters:
| Parameter | Type | Default | Description |
|---|---|---|---|
path |
StrOrPath |
required | Path to config file. Accepts str, Path, or any os.PathLike. |
overrides |
dict[str, Any] \| None |
None |
Dictionary of config overrides. |
cli_overrides |
bool |
True |
Whether to parse CLI overrides. |
exclude_markers |
bool |
False |
If True, remove internal markers. |
Returns: str - Resolved config as a YAML string
Examples:
rc.to_json(path, *, overrides=None, cli_overrides=True, exclude_markers=False, indent=2)¶
Export resolved config as a JSON string.
Parameters:
| Parameter | Type | Default | Description |
|---|---|---|---|
path |
StrOrPath |
required | Path to config file. Accepts str, Path, or any os.PathLike. |
overrides |
dict[str, Any] \| None |
None |
Dictionary of config overrides. |
cli_overrides |
bool |
True |
Whether to parse CLI overrides. |
exclude_markers |
bool |
False |
If True, remove internal markers. |
indent |
int \| None |
2 |
Number of spaces for indentation.None for compact output. |
Returns: str - Resolved config as a JSON string
Examples:
json_str = rc.to_json(path=Path("config.yaml"))
compact = rc.to_json(path=Path("config.yaml"), indent=None)
rc.to_toml(path, *, overrides=None, cli_overrides=True, exclude_markers=False)¶
Export resolved config as a TOML string.
Parameters:
| Parameter | Type | Default | Description |
|---|---|---|---|
path |
StrOrPath |
required | Path to config file. Accepts str, Path, or any os.PathLike. |
overrides |
dict[str, Any] \| None |
None |
Dictionary of config overrides. |
cli_overrides |
bool |
True |
Whether to parse CLI overrides. |
exclude_markers |
bool |
False |
If True, remove internal markers. |
Returns: str - Resolved config as a TOML string
Examples:
rc.to_file(source, output_path, *, overrides=None, cli_overrides=True, exclude_markers=False)¶
Export config to a single file with format auto-detected from output path extension.
Parameters:
| Parameter | Type | Default | Description |
|---|---|---|---|
source |
StrOrPath \| dict[str, Any] |
required | Path to config file, or dict. Accepts str, Path, or any os.PathLike. |
output_path |
StrOrPath |
required | Output file path. Extension determines format (.yaml, .json, .toml). |
overrides |
dict[str, Any] \| None |
None |
Config overrides. Ignored if source is dict. |
cli_overrides |
bool |
True |
Parse CLI overrides. Ignored if source is dict. |
exclude_markers |
bool |
False |
If True, remove internal markers. |
Returns: None
Raises:
| Exception | Condition |
|---|---|
ConfigFileError |
Output file extension not supported |
Examples:
# From file path
rc.to_file(source=Path("config.yaml"), output_path=Path("output.json"))
# From dict
config = {"model": {"lr": 0.01}, "epochs": 10}
rc.to_file(source=config, output_path=Path("output.yaml"))
rc.to_files(source, config_root_file, *, overrides=None, cli_overrides=True, exclude_markers=False)¶
Export config preserving file structure (with _ref_ relationships).
Parameters:
| Parameter | Type | Default | Description |
|---|---|---|---|
source |
StrOrPath \| dict[str, Any] |
required | Path to config file, or dict. Accepts str, Path, or any os.PathLike. |
config_root_file |
StrOrPath |
required | Output root file path. Extension determines root format. |
overrides |
dict[str, Any] \| None |
None |
Config overrides. Ignored if source is dict. |
cli_overrides |
bool |
True |
Parse CLI overrides. Ignored if source is dict. |
exclude_markers |
bool |
False |
If True, remove internal markers. |
Returns: None
Behavior:
- Root file format determined by
config_root_fileextension - Referenced files preserve their original formats
- When source is dict, only root file is written
Examples:
rc.to_files(source=Path("trainer.yaml"), config_root_file=Path("output/trainer.json"))
# Creates:
# output/trainer.json (root in JSON)
# output/models/resnet.yaml (preserves YAML)
rc.export(path, exporter, *, overrides=None, cli_overrides=True)¶
Export resolved config using a custom exporter.
Parameters:
| Parameter | Type | Default | Description |
|---|---|---|---|
path |
StrOrPath |
required | Path to config file. Accepts str, Path, or any os.PathLike. |
exporter |
Exporter |
required | Exporter instance to use. |
overrides |
dict[str, Any] \| None |
None |
Dictionary of config overrides. |
cli_overrides |
bool |
True |
Parse CLI overrides. |
Returns: The exported data in the exporter's target format
Examples:
class MyExporter(Exporter):
def export(self, config: dict) -> str:
return json.dumps(config)
result = rc.export(path=Path("config.yaml"), exporter=MyExporter())
@rc.resolver(*path)¶
Decorator to register a resolver function for use in interpolation expressions.
Parameters:
| Parameter | Type | Default | Description |
|---|---|---|---|
*path |
str |
required | Path components. Accepts multiple arguments ("db", "lookup") or a single delimited string ("db:lookup" or "db.lookup"). |
Returns: Decorator function
Special Parameters (in decorated function):
_config_(dict): Keyword-only parameter that receives read-only view of current config
Examples:
# All equivalent ways to register "db:lookup":
@rc.resolver("db", "lookup")
def lookup1(table: str, id: int) -> dict:
return database.get(table, id)
@rc.resolver("db:lookup")
def lookup2(table: str, id: int) -> dict:
return database.get(table, id)
@rc.resolver("db.lookup")
def lookup3(table: str, id: int) -> dict:
return database.get(table, id)
# Simple resolver
@rc.resolver("uuid")
def gen_uuid() -> str:
import uuid
return str(uuid.uuid4())
# Resolver with config access
@rc.resolver("derive")
def derive(path: str, *, _config_: dict) -> Any:
return _config_.get(path)
rc.register_resolver(*path, func)¶
Register a custom resolver function for use in interpolation expressions.
Parameters:
| Parameter | Type | Default | Description |
|---|---|---|---|
*path |
str |
required | Path components. Accepts multiple arguments ("db", "lookup") or a single delimited string ("db:lookup" or "db.lookup"). |
func |
Callable[..., Any] |
required | The resolver function to register. |
Returns: None
Raises:
| Exception | Condition |
|---|---|
ValueError |
If path is empty or func is not callable |
Examples:
def gen_uuid() -> str:
import uuid
return str(uuid.uuid4())
# All equivalent:
rc.register_resolver("uuid", func=gen_uuid)
rc.register_resolver("db", "lookup", func=my_lookup)
rc.register_resolver("db:lookup", func=my_lookup)
rc.register_resolver("db.lookup", func=my_lookup)
rc.unregister_resolver(*path)¶
Unregister a previously registered resolver.
Parameters:
| Parameter | Type | Default | Description |
|---|---|---|---|
*path |
str |
required | Path components. Accepts multiple arguments ("db", "lookup") or a single delimited string ("db:lookup" or "db.lookup"). |
Returns: None
Raises:
| Exception | Condition |
|---|---|
KeyError |
No resolver with that path exists |
Examples:
rc.unregister_resolver("uuid")
# All equivalent ways to unregister "db:lookup":
rc.unregister_resolver("db", "lookup")
rc.unregister_resolver("db:lookup")
rc.unregister_resolver("db.lookup")
rc.set_help_integration(integration)¶
Set a custom help integration for CLI help display.
Parameters:
| Parameter | Type | Default | Description |
|---|---|---|---|
integration |
HelpIntegration |
required | A HelpIntegration instance to use. |
Returns: None
Raises:
| Exception | Condition |
|---|---|
ValueError |
If integration is None. |
Examples:
rc.current_help_integration()¶
Get the current help integration.
Parameters: None
Returns: HelpIntegration - The current integration (default: FlatHelpIntegration)
Examples:
integration = rc.current_help_integration()
print(type(integration)) # <class 'rconfig.help.FlatHelpIntegration'>
@rc.help_integration¶
Decorator to register a function as the help integration.
The decorated function receives (provenance, config_path) and is responsible for all behavior including calling sys.exit() if needed.
Parameters:
| Parameter | Type | Default | Description |
|---|---|---|---|
func |
Callable[[Provenance, str], None] |
required | Function to handle help display. |
Returns: The same function (for use as decorator)
Examples:
@rc.help_integration
def my_help(provenance, config_path):
print(f"Help for {config_path}")
for path, entry in provenance.items():
print(f" {path}: {entry.type_hint}")
sys.exit(0)
@rc.on_config_loaded(*, pattern=None, priority=50)¶
Decorator to register a hook called after config composition, before instantiation.
Hooks can optionally return a dict to modify the config. If a hook returns None (or doesn't return), the config is unchanged. Multiple hooks chain modifications in priority order.
Parameters:
| Parameter | Type | Default | Description |
|---|---|---|---|
pattern |
str \| None |
None |
Glob pattern for conditional execution. |
priority |
int |
50 |
Execution order (lower values run first). |
Returns: The decorated function.
Examples:
from rconfig.hooks import HookContext
@rc.on_config_loaded
def validate_paths(ctx: HookContext) -> None:
"""Validate data paths exist."""
if ctx.config and "data_path" in ctx.config:
path = Path(ctx.config["data_path"])
if not path.exists():
raise ValueError(f"Data path not found: {path}")
@rc.on_config_loaded(pattern="**/model/*.yaml", priority=10)
def model_hook(ctx: HookContext) -> None:
"""Only runs for model configs, runs early."""
...
@rc.on_config_loaded
def inject_secrets(ctx: HookContext) -> dict | None:
"""Modify config by returning a new dict."""
if ctx.config.get("api_key") == "_required_":
return {**ctx.config, "api_key": os.getenv("API_KEY")}
return None # No changes
@rc.on_before_instantiate(*, pattern=None, priority=50)¶
Decorator to register a hook called before each object's constructor.
Parameters:
| Parameter | Type | Default | Description |
|---|---|---|---|
pattern |
str \| None |
None |
Glob pattern for conditional execution. |
priority |
int |
50 |
Execution order (lower values run first). |
Returns: The decorated function.
Examples:
@rc.on_before_instantiate
def log_instantiation(ctx: HookContext) -> None:
print(f"Creating {ctx.target_name} at {ctx.inner_path}")
@rc.on_after_instantiate(*, pattern=None, priority=50)¶
Decorator to register a hook called after each object's constructor returns.
Parameters:
| Parameter | Type | Default | Description |
|---|---|---|---|
pattern |
str \| None |
None |
Glob pattern for conditional execution. |
priority |
int |
50 |
Execution order (lower values run first). |
Returns: The decorated function.
Examples:
@rc.on_after_instantiate
def register_metrics(ctx: HookContext) -> None:
metrics.register(ctx.target_name, ctx.instance)
@rc.on_error(*, pattern=None, priority=50)¶
Decorator to register a hook called when instantiation fails.
Parameters:
| Parameter | Type | Default | Description |
|---|---|---|---|
pattern |
str \| None |
None |
Glob pattern for conditional execution. |
priority |
int |
50 |
Execution order (lower values run first). |
Returns: The decorated function.
Examples:
@rc.on_error
def log_failures(ctx: HookContext) -> None:
logger.error(f"Instantiation failed: {ctx.error}")
rc.register_hook(phase, func, *, name=None, pattern=None, priority=50)¶
Explicitly register a hook function for a specific phase.
Parameters:
| Parameter | Type | Default | Description |
|---|---|---|---|
phase |
HookPhase |
required | The lifecycle phase to register for. |
func |
Callable |
required | The hook function. |
name |
str \| None |
None |
Hook name (defaults to function name). |
pattern |
str \| None |
None |
Glob pattern for conditional execution. |
priority |
int |
50 |
Execution order (lower values run first). |
Returns: None
Examples:
from rconfig.hooks import HookPhase
def my_hook(ctx: HookContext) -> None:
print(f"Config loaded: {ctx.config_path}")
rc.register_hook(HookPhase.CONFIG_LOADED, my_hook, name="my_hook")
rc.unregister_hook(name, *, phase=None)¶
Remove a registered hook by name.
Parameters:
| Parameter | Type | Default | Description |
|---|---|---|---|
name |
str |
required | Name of the hook to remove. |
phase |
HookPhase \| None |
None |
If specified, only remove from this phase. |
Returns: None
Raises:
| Exception | Condition |
|---|---|
KeyError |
If no hook with that name exists |
Examples:
rc.register_callback(callback)¶
Register a Callback class instance. All implemented methods are registered as hooks.
Parameters:
| Parameter | Type | Default | Description |
|---|---|---|---|
callback |
Callback |
required | Instance of a Callback subclass |
Returns: None
Examples:
class ExperimentTracker(rc.Callback):
def on_config_loaded(self, ctx: HookContext) -> None:
self.run_id = start_run()
log_config(self.run_id, dict(ctx.config))
def on_after_instantiate(self, ctx: HookContext) -> None:
log_component(self.run_id, ctx.target_name)
tracker = ExperimentTracker()
rc.register_callback(tracker)
rc.unregister_callback(callback)¶
Remove all hooks registered by a Callback instance.
Parameters:
| Parameter | Type | Default | Description |
|---|---|---|---|
callback |
Callback |
required | The Callback instance to remove |
Returns: None
Examples:
rc.known_hooks()¶
Return a read-only view of all registered hooks.
Parameters: None
Returns: MappingProxyType[HookPhase, tuple[HookEntry, ...]]
Examples:
for phase, hooks in rc.known_hooks().items():
for hook in hooks:
print(f"{phase.name}: {hook.name} (priority={hook.priority})")
Common Types¶
Types returned by common API functions.
ValidationResult¶
Result of config validation, returned by rc.validate().
Attributes:
| Attribute | Type | Description |
|---|---|---|
valid |
bool |
True if validation passed with no errors |
errors |
list[ValidationError] |
List of validation errors (empty if valid=True) |
Examples:
result = rc.validate(path="config.yaml")
if not result.valid:
for error in result.errors:
print(error)
ConfigDiff¶
Immutable diff result, returned by rc.diff(). Acts as a mapping of config paths to DiffEntry objects.
Attributes:
| Attribute | Type | Description |
|---|---|---|
added |
MappingProxyType[str, DiffEntry] |
Entries present only in right |
removed |
MappingProxyType[str, DiffEntry] |
Entries present only in left |
changed |
MappingProxyType[str, DiffEntry] |
Entries with different values |
unchanged |
MappingProxyType[str, DiffEntry] |
Entries with identical values |
Methods:
| Method | Returns | Description |
|---|---|---|
is_empty() |
bool |
True if no added/removed/changed |
to_dict() |
dict[str, Any] |
Export as dictionary |
__len__() |
int |
Total entry count |
__contains__(path) |
bool |
Check if path exists in diff |
__getitem__(path) |
DiffEntry |
Get entry by config path |
DiffEntry¶
A single entry in a ConfigDiff.
Attributes:
| Attribute | Type | Description |
|---|---|---|
path |
str |
Config path (e.g., "model.lr") |
diff_type |
DiffEntryType |
One of: ADDED, REMOVED, CHANGED, UNCHANGED |
left_value |
Any |
Value in left config (None if added) |
right_value |
Any |
Value in right config (None if removed) |
left_provenance |
ProvenanceEntry \| None |
Provenance entry from left config |
right_provenance |
ProvenanceEntry \| None |
Provenance entry from right config |
ProvenanceNode¶
Immutable node in a provenance trace tree, returned by prov.trace(path). Forms a tree structure for tracing compound expressions through refs, interpolations, operators, and resolvers.
Attributes:
| Attribute | Type | Description |
|---|---|---|
source_type |
NodeSourceType |
Type of this node (file, ref, interpolation, etc.) |
path |
str \| None |
Config path (e.g., "/model.lr") |
file |
str \| None |
Source file name |
line |
int \| None |
Line number in source file |
value |
Any |
The resolved value at this node |
expression |
str \| None |
Interpolation expression (e.g., "${/a + /b}") |
operator |
str \| None |
Operator for compound expressions (+, *, etc.) |
env_var |
str \| None |
Environment variable name (for env sources) |
cli_arg |
str \| None |
CLI argument (for CLI sources) |
resolver_name |
str \| None |
Resolver path (e.g., "uuid", "db:lookup") |
resolver_func |
str \| None |
Function name of the resolver |
resolver_module |
str \| None |
Module where the resolver is defined |
children |
tuple[ProvenanceNode, ...] |
Child nodes in the tree |
Methods:
| Method | Returns | Description |
|---|---|---|
to_dict() |
dict[str, Any] |
Recursively convert to dictionary |
Examples:
prov = rc.get_provenance(path="config.yaml")
tree = prov.trace("model.lr")
if tree:
print(tree.source_type) # "file", "interpolation", etc.
print(tree.file, tree.line)
for child in tree.children:
print(f" {child.source_type}: {child.path}")
# Export as dict
data = tree.to_dict()
NodeSourceType¶
Enum (StrEnum) indicating the type of each node in a provenance trace tree.
Values:
| Value | Description |
|---|---|
FILE |
Value came from a config file |
REF |
Value came from a _ref_ reference |
INSTANCE |
Value came from an instance chain |
INTERPOLATION |
Value was computed via interpolation |
CLI |
Value was set via command-line argument |
ENV |
Value was set via environment variable |
PROGRAMMATIC |
Value was set programmatically |
OPERATOR |
Value is result of an operator expression |
RESOLVER |
Value came from a resolver function |
Advanced API¶
Classes and types for extending and customizing rconfig. Use these when you need to create custom loaders, exporters, or help integrations.
Multirun Types¶
MultirunResult¶
Result of a single multirun instantiation. Contains the immutable resolved config, the specific overrides applied for this run, and the instantiated object (or stored error).
Attributes:
| Attribute | Type | Description |
|---|---|---|
config |
MappingProxyType[str, Any] |
Immutable view of the resolved config |
overrides |
MappingProxyType[str, Any] |
The specific overrides for this run |
instance |
T |
The instantiated object (property) |
Notes:
instanceis a property that raises any stored error when accessed- Use try/except for graceful error handling per run
Examples:
for result in rc.instantiate_multirun(...):
# Fail fast - raises if this run failed
train(result.instance)
# Or handle errors individually
try:
train(result.instance)
except (ValidationError, InstantiationError) as e:
log_failure(result.overrides, e)
MultirunIterator¶
Lazy iterator with length and slicing support for multirun results. Enables efficient iteration with progress tracking.
Methods:
| Method | Returns | Description |
|---|---|---|
__len__() |
int |
Total number of runs |
__iter__() |
MultirunIterator[T] |
Fresh iterator from beginning |
__reversed__() |
MultirunIterator[T] |
Iterator in reverse order |
__getitem__(i) |
MultirunResult[T] |
Access single run by index |
__getitem__(s) |
MultirunIterator[T] |
Slice to get subset iterator |
Examples:
results = rc.instantiate_multirun(...)
# Progress tracking with tqdm
for result in tqdm(results):
train(result.instance)
# Resume from crash point
for result in results[50:]:
train(result.instance)
# Distribute across workers
worker1_results = results[0:25]
worker2_results = results[25:50]
# Debug specific run
single_result = results[3]
MULTIRUN_HELP¶
Help text constant for multirun CLI options. Use this to include multirun documentation in your CLI help.
Type: str
Example:
import argparse
from rconfig import MULTIRUN_HELP
parser = argparse.ArgumentParser(
epilog=MULTIRUN_HELP,
formatter_class=argparse.RawDescriptionHelpFormatter
)
MultirunError¶
Base exception for multirun-related errors.
InvalidSweepValueError¶
Raised when sweep values are not lists.
NoRunConfigurationError¶
Raised when neither sweep nor experiments is provided to instantiate_multirun().
Help Integration Classes¶
HelpIntegration¶
Abstract base class for CLI help integrations. Subclass this to customize how config help is integrated into CLI.
Constructor:
| Parameter | Type | Default | Description |
|---|---|---|---|
consume_help_flag |
bool |
True |
If True, remove --help/-h from sys.argv. |
Abstract Methods:
| Method | Description |
|---|---|
integrate(provenance, config_path) |
Called when --help/-h is detected. |
Examples:
from rconfig import HelpIntegration
class CustomHelpIntegration(HelpIntegration):
def integrate(self, provenance, config_path):
print(f"Custom help for {config_path}")
for path, entry in provenance.items():
print(f" {path}: {entry.value}")
sys.exit(0)
rc.set_help_integration(CustomHelpIntegration())
FlatHelpIntegration¶
Displays config entries as a flat aligned table. This is the default integration.
Constructor:
| Parameter | Type | Default | Description |
|---|---|---|---|
output |
TextIO \| None |
sys.stdout |
Output stream. |
Output format:
Configuration options for config.yaml
=====================================
model.lr float 0.001 Learning rate
model.hidden_size int 256 Hidden layer size
data.path str (required) Path to data
GroupedHelpIntegration¶
Displays config entries grouped by top-level key with indentation.
Constructor:
| Parameter | Type | Default | Description |
|---|---|---|---|
output |
TextIO \| None |
sys.stdout |
Output stream. |
Output format:
Configuration options for config.yaml
=====================================
model:
lr float 0.001 Learning rate
hidden_size int 256 Hidden layer size
data:
path str (required) Path to data
Examples:
ArgparseHelpIntegration¶
Integrates config entries into argparse help output. Adds config entries to the parser's epilog.
Constructor:
| Parameter | Type | Default | Description |
|---|---|---|---|
parser |
argparse.ArgumentParser |
required | The argparse parser to integrate. |
Notes:
- Uses
consume_help_flag=Falsebecause argparse handles --help itself
Examples:
import argparse
from rconfig import ArgparseHelpIntegration
parser = argparse.ArgumentParser()
parser.add_argument("--verbose", action="store_true")
rc.set_help_integration(ArgparseHelpIntegration(parser))
args = parser.parse_args()
config = rc.instantiate(Path("config.yaml"))
Exporter Registry¶
rc.register_exporter(exporter, *extensions)¶
Register an exporter for specific file extensions.
Parameters:
| Parameter | Type | Default | Description |
|---|---|---|---|
exporter |
Exporter |
required | Exporter instance to register. |
*extensions |
str |
required | Extensions to register (e.g., ".xml", ".protobuf"). |
Returns: None
Examples:
class XmlExporter(Exporter):
def export(self, config: dict) -> str:
return dict_to_xml(config)
rc.register_exporter(XmlExporter(), ".xml")
rc.unregister_exporter(extension)¶
Unregister an exporter by extension.
Parameters:
| Parameter | Type | Default | Description |
|---|---|---|---|
extension |
str |
required | The extension to unregister. |
Returns: None
Raises:
| Exception | Condition |
|---|---|
KeyError |
Extension not registered |
Examples:
rc.get_exporter(path)¶
Get the appropriate exporter for a config file based on its extension.
Parameters:
| Parameter | Type | Default | Description |
|---|---|---|---|
path |
StrOrPath |
required | Path to the config file. Accepts str, Path, or any os.PathLike. |
Returns: Exporter - An exporter instance for the file format
Raises:
| Exception | Condition |
|---|---|
ConfigFileError |
If no exporter supports the file format. |
Examples:
rc.supported_exporter_extensions()¶
Get all supported export file extensions.
Parameters: None
Returns: frozenset[str] - Supported extensions (lowercase, e.g., {'.yaml', '.json', '.toml'})
Examples:
Exporter Classes¶
Exporter¶
Abstract base class for config exporters. Subclass this to create custom exporters.
Abstract Methods:
| Method | Returns | Description |
|---|---|---|
export(config: dict) |
Any |
Export config to the target format |
Examples:
from rconfig import Exporter
class XmlExporter(Exporter):
def export(self, config: dict) -> str:
return dict_to_xml(config)
rc.register_exporter(XmlExporter(), ".xml")
YamlExporter¶
Export config as a YAML string.
Constructor:
| Parameter | Type | Default | Description |
|---|---|---|---|
default_flow_style |
bool \| None |
False |
None=block, True=flow, False=mixed |
indent |
int |
2 |
Indentation spaces |
exclude_markers |
bool |
False |
Remove internal markers |
markers |
tuple[str, ...] |
(default) | Marker keys to exclude |
JsonExporter¶
Export config as a JSON string.
Constructor:
| Parameter | Type | Default | Description |
|---|---|---|---|
indent |
int \| None |
2 |
Indentation (None for compact) |
ensure_ascii |
bool |
False |
Escape non-ASCII characters |
sort_keys |
bool |
False |
Sort dictionary keys |
exclude_markers |
bool |
False |
Remove internal markers |
markers |
tuple[str, ...] |
(default) | Marker keys to exclude |
TomlExporter¶
Export config as a TOML string.
Constructor:
| Parameter | Type | Default | Description |
|---|---|---|---|
multiline_strings |
bool |
False |
Use multiline for strings |
exclude_markers |
bool |
False |
Remove internal markers |
markers |
tuple[str, ...] |
(default) | Marker keys to exclude |
DictExporter¶
Export config as a Python dictionary. This is the base exporter used internally.
FileExporter¶
Base class for file-based exporters. Subclass this to create exporters that write to files.
SingleFileExporter¶
Export config to a single file. Used by rc.to_file().
MultiFileExporter¶
Export config preserving _ref_ structure across multiple files. Used by rc.to_files().
Loader Registry¶
rc.register_loader(loader, *extensions)¶
Register a config file loader for specific extensions.
Parameters:
| Parameter | Type | Default | Description |
|---|---|---|---|
loader |
ConfigFileLoader |
required | A ConfigFileLoader instance to register. |
*extensions |
str |
required | Extensions to register (e.g., ".ini", ".conf"). |
Returns: None
Examples:
class IniConfigLoader(ConfigFileLoader):
def load(self, path: Path) -> dict[str, Any]:
import configparser
parser = configparser.ConfigParser()
parser.read(path)
return {s: dict(parser[s]) for s in parser.sections()}
def load_with_positions(self, path: Path) -> PositionMap:
return PositionMap(self.load(path))
rc.register_loader(IniConfigLoader(), ".ini")
rc.unregister_loader(extension)¶
Unregister a config file loader by extension.
Parameters:
| Parameter | Type | Default | Description |
|---|---|---|---|
extension |
str |
required | The extension to unregister. |
Returns: None
Raises:
| Exception | Condition |
|---|---|
KeyError |
Extension not registered |
Examples:
rc.get_loader(path)¶
Get the appropriate loader for a config file based on its extension.
Parameters:
| Parameter | Type | Default | Description |
|---|---|---|---|
path |
StrOrPath |
required | Path to the config file. Accepts str, Path, or any os.PathLike. |
Returns: ConfigFileLoader - A loader instance for the file format
Raises:
| Exception | Condition |
|---|---|
ConfigFileError |
If no loader supports the file format. |
Examples:
rc.supported_loader_extensions()¶
Get all supported loader file extensions.
Parameters: None
Returns: frozenset[str] - Supported extensions (lowercase, e.g., {'.yaml', '.yml', '.json', '.toml'})
Examples:
Loader Classes¶
ConfigFileLoader¶
Abstract base class for config file loaders. Subclass this to support additional file formats.
Abstract Methods:
| Method | Returns | Description |
|---|---|---|
load(path: Path) |
dict |
Load config as dictionary |
load_with_positions(path) |
PositionMap |
Load with line/column position info |
Examples:
from rconfig import ConfigFileLoader
class IniConfigLoader(ConfigFileLoader):
def load(self, path: Path) -> dict:
import configparser
parser = configparser.ConfigParser()
parser.read(path)
return {s: dict(parser[s]) for s in parser.sections()}
def load_with_positions(self, path: Path) -> PositionMap:
return PositionMap(self.load(path))
rc.register_loader(IniConfigLoader(), ".ini")
YamlConfigLoader¶
Load YAML config files using ruamel.yaml.
Supported Extensions: .yaml, .yml
JsonConfigLoader¶
Load JSON config files using Python's standard library.
Supported Extensions: .json
TomlConfigLoader¶
Load TOML config files using Python 3.11+ tomllib.
Supported Extensions: .toml
Deprecation Classes¶
DeprecationInfo¶
Information about a deprecated key.
Attributes:
| Attribute | Type | Description |
|---|---|---|
old_key |
str |
The deprecated key path |
new_key |
str \| None |
Migration target (if any) |
message |
str \| None |
Custom deprecation message |
remove_in |
str \| None |
Version when key will be removed |
policy |
str \| None |
Override policy (warn/error/ignore) |
DeprecationHandler¶
Abstract base class for custom deprecation warning handlers.
Abstract Methods:
| Method | Description |
|---|---|
handle(info, path, file, line) |
Called when deprecated key used |
Examples:
from rconfig import DeprecationHandler, DeprecationInfo
class LoggingHandler(DeprecationHandler):
def handle(self, info: DeprecationInfo, path: str, file: str, line: int) -> None:
import logging
logging.warning(f"Deprecated key '{path}' at {file}:{line}")
rc.set_deprecation_handler(LoggingHandler())
DeprecatedKeyError¶
Exception raised when a deprecated key is used and the deprecation policy is set to "error".
RconfigDeprecationWarning¶
Warning class used by the default deprecation handler. Integrates with Python's warnings filter system.
Hook Classes¶
rc.Callback¶
Base class for class-based hooks that can maintain state across hook invocations.
Methods to Override:
| Method | Phase | Description |
|---|---|---|
on_config_loaded(ctx) |
CONFIG_LOADED | Called after config composition |
on_before_instantiate(ctx) |
BEFORE_INSTANTIATE | Called before each constructor |
on_after_instantiate(ctx) |
AFTER_INSTANTIATE | Called after each constructor |
on_error(ctx) |
ON_ERROR | Called when instantiation fails |
Examples:
class ExperimentTracker(rc.Callback):
def __init__(self, tracking_uri: str):
self.tracking_uri = tracking_uri
self.run_id = None
def on_config_loaded(self, ctx: HookContext) -> None:
self.run_id = start_run(self.tracking_uri)
log_config(self.run_id, dict(ctx.config))
def on_after_instantiate(self, ctx: HookContext) -> None:
log_component(self.run_id, ctx.target_name, ctx.instance)
def on_error(self, ctx: HookContext) -> None:
mark_failed(self.run_id, str(ctx.error))
tracker = ExperimentTracker("http://mlflow.internal")
rc.register_callback(tracker)
HookPhase¶
Enum defining the lifecycle phases where hooks can be registered.
Values:
| Value | Description |
|---|---|
CONFIG_LOADED |
After config composition, before instantiation |
BEFORE_INSTANTIATE |
Before each object's constructor call |
AFTER_INSTANTIATE |
After each object's constructor returns |
ON_ERROR |
When instantiation fails with an exception |
HookContext¶
Immutable context object passed to hook functions.
Attributes:
| Attribute | Type | Available In | Description |
|---|---|---|---|
phase |
HookPhase |
All | Current lifecycle phase |
config_path |
str |
All | Path to the config file |
config |
MappingProxyType or None |
All | Read-only view of config dict |
inner_path |
str \| None |
BEFORE/AFTER_INSTANTIATE | Path within config |
target_name |
str \| None |
BEFORE/AFTER_INSTANTIATE | The _target_ name |
instance |
Any \| None |
AFTER_INSTANTIATE | The instantiated object |
error |
Exception \| None |
ON_ERROR | The exception that occurred |
HookEntry¶
Immutable dataclass representing a registered hook.
Attributes:
| Attribute | Type | Description |
|---|---|---|
name |
str |
Hook identifier |
phase |
HookPhase |
Lifecycle phase |
func |
Callable |
The hook function |
pattern |
str \| None |
Glob pattern for conditional execution |
priority |
int |
Execution order (lower runs first) |
HookError¶
Base exception for hook-related errors.
HookExecutionError¶
Exception raised when a hook function raises an error during execution.
Attributes:
| Attribute | Type | Description |
|---|---|---|
hook_name |
str |
Name of the failing hook |
phase |
HookPhase |
Phase when error occurred |
original_error |
Exception |
The original exception |