API Reference
iConfig Module
Main user interface for hierarchical configuration management.
This module provides the primary iConfig class that serves as the main
entry point for users to interact with hierarchical configuration data. It includes
a sophisticated singleton decorator and the core configuration access interface.
The module combines file-based configuration management with in-memory caching, environment variable expansion, and flexible access patterns. The singleton pattern ensures consistent configuration state across an application while allowing opt-out behavior when needed.
- Key Features:
Conditional singleton pattern with configuration-based control
Hierarchical configuration access with path filtering
Environment variable expansion in configuration values
Lazy loading of configuration files for performance
Type-safe overloaded methods for better IDE support
Example
Basic usage of the iConfig interface:
from iconfig import iConfig
# Initialize configuration (singleton by default)
config = iConfig()
# Get configuration values
app_name = config.get('app_name')
db_port = config.get('port', path=['database'])
# Use with defaults and type hints
timeout = config.get('timeout', default=30)
# Callable interface
debug = config('debug', default=False)
# Set values (in-memory)
config.set('new_setting', value=True)
- Classes:
iConfig: Main configuration interface with singleton support
- Functions:
singleton_or_not: Decorator for conditional singleton behavior
KeyIndex Module
Internal indexing engine for fast hierarchical configuration lookups.
This module provides the KeyIndex class which serves as the core indexing
engine for the iConfig system. It handles file discovery, builds searchable indexes
of configuration keys, and provides fast lookups across multiple YAML files.
The KeyIndex class is designed for performance, building an in-memory index of all configuration keys with metadata about their locations, hierarchy levels, and file sources. This allows for O(1) key lookups without re-parsing configuration files.
Example
Using KeyIndex for configuration management:
from iconfig.keyindex import KeyIndex
# Initialize and build index
ki = KeyIndex()
# Get configuration values with filtering
result = ki.get('port', path=['database'])
# Add new configuration entry
ki.add('new_key', 'value', path=['section'], level=0)
# Save index to disk
ki.save()
- Classes:
KeyIndex: Main indexing engine for hierarchical configuration management.
Note
This is an internal module. End users should typically use the iConfig class which provides a simpler interface wrapping KeyIndex functionality.
- class iconfig.keyindex.KeyIndex(config_home=None, load_index=True, force_rebuild=False)[source]
Bases:
objectCore indexing engine for hierarchical configuration management.
The KeyIndex class provides the internal engine that powers the iConfig system. It discovers configuration files, builds searchable indexes, and provides fast lookups with support for hierarchical filtering by path, level, and depth.
The class maintains three main data structures: -
_index: Maps configuration keys to their metadata and locations -_files: Tracks discovered configuration files and their properties -_cfg: Runtime cache of loaded configuration file contents- Parameters:
load_index (bool, optional) – Whether to automatically load/build the index on initialization. Defaults to True.
Example
Basic KeyIndex operations:
# Initialize with automatic index building ki = KeyIndex() # Search for configuration keys port_entries = ki.get('port') db_port = ki.get('port', path=['database']) # Get metadata about key locations location = ki.whereis('app_name') # Add new configuration entries ki.add('timeout', 30, path=['api'], level=1) # Persist changes ki.save()
Note
The KeyIndex automatically discovers YAML files in the configuration directory and builds/maintains an index for fast lookups. The index is persisted to disk for quick startup times on subsequent runs.
- __init__(config_home=None, load_index=True, force_rebuild=False)[source]
Initialize the KeyIndex with configuration directory and options.
Sets up the internal data structures and optionally loads or builds the configuration index from the specified directory.
- get(key, path=None, level=-1, depth=-1, forcefirst=False, default=None)[source]
Retrieve a configuration value by its key.
Performs fast O(1) lookup of configuration values using the pre-built index. If the key exists in multiple files, returns the value from the file with the highest priority (lowest hierarchy level).
- Parameters:
key (str) – The configuration key to look up.
path (list[str] | str | None) – Optional path filter to narrow search.
level (int) – Filter by hierarchy level (-1 for any level).
depth (int) – Filter by nesting depth (-1 for any depth).
forcefirst (bool) – Return first match instead of highest priority.
default (Any) – Default value if key not found.
- Returns:
The configuration value associated with the key, or default if the key is not found.
- Return type:
Any
Example
>>> index = KeyIndex() >>> value = index.get('database.host') >>> print(value) # 'localhost'
- whereis(key, path=None, level=-1, depth=-1)[source]
Find the file location and metadata for a configuration key.
Returns detailed information about where a configuration key is defined, including the hierarchy level and nesting path. This is useful for debugging configuration issues and understanding the configuration structure.
- Parameters:
- Returns:
A list of dictionaries containing metadata about the key’s locations, each with:
’level’: Hierarchy level (0 for root files)
’path’: The full key path as a list
Returns None if the key is not found.
- Return type:
Example
>>> index = KeyIndex() >>> locations = index.whereis('database.host') >>> print(locations) # [{'level': 0, 'path': ['database', 'host']}]
- add(key, level, depth, dict_ref, path)[source]
Add a configuration key entry to the index.
Adds metadata for a configuration key to the internal index, including its hierarchy level, nesting depth, source file, and path information. This method is typically called during index building.
- Parameters:
key (str) – The configuration key to add.
level (int) – Hierarchy level (0 for root files, higher for subdirectories).
depth (int) – Nesting depth within the configuration structure.
dict_ref (str) – Reference to the source file containing this key.
path (str | list[str]) – The path to this key within the configuration.
- Return type:
Example
>>> index = KeyIndex() >>> index.add('host', 0, 1, 'config/db.yaml', ['database', 'host'])
Labels Module
String constants and labels used throughout the iConfig system.
This module defines the Labels class that provides string constants
used as dictionary keys and identifiers throughout the configuration system.
Using a centralized Labels class ensures consistency and prevents typos in
string literals across the codebase.
The Labels class provides string constants that can be used as dictionary keys and includes utility methods for introspection and iteration over the available labels.
Example
Using Labels for consistent key access:
from iconfig.labels import Labels
# Use labels as dictionary keys
entry = {
Labels.FILE_PATH: '/path/to/config.yaml',
Labels.LEVEL: 0,
Labels.PATH: ['database']
}
# Access values using Labels
file_path = entry[Labels.FILE_PATH]
- The module exports the :class:`Labels` class with all configuration constants.
- class iconfig.labels.Labels[source]
Bases:
objectString constants for configuration system keys and identifiers.
Provides string constants used as dictionary keys and identifiers throughout the iConfig system. The class includes both the constant definitions and utility methods for introspection and iteration.
The Labels class serves as a centralized location for all string constants used in the configuration system, preventing typos and ensuring consistency across the codebase.
Example
Using Labels in configuration entries:
entry = { Labels.FILE_PATH: '/etc/myapp/config.yaml', Labels.LEVEL: 0, Labels.DEPTH: 2, Labels.PATH: ['database', 'connection'], Labels.DICT_REF: 'config_main' } # Access values using Labels path = entry[Labels.FILE_PATH] level = entry[Labels.LEVEL]
Note
This is a regular class (not an enum) that provides string constants and utility methods for working with those constants.
- INDEX = 'index'
- FILES = 'files'
- LEVEL = 'level'
- DEPTH = 'depth'
- DICT_REF = 'dict_ref'
- PATH = 'path'
- FILE_PATH = 'file_path'
- MTIME = 'mtime'
- classmethod values()[source]
Return all label string values as a list.
Collects all string constants defined in the Labels class into a list, excluding methods and special attributes.
Example
>>> Labels.values() ['index', 'files', 'level', 'depth', 'dict_ref', 'path', 'file_path', 'mtime']
- classmethod names()[source]
Return all label constant names as a list.
Collects all attribute names that correspond to string constants, excluding methods and special attributes.
Example
>>> Labels.names() ['INDEX', 'FILES', 'LEVEL', 'DEPTH', 'DICT_REF', 'PATH', 'FILE_PATH', 'MTIME']
- classmethod items()[source]
Return (name, value) pairs for all label constants.
Provides a dictionary-like items() interface for the Labels class, returning tuples of (attribute_name, string_value) for all constants.
Example
>>> Labels.items() [('INDEX', 'index'), ('FILES', 'files'), ('LEVEL', 'level'), ...]
Utils Module
Utility functions for configuration file discovery and key path processing.
This module provides essential utility functions used throughout the iConfig system for file system operations and key path manipulation. These functions support the core functionality of hierarchical configuration management.
The module includes functions for: - Discovering YAML configuration files in directory structures - Processing and normalizing key paths with dot notation support - File metadata collection for change detection
Example
Basic usage of utility functions:
from pathlib import Path
from iconfig.utils import discover_config_files, get_key_path
# Discover configuration files
config_dir = Path("config")
files = discover_config_files(config_dir)
# Process key paths
key, path = get_key_path("database.host", ["production"])
- Functions:
discover_config_files: Recursively find YAML files with metadata get_key_path: Parse and normalize key paths with dot notation
- iconfig.utils.discover_config_files(base_path, pattern='*.yaml')[source]
Recursively discover configuration files with metadata collection.
Scans the specified directory tree for files matching the given pattern and collects metadata including file paths, modification times, and hierarchy levels. This information is used for index building and change detection.
- Parameters:
- Returns:
Dictionary mapping relative file paths to metadata dictionaries containing:
file_path (str): Absolute path to the configuration file
mtime (float): File modification time as timestamp
level (int): Hierarchy level based on directory depth
- Return type:
Example
Discovering configuration files:
config_dir = Path("config") files = discover_config_files(config_dir) # Result structure: # { # "database.yaml": { # "file_path": "/path/to/config/database.yaml", # "mtime": 1699123456.789, # "level": 0 # }, # "api/settings.yaml": { # "file_path": "/path/to/config/api/settings.yaml", # "mtime": 1699123457.123, # "level": 1 # } # }
Note
The hierarchy level is calculated based on directory depth relative to the base path, with 0 representing files in the root directory.
- iconfig.utils.get_key_path(key, path)[source]
Parse and normalize key paths with dot notation support.
Processes configuration keys that may contain dot notation (e.g., “database.host”) and combines them with existing path contexts to create normalized key and path components. This enables flexible key specification and hierarchical access.
- Parameters:
- Returns:
A tuple containing:
key (str): The final key component (rightmost part after dots)
path (list[str]): Combined path context including dot notation parts
- Return type:
Example
Processing keys with dot notation:
# Simple key without dots key, path = get_key_path("host", ["database"]) # Result: ("host", ["database"]) # Key with dot notation key, path = get_key_path("database.host", []) # Result: ("host", ["database"]) # Combining dot notation with existing path key, path = get_key_path("connection.timeout", ["api"]) # Result: ("timeout", ["connection", "api"]) # String path converted to list key, path = get_key_path("port", "database") # Result: ("port", ["database"])
Note
When dot notation is present, the key is split and the rightmost component becomes the key while preceding components are prepended to the path context.
- iconfig.utils.singleton_or_not(class_)[source]
Decorator that conditionally implements the singleton pattern.
Provides a sophisticated singleton implementation that can be controlled through configuration settings. The singleton behavior is determined by a configuration key ‘<class_name>.singleton’ - when True, the class behaves as a singleton; when False, new instances are created each time.
This allows applications to control singleton behavior through configuration without code changes, enabling different patterns for different environments (e.g., singleton in production, new instances in testing).
- Parameters:
class – The class to decorate with conditional singleton behavior.
- Returns:
A wrapper function that manages instance creation according to the singleton configuration setting.
- Return type:
function
Example
Using the conditional singleton decorator:
@singleton_or_not class MyConfig: def __init__(self): pass # Behavior depends on 'myconfig.singleton' configuration: # If True (default): same instance returned # If False: new instance created each time config1 = MyConfig() config2 = MyConfig() # Same or different based on config
Note
The decorator maintains an internal instances dictionary to track singleton objects. The singleton check is performed on each instantiation to allow dynamic behavior changes through configuration updates.