Skip to content

Loader

provide.foundation.config.loader

TODO: Add module docstring.

Classes

ChainedLoader

ChainedLoader(*loaders: ConfigLoader)

Bases: ConfigLoader

Try multiple loaders until one succeeds.

Initialize chained configuration loader.

Parameters:

Name Type Description Default
*loaders ConfigLoader

Configuration loaders to try in order

()
Source code in provide/foundation/config/loader.py
def __init__(self, *loaders: ConfigLoader) -> None:
    """Initialize chained configuration loader.

    Args:
        *loaders: Configuration loaders to try in order

    """
    self.loaders = loaders
Functions
exists
exists() -> bool

Check if any configuration source exists.

Source code in provide/foundation/config/loader.py
def exists(self) -> bool:
    """Check if any configuration source exists."""
    return any(loader.exists() for loader in self.loaders)
load
load(config_class: type[T]) -> T

Load configuration from first available source.

Source code in provide/foundation/config/loader.py
def load(self, config_class: type[T]) -> T:
    """Load configuration from first available source."""
    for loader in self.loaders:
        if loader.exists():
            return loader.load(config_class)

    raise ValueError("No configuration source available")

ConfigLoader

Bases: ABC

Abstract base class for configuration loaders.

Built-in implementations: - FileConfigLoader: YAML, JSON, TOML, .env files - RuntimeConfigLoader: Environment variables - DictConfigLoader: In-memory dictionaries

For cloud secret managers (Vault, AWS Secrets, Azure Key Vault), implement custom loaders following this protocol.

Examples: docs/guide/advanced/integration-patterns.md#custom-configuration-sources

Functions
exists abstractmethod
exists() -> bool

Check if the configuration source exists.

Returns:

Type Description
bool

True if source exists

Source code in provide/foundation/config/loader.py
@abstractmethod
def exists(self) -> bool:
    """Check if the configuration source exists.

    Returns:
        True if source exists

    """
load abstractmethod
load(config_class: type[T]) -> T

Load configuration.

Parameters:

Name Type Description Default
config_class type[T]

Configuration class to instantiate

required

Returns:

Type Description
T

Configuration instance

Source code in provide/foundation/config/loader.py
@abstractmethod
def load(self, config_class: type[T]) -> T:
    """Load configuration.

    Args:
        config_class: Configuration class to instantiate

    Returns:
        Configuration instance

    """

DictConfigLoader

DictConfigLoader(
    data: ConfigDict,
    source: ConfigSource = ConfigSource.RUNTIME,
)

Bases: ConfigLoader

Load configuration from a dictionary.

Initialize dictionary configuration loader.

Parameters:

Name Type Description Default
data ConfigDict

Configuration data

required
source ConfigSource

Source of the configuration

RUNTIME
Source code in provide/foundation/config/loader.py
def __init__(self, data: ConfigDict, source: ConfigSource = ConfigSource.RUNTIME) -> None:
    """Initialize dictionary configuration loader.

    Args:
        data: Configuration data
        source: Source of the configuration

    """
    self.data = data
    self.source = source
Functions
exists
exists() -> bool

Check if configuration data exists.

Source code in provide/foundation/config/loader.py
def exists(self) -> bool:
    """Check if configuration data exists."""
    return self.data is not None
load
load(config_class: type[T]) -> T

Load configuration from dictionary.

Source code in provide/foundation/config/loader.py
def load(self, config_class: type[T]) -> T:
    """Load configuration from dictionary."""
    return config_class.from_dict(self.data, source=self.source)

FileConfigLoader

FileConfigLoader(
    path: str | Path,
    format: ConfigFormat | None = None,
    encoding: str = "utf-8",
)

Bases: ConfigLoader

Load configuration from files.

Initialize file configuration loader.

Parameters:

Name Type Description Default
path str | Path

Path to configuration file

required
format ConfigFormat | None

File format (auto-detected if None)

None
encoding str

File encoding

'utf-8'
Source code in provide/foundation/config/loader.py
def __init__(
    self,
    path: str | Path,
    format: ConfigFormat | None = None,
    encoding: str = "utf-8",
) -> None:
    """Initialize file configuration loader.

    Args:
        path: Path to configuration file
        format: File format (auto-detected if None)
        encoding: File encoding

    """
    self.path = Path(path)
    self.encoding = encoding

    if format is None:
        format = ConfigFormat.from_extension(str(self.path))
        if format is None:
            raise ConfigurationError(
                f"Cannot determine format for file: {self.path}",
                code="CONFIG_FORMAT_UNKNOWN",
                path=str(self.path),
            )

    self.format = format
Functions
exists
exists() -> bool

