Config

Main Configuration Class

class varlord.config.Config(model, sources, policy=None, show_source_help=True)[source]

Bases: object

Main configuration manager.

Provides a unified interface for loading configuration from multiple sources with customizable priority ordering.

Example

>>> @dataclass
... class AppConfig:
...     host: str = "127.0.0.1"
...     port: int = 8000
...
>>> cfg = Config(
...     model=AppConfig,
...     sources=[
...         sources.Defaults(model=AppConfig),
...         sources.Env(prefix="APP_"),
...         sources.CLI(),  # Model auto-injected
...     ],
... )
>>> config = cfg.load()
>>> print(config.host)
__init__(model, sources, policy=None, show_source_help=True)[source]

Initialize Config.

Parameters:
  • model (type[Any]) – Dataclass model for configuration

  • sources (list[Source]) – List of configuration sources (order determines priority: later sources override earlier ones)

  • policy (PriorityPolicy | None) – Optional PriorityPolicy for per-key priority rules

  • show_source_help (bool) – Whether to show source mapping help in errors (default: True)

Raises:

varlord.exceptions.ModelDefinitionError – If any field is missing required/optional metadata

Note

  • Priority is determined by sources order: later sources override earlier ones

  • Use PriorityPolicy only when you need per-key priority rules

  • Model defaults are automatically applied as base layer (no need for Defaults source)

  • Model is automatically injected to all sources (no need to pass model to sources)

  • All fields MUST have explicit required/optional metadata

classmethod from_model(model, cli=True, dotenv='.env', etcd=None, policy=None)[source]

Create Config with common sources (convenience method).

Parameters:
  • model (type[Any]) – Dataclass model for configuration

  • cli (bool) – Whether to include CLI source

  • dotenv (str | None) – Path to .env file (None to disable)

  • etcd (dict | None) – Etcd configuration dict with keys: host, port, prefix, watch

  • policy (PriorityPolicy | None) – Optional PriorityPolicy for per-key priority rules

Returns:

Config instance

Return type:

Config

Note

  • Model defaults are automatically applied as base layer

  • Source priority order: Defaults (auto) < DotEnv < Env < Etcd < CLI

  • All sources are filtered by model fields

  • All fields MUST have explicit required/optional metadata

Example

>>> from dataclasses import dataclass, field
>>> @dataclass
... class AppConfig:
...     host: str = field(default="127.0.0.1", )
...     port: int = field(default=8000, )
>>> cfg = Config.from_model(
...     AppConfig,
...     cli=True,
...     dotenv=".env",
... )
validate(config_dict=None)[source]

Validate configuration.

Parameters:

config_dict (dict[str, Any] | None) – Optional configuration dict to validate. If None, loads and validates current configuration.

Raises:

varlord.exceptions.RequiredFieldError – If required fields are missing.

handle_cli_commands()[source]

Handle CLI commands (–help/-h and –check-variables/-cv) using current config.

This method processes basic CLI commands based on the current configuration. It should be called once at program startup, before calling load(). It handles CLI commands and exits if necessary: - –help/-h: Shows help with source priority and mapping rules, then exits with code 0 - –check-variables/-cv: Shows diagnostic table and exits with code 1 if required fields are missing

Note

This method uses the current Config’s sources and model to generate help information. It is designed to be called once at startup. After this method returns (without exiting), you can safely call load() to get the configuration.

load(validate=True)[source]

Load configuration with automatic defaults and optional validation.

Parameters:

validate (bool) – Whether to validate required fields (default: True)

Returns:

Model instance with configuration loaded from all sources.

Raises:

varlord.exceptions.RequiredFieldError – If required fields are missing and validate=True.

Return type:

Any

Note

This method loads configuration once. For dynamic updates, use load_store() instead.

For handling CLI commands (–help, –check-variables), call handle_cli_commands() first.

load_store()[source]

Load configuration store (supports dynamic updates).

Automatically enables watch if any source supports it.

