Module

debug.config_inspector

Configuration Inspector and Diff Tool.

Advanced configuration comparison and analysis beyond the basic bengal config diffcommand. Provides deep comparison between config sources, explains how effective values are resolved through the layer system, and identifies potential configuration issues.

Key Features:

  • ConfigDiff: Single configuration key difference
  • ConfigComparisonResult: Complete diff between two sources
  • KeyExplanation: Resolution chain for a specific key
  • ConfigInspector: Debug tool combining all capabilities

Use Cases:

  • Compare local vs production configuration
  • Understand why a config key has a specific value
  • Detect configuration drift between environments
  • Find deprecated or suspicious configuration

Example:

>>> from bengal.debug.config_inspector import ConfigInspector
>>> inspector = ConfigInspector(site)
>>> diff = inspector.compare("local", "production")
>>> print(diff.format_detailed())

Comparing: local → production Added: 1 Removed: 0 Changed: 3

>>> explanation = inspector.explain_key("site.baseurl")
>>> print(explanation.format())

site.baseurl: https://example.com Source: environments/production.yaml Resolution chain: ○ _default: / → environments/production: https://example.com

Related Modules:

  • bengal.config.directory_loader: Config loading and layering
  • bengal.config.environment: Environment detection
  • bengal.debug.base: Debug tool infrastructure

See Also:

  • bengal/cli/commands/config.py: CLI integration

Classes

ConfigDiff 8
A single configuration key difference between two sources.

A single configuration key difference between two sources.

Attributes

Name Type Description
path str

Dot-separated key path (e.g., "site.title", "build.parallel").

type Literal['added', 'removed', 'changed']

Type of change: "added", "removed", or "changed".

old_value Any

Previous value (None for added keys).

new_value Any

New value (None for removed keys).

old_origin str | None

Source file where old value came from.

new_origin str | None

Source file where new value comes from.

impact str | None

Potential impact description of this change.

Methods

format 0 str
Format the diff for display.
def format(self) -> str
Returns
str Single line like "+ key: value" or "~ key: old → new"
ConfigComparisonResult 11
Complete result of comparing two configuration sources. Contains all differences found, categorize…

Complete result of comparing two configuration sources.

Contains all differences found, categorized by type, with the full configuration dictionaries for reference.

Attributes

Name Type Description
source1 str

Name of first (earlier/base) configuration source.

source2 str

Name of second (later/target) configuration source.

diffs list[ConfigDiff]

List of all ConfigDiff instances found.

config1 dict[str, Any]

Complete configuration dictionary from source1.

config2 dict[str, Any]

Complete configuration dictionary from source2.

Methods

has_changes 0 bool
Check if there are any differences.
property
def has_changes(self) -> bool
Returns
bool
added 0 list[ConfigDiff]
Get keys that were added in source2.
property
def added(self) -> list[ConfigDiff]
Returns
list[ConfigDiff]
removed 0 list[ConfigDiff]
Get keys that were removed from source1.
property
def removed(self) -> list[ConfigDiff]
Returns
list[ConfigDiff]
changed 0 list[ConfigDiff]
Get keys with different values between sources.
property
def changed(self) -> list[ConfigDiff]
Returns
list[ConfigDiff]
format_summary 0 str
Format a brief summary of differences.
def format_summary(self) -> str
Returns
str Multi-line summary with counts by change type.
format_detailed 0 str
Format detailed diff output with all changes. Shows added, removed, and change…
def format_detailed(self) -> str

Format detailed diff output with all changes.

Shows added, removed, and changed keys with their values and origin files.

Returns
str Multi-line detailed diff output.
KeyExplanation 8
Explanation of how a configuration key got its effective value. Shows the complete resolution chai…

Explanation of how a configuration key got its effective value.

Shows the complete resolution chain through defaults, environment, and profile layers, indicating which layer provided the final value.

Attributes

Name Type Description
key_path str

Dot-separated key path (e.g., "site.baseurl").

effective_value Any

The final resolved value for this key.

origin str | None

Source file where the effective value came from.

layer_values list[tuple[str, Any]]

Resolution chain as (source, value) tuples.

is_default bool

Whether the value comes from _default layer.

deprecated bool

Whether this key is deprecated.

deprecation_message str | None

Message explaining deprecation.

Methods

format 0 str
Format the explanation for display. Shows key, value, origin, and full resolut…
def format(self) -> str

