Module

config.directory_loader

Directory-based configuration loader (internal helper).

Used bybengal.config.unified_loaderto support directory-style configs (config/_default, config/environments, config/profiles). Prefer importing and usingUnifiedConfigLoader from bengal.config; this module remains as the internal implementation for directory mode.

This module provides a loader for configuration files organized in a directory structure, supporting multi-file configurations with environment-specific and profile-specific overrides.

Directory Structure:

The expected directory layout is::

config/
├── _default/           # Base configuration (multiple YAML files)
│   ├── site.yaml       # Site metadata
│   ├── build.yaml      # Build settings
│   └── theme.yaml      # Theme configuration
├── environments/       # Environment-specific overrides
│   ├── production.yaml
│   ├── preview.yaml
│   └── local.yaml
└── profiles/           # User-defined profiles
    ├── writer.yaml
    └── developer.yaml

Merge Precedence (lowest to highest):

  1. Bengal DEFAULTS fromdefaults.py- Built-in defaults
  2. config/_default/*.yaml- Base configuration
  3. config/environments/<env>.yaml- Environment overrides
  4. config/profiles/<profile>.yaml- Profile settings

Features:

  • Auto-detection of deployment environment (Netlify, Vercel, GitHub Actions)
  • Feature group expansion (e.g.,features.rss: true→ detailed config)
  • Origin tracking for debugging (bengal config show --origin)
  • Automatic environment variable overrides for baseurl

Classes:

ConfigLoadError: Raised when configuration loading fails. ConfigDirectoryLoader: Main loader class for directory-based configuration.

Example:

>>> from bengal.config.directory_loader import ConfigDirectoryLoader
>>> loader = ConfigDirectoryLoader(track_origins=True)
>>> config = loader.load(Path("config"), environment="production")

See Also:

  • bengal.config.unified_loader: Unified loader for all config modes.
  • bengal.config.environment: Environment detection logic.

Classes

ConfigLoadError 5
Raised when configuration loading fails. This exception is raised for various configuration loadin…

Raised when configuration loading fails.

This exception is raised for various configuration loading failures including missing directories, invalid YAML syntax, or file permission errors. ExtendsBengalConfigErrorfor consistent error handling throughout the configuration system.

Attributes

Name Type Description
message

Description of the error.

file_path

Path to the problematic file or directory.

line_number

Line number where the error occurred (if applicable).

suggestion

Helpful suggestion for fixing the error.

original_error

The underlying exception, if any.

ConfigDirectoryLoader 7
Load configuration from a directory structure with layered overrides. This loader supports multi-f…

Load configuration from a directory structure with layered overrides.

This loader supports multi-file configurations organized in directories, with automatic environment detection and profile-based customization. It provides deterministic merging with clear precedence rules.

Features:

  • Multi-file configs: Split configuration across multiple YAML files
    in ``_default/`` for better organization.
    
  • Environment overrides: Automatic detection of deployment environment
    with corresponding configuration overrides.
    
  • Profile support: User-defined profiles for different use cases
    (e.g., ``--profile writer``).
    
  • Origin tracking: Optional tracking of which file contributed each
    configuration key (for ``bengal config show --origin``).
    
  • Feature expansion: Simple feature toggles expanded to detailed config.

Attributes

Name Type Description
track_origins

Whether origin tracking is enabled.

origin_tracker ConfigWithOrigin | None

The :class:ConfigWithOrigininstance if tracking is enabled.

Methods

load 3 dict[str, Any]
Load config from directory with precedence. Precedence (lowest to highest): 1.…
def load(self, config_dir: Path, environment: str | None = None, profile: str | None = None) -> dict[str, Any]

Load config from directory with precedence.

Precedence (lowest to highest):

  1. Bengal DEFAULTS from defaults.py (built-in defaults)
  2. config/_default/*.yaml (base user config)
  3. config/environments/.yaml (environment overrides)
  4. config/profiles/.yaml (profile settings)
Parameters
Name Type Description
config_dir

Path to config directory

environment

Environment name (auto-detected if None)

Default:None
profile

Profile name (optional)

Default:None
Returns
dict[str, Any] Merged configuration dictionary
get_origin_tracker 0 ConfigWithOrigin | None
Get the origin tracker instance. Returns the origin tracker if tracking was en…
def get_origin_tracker(self) -> ConfigWithOrigin | None

Get the origin tracker instance.

Returns the origin tracker if tracking was enabled during initialization andload() has been called. The tracker contains information about which configuration file contributed each key.

Returns
ConfigWithOrigin | None The :class:`ConfigWithOrigin` instance if ``track_origins=True`` was passed to the constructor and config has been loaded, otherwise ``None``.
Internal Methods 3
__init__ 1
Initialize the directory configuration loader.
def __init__(self, track_origins: bool = False) -> None
Parameters
Name Type Description
track_origins

IfTrue, track which file contributed each configuration key. Use :meth:get_origin_tracker to access the tracking information after loading. Default is False.

Default:False
_load_directory 2 dict[str, Any]
Load and merge all YAML files in a directory. Files are loaded in sorted order…
def _load_directory(self, directory: Path, _origin_prefix: str = '') -> dict[str, Any]

Load and merge all YAML files in a directory.

Files are loaded in sorted order (alphabetically) for deterministic behavior. All files are collected first, then merged in a single batch operation for O(K × D) complexity instead of O(F × K × D).

Parameters
Name Type Description
directory

Directory containing YAML files to load.

_origin_prefix

Reserved for future origin tracking (currently unused).

Default:''
Returns
dict[str, Any] Merged configuration dictionary from all files in the directory.
_normalize_site_keys 1 dict[str, Any]
Move common site keys placed at the root into the site section. Provides backw…
def _normalize_site_keys(self, config: dict[str, Any]) -> dict[str, Any]

Move common site keys placed at the root into the site section.

Provides backward compatibility for configs that set title/baseurl/etc. at the root of _default/*.yaml instead of under [site].

Parameters
Name Type Description
config
Returns
dict[str, Any]