deployment.loader#
Configuration Parameter Loading and Management System.
This module provides a sophisticated parameter loading system that supports YAML configuration files with import directives, hierarchical parameter access, and environment variable expansion. The system is designed for flexible deployment configurations where complex service arrangements need robust parameter management.
The module implements a type-safe parameter access pattern through the Params class, which provides dot-notation access to nested configuration data while maintaining validation and error handling. Invalid parameter access returns InvalidParam objects rather than raising exceptions, enabling graceful degradation in configuration scenarios.
- Key Features:
Recursive YAML file imports with circular dependency detection
Environment variable expansion in string values
Type-safe parameter access with validation
Graceful error handling for missing configuration keys
Deep dictionary merging for configuration composition
Examples
Basic parameter loading:
>>> params = load_params('config.yml')
>>> database_host = params.database.host
>>> timeout = params.services.timeout
Configuration with imports:
# base_config.yml
database:
host: localhost
port: 5432
# app_config.yml
import: base_config.yml
database:
name: myapp # Merged with base config
services:
timeout: 30
>>> params = load_params('app_config.yml')
>>> print(params.database.host) # 'localhost' from base
>>> print(params.database.name) # 'myapp' from app config
Environment variable expansion:
# config.yml
project_root: ${PROJECT_ROOT}
data_dir: ${PROJECT_ROOT}/data
>>> os.environ['PROJECT_ROOT'] = '/home/user/project'
>>> params = load_params('config.yml')
>>> print(params.data_dir) # '/home/user/project/data'
See also
Params
: Main parameter container with hierarchical access
InvalidParam
: Error handling for missing configuration keys
_load_yaml()
: Core YAML loading with import processing
deployment.container_manager
: Uses this system for service configuration
- loader.load_params(file_path)[source]#
Load configuration parameters from YAML file into a Params object.
This is the main entry point for the configuration loading system. It loads a YAML configuration file (processing any import directives) and wraps the resulting data in a Params object that provides type-safe, hierarchical access to configuration values.
The function handles the complete configuration loading pipeline including import processing, environment variable expansion, and parameter object creation. The resulting Params object provides dot-notation access to nested configuration data with built-in validation and error handling.
- Parameters:
file_path (str) – Path to the YAML configuration file to load
- Raises:
FileNotFoundError – If the configuration file cannot be found
yaml.YAMLError – If YAML parsing fails
ValueError – If circular imports are detected
- Returns:
Parameter container with hierarchical access to configuration data
- Return type:
Examples
Basic configuration loading:
# config.yml database: host: localhost port: 5432 services: timeout: 30 retry_count: 3 >>> params = load_params('config.yml') >>> db_host = params.database.host # 'localhost' >>> timeout = params.services.timeout # 30 >>> invalid = params.nonexistent.key # InvalidParam, not exception
Environment variable expansion:
# config.yml project_root: ${PROJECT_ROOT} data_directory: ${PROJECT_ROOT}/data >>> import os >>> os.environ['PROJECT_ROOT'] = '/home/user/project' >>> params = load_params('config.yml') >>> print(params.data_directory) # '/home/user/project/data'
See also
_load_yaml()
: Core YAML loading implementationParams
: Return type providing parameter accessInvalidParam
: Error handling for missing configuration keysdeployment.container_manager
: Primary consumer of this functionality
- class loader.InvalidParam(name, parent=None)[source]#
Bases:
AbstractParam
Parameter object representing missing or invalid configuration data.
This class provides graceful error handling for configuration access patterns where requested parameters don’t exist. Instead of raising exceptions immediately, the system returns InvalidParam objects that maintain the access chain and provide meaningful error messages when finally used.
InvalidParam objects support continued dot-notation access, allowing code to chain parameter lookups naturally even when intermediate parameters are missing. The error is only raised when the parameter is actually used (e.g., in a boolean context or when converted to a string).
This approach enables defensive programming patterns where configuration access can be attempted optimistically, with errors handled at the point of actual use.
- Parameters:
name (str) – Name of the missing parameter
parent (AbstractParam, optional) – Parent parameter object in the access chain
Examples
Graceful error handling:
>>> params = load_params('config.yml') # Missing 'database.timeout' >>> timeout = params.database.timeout # Returns InvalidParam, no exception >>> if timeout: # Now evaluates to False ... print(f"Timeout: {timeout}") ... else: ... print("Using default timeout")
Error chain preservation:
>>> missing = params.nonexistent.deeply.nested.value >>> print(missing) # Shows path to first missing parameter <InvalidParam: 'root.nonexistent'>
See also
Params
: Valid parameter container that returns InvalidParam for missing keysAbstractParam.get_path()
: Path construction used in error messages- is_valid()[source]#
Check if this parameter is valid.
- Returns:
Always False for InvalidParam objects
- Return type:
bool
- __getattr__(key)[source]#
Support continued dot-notation access on invalid parameters.
Allows chaining of parameter access even when intermediate parameters are missing, maintaining the error state through the access chain.
- Parameters:
key (str) – Attribute name being accessed
- Returns:
New InvalidParam representing the continued invalid access
- Return type:
Examples
Continued access on missing parameters:
>>> invalid = params.missing.parameter >>> still_invalid = invalid.more.nested.access >>> print(still_invalid.is_valid()) # False
- __getitem__(key)[source]#
Raise error when bracket notation is used on invalid parameters.
- Parameters:
key (str or int) – Key being accessed
- Raises:
TypeError – Always raises with error message showing the invalid path
Note
Unlike dot notation (__getattr__), bracket notation immediately raises an error to provide clear feedback about the invalid parameter access.
- __bool__()[source]#
Evaluate InvalidParam objects as False in boolean contexts.
- Returns:
Always False
- Return type:
bool
Examples
Boolean evaluation for error handling:
>>> param = params.possibly.missing.value >>> if param: ... process_value(param) ... else: ... use_default_value()
- __repr__()[source]#
Provide clear error message showing the invalid parameter path.
Traces back through the InvalidParam chain to find the first missing parameter and displays its full path for debugging.
- Returns:
String representation showing the invalid parameter path
- Return type:
str
Examples
Error message generation:
>>> missing = params.database.missing.timeout >>> print(missing) <InvalidParam: 'root.database.missing'>
- class loader.Params(data, name, parent=None)[source]#
Bases:
AbstractParam
Primary parameter container providing hierarchical access to configuration data.
This class wraps configuration data (dictionaries, lists, or scalar values) and provides type-safe, hierarchical access through dot notation and bracket notation. The class handles environment variable expansion, supports deep copying, and provides graceful error handling through InvalidParam objects.
Params objects automatically detect the data type (dict, list, or scalar) and provide appropriate access methods. Nested structures are recursively wrapped in Params objects, creating a complete hierarchy that maintains parent-child relationships for path tracking and error reporting.
Environment variable expansion is performed on string values using os.expandvars, allowing configuration files to reference environment variables with ${VAR} syntax.
- Parameters:
data (dict or list or Any) – Configuration data to wrap (dict, list, or scalar value)
name (str) – Name of this parameter within its parent container
parent (AbstractParam, optional) – Parent parameter object, None for root parameters
Examples
Dictionary access patterns:
>>> config_data = {'database': {'host': 'localhost', 'port': 5432}} >>> params = Params(config_data, 'root') >>> host = params.database.host # 'localhost' >>> port = params.database['port'] # 5432 >>> missing = params.cache.timeout # InvalidParam, not exception
List access patterns:
>>> config_data = {'servers': ['web1', 'web2', 'api1']} >>> params = Params(config_data, 'root') >>> first_server = params.servers[0] # 'web1' >>> server_count = len(params.servers) # 3
Environment variable expansion:
>>> config_data = {'path': '${HOME}/data', 'url': '${API_HOST}:${API_PORT}'} >>> params = Params(config_data, 'root') >>> # Environment variables are expanded when values are accessed >>> data_path = params.path # '/home/user/data' (if HOME is set)
See also
InvalidParam
: Error handling for missing configuration keysAbstractParam
: Base class defining the parameter interfaceload_params()
: Main entry point for creating Params from YAML files