Returns:

ConfigStore instance for runtime configuration management.

Return type:

ConfigStore

Note

ConfigStore will use the same defaults + sources logic.

format_cli_help(prog=None)[source]

Generate CLI help text from model fields with source priority and mapping rules.

This method finds the CLI source and generates help text without using argparse’s built-in help, giving varlord complete control. It also includes source priority information and mapping rules.

Parameters:

prog (str | None) – Program name (default: script name from sys.argv[0])

Returns:

Formatted help text string, or empty string if no CLI source found

Return type:

str

format_diagnostic_table()[source]

Generate diagnostic table showing all variables and their status.

Returns:

  • Variable name

  • Required/Optional status

  • Load status (Loaded/Using Default/Missing)

  • Source (defaults/env/cli/dotenv/etc)

  • Value (if loaded)

Return type:

Formatted ASCII table string showing

handle_cli_flags(exit_on_help=True, exit_on_check_variables=False, prog=None)[source]

Handle CLI flags (–help/-h and –check-variables/-cv).

Parameters:
  • exit_on_help (bool) – If True, exit after showing help (default: True)

  • exit_on_check_variables (bool) – If True, exit after showing diagnostic table (default: False)

  • prog (str | None) – Program name for help text (default: script name from sys.argv[0])

Returns:

Tuple of (help_shown, check_variables_shown)

Return type:

tuple[bool, bool]

Note

This method checks sys.argv for –help/-h and –check-variables/-cv flags. If help is shown and exit_on_help=True, the program will exit. If check_variables is shown and exit_on_check_variables=True, the program will exit.

get_field_info()[source]

Get information about all fields in the model.

Returns:

List of FieldInfo objects for all fields (including nested)

Return type:

list[Any]

to_dict(validate=True)[source]

Get current configuration as dictionary.

Parameters:

validate (bool) – Whether to validate required fields (default: True)

Returns:

Dictionary representation of the current configuration

Return type:

dict[str, Any]

Example

>>> cfg = Config(model=AppConfig, sources=[...])
>>> config_dict = cfg.to_dict()
>>> print(config_dict["host"])
dump_json(file_path, validate=True, indent=2)[source]

Export current configuration to JSON file.

Parameters:
  • file_path (str | Path) – Path to output JSON file

  • validate (bool) – Whether to validate required fields before export (default: True)

  • indent (int) – JSON indentation (default: 2)

Example

>>> cfg = Config(model=AppConfig, sources=[...])
>>> cfg.dump_json("config.json")
dump_yaml(file_path, validate=True, default_flow_style=False)[source]

Export current configuration to YAML file.

Parameters:
  • file_path (str | Path) – Path to output YAML file

  • validate (bool) – Whether to validate required fields before export (default: True)

  • default_flow_style (bool) – Use flow style (default: False, uses block style)

Example

>>> cfg = Config(model=AppConfig, sources=[...])
>>> cfg.dump_yaml("config.yaml")
Raises:

ImportError – If PyYAML is not installed

dump_toml(file_path, validate=True)[source]

Export current configuration to TOML file.

Parameters:
  • file_path (str | Path) – Path to output TOML file

  • validate (bool) – Whether to validate required fields before export (default: True)

Example

>>> cfg = Config(model=AppConfig, sources=[...])
>>> cfg.dump_toml("config.toml")
Raises:

ImportError – If tomli-w is not installed

dump_env(file_path, validate=True, prefix='', uppercase=True, nested_separator='__')[source]

Export current configuration to .env file.

Parameters:
  • file_path (str | Path) – Path to output .env file

  • validate (bool) – Whether to validate required fields before export (default: True)

  • prefix (str) – Optional prefix for all environment variable names (e.g., APP_)

  • uppercase (bool) – Convert keys to uppercase (default: True)

  • nested_separator (str) – Separator for nested keys (default: “__”)

Example

