Classes
DirectiveContract
dataclass
Defines valid nesting relationships for a directive.
This is the KEY FEATURE that solves the neste…
DirectiveContract
dataclass Defines valid nesting relationships for a directive.
This is the KEY FEATURE that solves the nested directive validation problem. Contracts are checked at parse time to catch invalid nesting early.
Attributes
| Name | Type | Description |
|---|---|---|
requires_parent |
tuple[str, ...] |
This directive MUST be inside one of these parent types. Empty tuple means can appear anywhere (root-level OK). |
requires_children |
tuple[str, ...] |
This directive MUST contain at least one of these types. Empty tuple means no required children. |
min_children |
int |
Minimum count of required_children types. |
max_children |
int |
Maximum children (0 = unlimited). Example - StepDirective (must be inside steps): CONTRACT = DirectiveContract( requires_parent=("steps",), ) Example - StepsDirective (must contain steps): CONTRACT = DirectiveContract( requires_children=("step",), min_children=1, allowed_children=("step",), ) Example - TabSetDirective (tabs with items): CONTRACT = DirectiveContract( requires_children=("tab_item",), min_children=1, ) |
allowed_children |
tuple[str, ...] |
Only these child types are allowed (whitelist). Empty tuple means any children allowed. |
disallowed_children |
tuple[str, ...] |
These child types are NOT allowed (blacklist). Takes precedence over allowed_children. |
Methods 2
has_parent_requirement
property
True if this directive requires a specific parent.
has_parent_requirement
property def has_parent_requirement(self) -> bool
True if this directive requires a specific parent.
Returns
bool
has_child_requirement
property
True if this directive requires specific children.
has_child_requirement
property def has_child_requirement(self) -> bool
True if this directive requires specific children.
Returns
bool
Internal Methods 1
__post_init__
Validate contract configuration.
__post_init__
def __post_init__(self) -> None
Validate contract configuration.
ContractViolation
dataclass
Represents a contract violation found during parsing.
Collected violations can be:
- Logged as war…
ContractViolation
dataclass Represents a contract violation found during parsing.
Collected violations can be:
- Logged as warnings (default)
- Raised as errors (strict mode)
- Reported in health checks
Attributes
| Name | Type | Description |
|---|---|---|
directive |
str |
The directive type that was validated |
violation_type |
str |
Type of violation (for structured logging) |
message |
str |
Human-readable description |
expected |
list[str] | int | None |
What was expected (list, int, or description) |
found |
list[str] | str | int | None |
What was actually found |
location |
str | None |
Source location (e.g., "content/guide.md:45") |
Methods 1
to_log_dict
Convert to structured log format.
Note: Uses 'detail' instead of 'message' to …
to_log_dict
def to_log_dict(self) -> dict[str, Any]
Convert to structured log format.
Note: Uses 'detail' instead of 'message' to avoid conflict with BengalLogger's positional 'message' argument.
Returns
Dict suitable for structured logging kwargsdict[str, Any]
—
ContractValidator
Validates directive nesting against contracts.
Used by BengalDirective.parse() to check:
1. Parent…
ContractValidator
Validates directive nesting against contracts.
Used by BengalDirective.parse() to check:
- Parent context is valid (if requires_parent specified)
- Children meet requirements (if requires_children specified)
- Children types are allowed (if allowed_children specified)
Example usage in BengalDirective:
def parse(self, block, m, state):
# ... parse content ...
# Validate parent
if self.CONTRACT:
parent_type = self._get_parent_type(state)
violations = ContractValidator.validate_parent(
self.CONTRACT, self.TOKEN_TYPE, parent_type
)
for v in violations:
self.logger.warning(v.violation_type, **v.to_log_dict())
# ... parse children ...
# Validate children
if self.CONTRACT:
violations = ContractValidator.validate_children(
self.CONTRACT, self.TOKEN_TYPE, children
)
for v in violations:
self.logger.warning(v.violation_type, **v.to_log_dict())
Methods 2
validate_parent
staticmethod
Validate that the directive is inside a valid parent.
validate_parent
staticmethod def validate_parent(contract: DirectiveContract, directive_type: str, parent_type: str | None, location: str | None = None) -> list[ContractViolation]
Validate that the directive is inside a valid parent.
Parameters 4
contract |
DirectiveContract |
The directive's contract |
directive_type |
str |
The directive being validated (e.g., "step") |
parent_type |
str | None |
The parent directive type (None if at root) |
location |
str | None |
Source location for error messages |
Returns
List of violations (empty if valid)list[ContractViolation]
—
validate_children
staticmethod
Validate that children meet contract requirements.
validate_children
staticmethod def validate_children(contract: DirectiveContract, directive_type: str, children: list[dict[str, Any]], location: str | None = None) -> list[ContractViolation]
Validate that children meet contract requirements.
Parameters 4
contract |
DirectiveContract |
The directive's contract |
directive_type |
str |
The directive being validated (e.g., "steps") |
children |
list[dict[str, Any]] |
Parsed child tokens |
location |
str | None |
Source location for error messages |
Returns
List of violations (empty if valid)list[ContractViolation]
—