Files
2026-08-08 11:24:44 +03:00

3.2 KiB

name, description
name description
python-development-settings Application configuration and settings management. Use when defining, loading, validating, or extending application settings.

Rules

  • The root settings class must inherit from pydantic_settings.BaseSettings. This enables automatic loading from environment variables and .env files.
  • Every nested settings class (for individual services, adapters, or components) must inherit from pydantic.BaseModel, not from BaseSettings. Only the root class needs the env-loading behavior.
  • The root settings class exposes one field per top-level service or subsystem. Provide sensible defaults as plain values for immutable types (str, int, bool, None) and use Field(default_factory=...) only when the default is a mutable object (dict, list, or model instance). Never use mutable literals as class-attribute defaults in Pydantic v2. Provide defaults so the application starts without a config file when reasonable.
  • A settings class can accept either a settings object or a string key referencing another entry in the same config. The resolver (or a @model_validator) replaces string references with resolved instances after initial parsing. This is how services declare their dependencies declaratively.
  • Use @model_validator(mode="after") on the root settings class to validate cross-references between subsystems, resolve string keys to actual instances, and enforce consistency across the configuration graph.
  • Support loading from YAML config files with custom tags. Register !include for file inclusion and !env for environment variable interpolation inside YAML. The YAML loader builder must live as a @staticmethod inside the root settings class. Example:
    @staticmethod
    def get_yaml_loader(base_path: pathlib.Path) -> yaml.BaseLoader:
        loader = type("Loader", (yaml.SafeLoader,), {})
        loader.add_constructor(
            "!include",
            yaml_include.Constructor(base_dir=str(base_path)),
        )
        loader.add_constructor("!env", construct_env_tag)
        return loader
    
  • Support loading from JSON config files using standard json.load. JSON does not support custom tags; use string interpolation or env var resolution handled by BaseSettings after load.
  • Provide a single load() classmethod on the root settings class that reads the config file (YAML or JSON), then passes the parsed dict into the BaseSettings constructor along with optional _env_prefix and _env_file. Example:
    @classmethod
    def load(cls, config_file: pathlib.Path | None = None) -> Self:
        data = {}
        if config_file is not None:
            if config_file.suffix in (".yaml", ".yml"):
                data.update(yaml.load(config_file.read_text(), Loader=get_loader()))
            elif config_file.suffix == ".json":
                data.update(json.loads(config_file.read_text()))
        return cls(**data)
    
  • Keep each subsystem's settings in its own settings.py module inside the subsystem package. Import and compose them into the root settings class. Do not inline subsystem schemas into the root file.
  • Use pydantic.Field(default_factory=...) for mutable default values (dicts, lists, models). Never use mutable literals as class-attribute defaults in Pydantic v2.