Format the explanation for display.

Shows key, value, origin, and full resolution chain.

Returns
str Multi-line formatted explanation.
ConfigInspector 14
Advanced configuration inspector and diff tool. Provides deep comparison between configuration sou…

Advanced configuration inspector and diff tool.

Provides deep comparison between configuration sources (environments, profiles), explains how values are resolved through the layer system, and identifies potential configuration issues.

Capabilities:

  • Deep comparison between any config sources
  • Origin tracking for each value
  • Impact analysis for configuration changes
  • Key-level explanation of value resolution
  • Default value detection
  • Deprecation warnings
  • Issue detection (missing protocols, trailing slashes)

Creation:

Instantiate with a Site instance:

    inspector = ConfigInspector(site)

Attributes

Name Type Description
name str
description str
IMPACT_PATTERNS ClassVar[dict[str, str]]

Methods

run 4 DebugReport
Run config inspection.
def run(self, compare_to: str | None = None, explain_key: str | None = None, list_sources: bool = False, **kwargs: Any) -> DebugReport
Parameters
Name Type Description
compare_to

Source to compare against (environment or profile)

Default:None
explain_key

Specific key to explain

Default:None
list_sources

List available config sources **kwargs: Additional arguments

Default:False
**kwargs
Returns
DebugReport DebugReport with findings
analyze 0 DebugReport
Perform analysis and return report. This is the abstract method required by De…
def analyze(self) -> DebugReport

Perform analysis and return report.

This is the abstract method required by DebugTool. For parameterized analysis, use run() instead.

Returns
DebugReport
compare 3 ConfigComparisonResult
Compare two configuration sources.
def compare(self, source1: str, source2: str, track_origins: bool = True) -> ConfigComparisonResult
Parameters
Name Type Description
source1

First source (environment name, "profile:name", or file path)

source2

Second source

track_origins

Track origin of each value

Default:True
Returns
ConfigComparisonResult ConfigComparisonResult with all differences
explain_key 1 KeyExplanation | None
Explain how a config key got its effective value. Shows the resolution chain t…
def explain_key(self, key_path: str) -> KeyExplanation | None

Explain how a config key got its effective value.

Shows the resolution chain through defaults → environment → profile.

Parameters
Name Type Description
key_path

Dot-separated key path (e.g., "site.title")

Returns
KeyExplanation | None KeyExplanation or None if key not found
find_issues 0 list[DebugFinding]
Find potential configuration issues. **Checks for:** - Deprecated keys - Missi…
def find_issues(self) -> list[DebugFinding]

Find potential configuration issues.

Checks for:

  • Deprecated keys
  • Missing required keys
  • Type mismatches
  • Suspicious values
Returns
list[DebugFinding] List of findings
Internal Methods 6
__init__ 3
Initialize inspector.
def __init__(self, site: Any = None, cache: Any = None, root_path: Path | None = None) -> None
Parameters
Name Type Description
site

Site instance

Default:None
cache

Optional BuildCache (unused but required by DebugTool)

Default:None
root_path

Optional root path override

Default:None
_list_available_sources 0 list[str]
List available configuration sources.
def _list_available_sources(self) -> list[str]
Returns
list[str]
_load_config_source 2 tuple[dict[str, Any], di…
Load configuration from a source.
def _load_config_source(self, source: str, track_origins: bool = True) -> tuple[dict[str, Any], dict[str, str]]
Parameters
Name Type Description
source

Source identifier

track_origins

Whether to track origins

Default:True
Returns
tuple[dict[str, Any], dict[str, str]] Tuple of (config_dict, origins_dict)
_compute_diffs 6
Recursively compute diffs between configs.
def _compute_diffs(self, config1: dict[str, Any], config2: dict[str, Any], origins1: dict[str, str], origins2: dict[str, str], path: list[str], diffs: list[ConfigDiff]) -> None
Parameters
Name Type Description
config1
config2
origins1
origins2
path
diffs
_get_impact 1 str | None
Get potential impact description for a config key.
def _get_impact(self, key: str) -> str | None
Parameters
Name Type Description
key
Returns
str | None
_load_defaults_only 1 dict[str, Any]
Load only the _default config files.
def _load_defaults_only(self, defaults_dir: Path) -> dict[str, Any]
Parameters
Name Type Description
defaults_dir
Returns
dict[str, Any]