Check if configuration file exists.

Source code in provide/foundation/config/loader.py
def exists(self) -> bool:
    """Check if configuration file exists."""
    return self.path.exists()
load
load(config_class: type[T]) -> T

Load configuration from file.

Source code in provide/foundation/config/loader.py
@resilient(
    context_provider=lambda: {"loader": FileConfigLoader},
    error_mapper=lambda e: ConfigurationError(
        f"Failed to load configuration: {e}",
        code="CONFIG_LOAD_ERROR",
        cause=e,
    )
    if not isinstance(e, ConfigurationError | NotFoundError)
    else e,
)
def load(self, config_class: type[T]) -> T:
    """Load configuration from file."""
    from provide.foundation.logger.setup.coordinator import (
        create_foundation_internal_logger,
    )
    from provide.foundation.utils.timing import timed_block

    setup_logger = create_foundation_internal_logger()

    with timed_block(setup_logger, f"Load config from {self.path.name}"):
        if not self.exists():
            raise NotFoundError(
                f"Configuration file not found: {self.path}",
                code="CONFIG_FILE_NOT_FOUND",
                path=str(self.path),
            )

        data = self._read_file()
        return config_class.from_dict(data, source=ConfigSource.FILE)

MultiSourceLoader

MultiSourceLoader(*loaders: ConfigLoader)

Bases: ConfigLoader

Load configuration from multiple sources with precedence.

Initialize multi-source configuration loader.

Parameters:

Name Type Description Default
*loaders ConfigLoader

Configuration loaders in order of precedence (later overrides earlier)

()
Source code in provide/foundation/config/loader.py
def __init__(self, *loaders: ConfigLoader) -> None:
    """Initialize multi-source configuration loader.

    Args:
        *loaders: Configuration loaders in order of precedence (later overrides earlier)

    """
    self.loaders = loaders
Functions
exists
exists() -> bool

Check if any configuration source exists.

Source code in provide/foundation/config/loader.py
def exists(self) -> bool:
    """Check if any configuration source exists."""
    return any(loader.exists() for loader in self.loaders)
load
load(config_class: type[T]) -> T

Load and merge configuration from multiple sources.

Source code in provide/foundation/config/loader.py
def load(self, config_class: type[T]) -> T:
    """Load and merge configuration from multiple sources."""
    if not self.exists():
        raise ValueError("No configuration sources available")

    config = None

    for loader in self.loaders:
        if loader.exists():
            if config is None:
                config = loader.load(config_class)
            else:
                # Load and merge
                new_config = loader.load(config_class)
                new_dict = new_config.to_dict(include_sensitive=True)
                # Update each field with its proper source
                for key, value in new_dict.items():
                    source = new_config.get_source(key)
                    if source is not None:
                        config.update({key: value}, source=source)

    if config is None:
        raise ValueError("Failed to load configuration from any source")
    return config

RuntimeConfigLoader

RuntimeConfigLoader(
    prefix: str = "",
    delimiter: str = "_",
    case_sensitive: bool = False,
)

Bases: ConfigLoader

Load configuration from environment variables.

Initialize environment configuration loader.

Parameters:

Name Type Description Default
prefix str

Prefix for environment variables

''
delimiter str

Delimiter between prefix and field name

'_'
case_sensitive bool

Whether variable names are case-sensitive

False
Source code in provide/foundation/config/loader.py
def __init__(self, prefix: str = "", delimiter: str = "_", case_sensitive: bool = False) -> None:
    """Initialize environment configuration loader.

    Args:
        prefix: Prefix for environment variables
        delimiter: Delimiter between prefix and field name
        case_sensitive: Whether variable names are case-sensitive

    """
    self.prefix = prefix
    self.delimiter = delimiter
    self.case_sensitive = case_sensitive
Functions
exists
exists() -> bool

Check if any relevant environment variables exist.

Source code in provide/foundation/config/loader.py
def exists(self) -> bool:
    """Check if any relevant environment variables exist."""
    if self.prefix:
        prefix_with_delim = f"{self.prefix}{self.delimiter}"
        return any(key.startswith(prefix_with_delim) for key in os.environ)
    return bool(os.environ)
load
load(config_class: type[T]) -> T

Load configuration from environment variables.

Source code in provide/foundation/config/loader.py
def load(self, config_class: type[T]) -> T:
    """Load configuration from environment variables."""
    if not issubclass(config_class, RuntimeConfig):
        raise TypeError(f"{config_class.__name__} must inherit from RuntimeConfig")

    return config_class.from_env(
        prefix=self.prefix,
        delimiter=self.delimiter,
        case_sensitive=self.case_sensitive,
    )

Functions