>>> cfg = Config(model=AppConfig, sources=[...])
>>> cfg.dump_env(".env", prefix="APP_")
# Creates: APP_HOST=localhost
#          APP_PORT=8000
__repr__()[source]

Return string representation.

Helper Methods (Internal)

Note

These methods are used internally by the Config class. They are documented here for advanced users who want to understand the implementation or extend the functionality.

Config._unwrap_optional_type(field_type)[source]

Unwrap Optional[T] to get T.

For Union[T, None] types, returns T. For other types, returns the original type.

Parameters:

field_type (type) – Field type to unwrap

Returns:

The non-None type from Optional[T], or the original type

Return type:

type

Example

>>> self._unwrap_optional_type(Optional[str])
<class 'str'>
>>> self._unwrap_optional_type(str)
<class 'str'>
Config._process_dataclass_instances(flat_dict)[source]

Convert all dataclass instances in flat_dict to dicts.

Parameters:

flat_dict (dict[str, Any]) – Dictionary that may contain dataclass instances as values

Returns:

Dictionary with all dataclass instances converted to dicts

Return type:

dict[str, Any]

Config._process_flat_keys(flat_dict, field_info, result)[source]

Process non-nested (flat) keys with type conversion.

Parameters:
  • flat_dict (dict[str, Any]) – Processed flat dictionary

  • field_info (dict) – Dictionary mapping field names to field objects

  • result (dict[str, Any]) – Result dictionary to populate

Config._collect_nested_keys(flat_dict, field_info)[source]

Collect all nested keys grouped by parent key.

Parameters:
  • flat_dict (dict[str, Any]) – Processed flat dictionary

  • field_info (dict) – Dictionary mapping field names to field objects

Returns:

Dictionary mapping parent keys to their nested key-value pairs

Return type:

dict[str, dict[str, Any]]

Config._process_nested_keys(nested_collections, field_info, result)[source]

Process collected nested structures recursively.

Parameters:
  • nested_collections (dict[str, dict[str, Any]]) – Nested keys grouped by parent key

  • field_info (dict) – Dictionary mapping field names to field objects

  • result (dict[str, Any]) – Result dictionary to populate

Config._convert_to_dataclasses(result, field_info)[source]

Convert nested dicts to dataclass instances with type conversion.

Parameters:
  • result (dict[str, Any]) – Result dictionary with nested dicts

  • field_info (dict) – Dictionary mapping field names to field objects

Config._flatten_to_nested(flat_dict, model)[source]

Convert flat dict with dot notation to nested structure.

Example

{“db.host”: “localhost”, “db.port”: 5432, “host”: “0.0.0.0”} → {“db”: {“host”: “localhost”, “port”: 5432}, “host”: “0.0.0.0”}

Parameters:
  • flat_dict (dict[str, Any]) – Flat dictionary with dot-notation keys

  • model (type) – Dataclass model to map to

Returns:

Nested dictionary matching the model structure

Return type:

dict[str, Any]

Usage Examples

Basic Usage

from dataclasses import dataclass, field
from varlord import Config, sources

@dataclass(frozen=True)
class AppConfig:
    host: str = field(default="localhost")
    port: int = field(default=8000)
    debug: bool = field(default=False)

# Load configuration from environment variables
cfg = Config(model=AppConfig, sources=[sources.Env()])
config = cfg.load()

print(config.host, config.port, config.debug)

Multiple Sources with Priority

# Load from multiple sources (later sources override earlier ones)
cfg = Config(
    model=AppConfig,
    sources=[
        sources.Env(),        # Priority 1
        sources.DotEnv(),      # Priority 2
        sources.CLI(),         # Priority 3 (highest)
    ],
)

Warning

Pitfall: Source order matters! Later sources override earlier ones. If PORT is set in both environment variables and CLI, the CLI value wins.

With Validation

cfg = Config(model=AppConfig, sources=[sources.Env()])
config = cfg.load(validate=True)

Note

Best Practice: Always validate configuration in production to catch errors early.