Module

analysis.analyzer

Block analyzer - unified entry point for template analysis.

Combines dependency analysis, purity checking, landmark detection, and role classification into a unified analysis pass.

Classes

BlockAnalyzer 12
Analyze template blocks and extract metadata. Combines dependency analysis, purity checking, landm…

Analyze template blocks and extract metadata.

Combines dependency analysis, purity checking, landmark detection, and role classification into a unified analysis pass.

Thread-safe: Stateless analyzers, creates new result objects.

Configuration:

>>> from kida.analysis import AnalysisConfig
    >>> config = AnalysisConfig(
    ...     page_prefixes=frozenset({"post.", "item."}),
    ...     site_prefixes=frozenset({"global.", "settings."}),
    ... )
    >>> analyzer = BlockAnalyzer(config=config)

Methods

analyze 1 TemplateMetadata
Analyze a template AST and return metadata.
def analyze(self, ast: Template) -> TemplateMetadata
Parameters
Name Type Description
ast

Parsed template AST (nodes.Template)

Returns
TemplateMetadata TemplateMetadata with block information
validate_calls 1 list[CallValidation]
Validate call sites against {% def %} signatures. Walks the AST to collect all…
def validate_calls(self, ast: Template) -> list[CallValidation]

Validate call sites against {% def %} signatures.

Walks the AST to collect all{% def %}signatures, then checks everyFuncCall and {% call %}site that references a known definition. Reports unknown parameters, missing required parameters, and duplicate keyword arguments.

Only validates calls within the same compilation unit. Cross-template calls (via{% from ... import %}) are not checked.

When a{% def %} declares *args or **kwargs, validation is relaxed accordingly (extra positional/keyword args are allowed).

Parameters
Name Type Description
ast

Parsed template AST.

Returns
list[CallValidation] List of ``CallValidation`` results — one per problematic call site. An empty list means all call sites are valid.
Internal Methods 10
__init__ 2
Initialize analyzer with optional configuration.
def __init__(self, config: AnalysisConfig | None = None, template_resolver: Callable[[str], Any] | None = None) -> None
Parameters
Name Type Description
config

Analysis configuration. Uses DEFAULT_CONFIG if not provided.

Default:None
template_resolver

Optional callback(name: str) -> Template | None to resolve included templates for purity analysis. If None, includes return "unknown" purity.

Default:None
_analyze_block 1 BlockMetadata
Analyze a single block node.
def _analyze_block(self, block_node: Block) -> BlockMetadata
Parameters
Name Type Description
block_node
Returns
BlockMetadata
_collect_blocks 1 list[Block]
Recursively collect all Block nodes from AST.
def _collect_blocks(self, ast: Template) -> list[Block]
Parameters
Name Type Description
ast
Returns
list[Block]
_collect_blocks_recursive 2
Recursively find Block nodes.
def _collect_blocks_recursive(self, nodes: Sequence[Node], blocks: list[Block]) -> None
Parameters
Name Type Description
nodes
blocks
_analyze_top_level 2 frozenset[str]
Analyze dependencies in top-level code outside blocks. This captures dependenc…
def _analyze_top_level(self, ast: Template, block_names: set[str]) -> frozenset[str]

Analyze dependencies in top-level code outside blocks.

This captures dependencies from:

  • Code before/after blocks
  • Extends expression (e.g., dynamic parent template)
  • Context type declarations

Does NOT include dependencies from inside blocks (those are tracked per-block).

Parameters
Name Type Description
ast
block_names
Returns
frozenset[str]
_analyze_top_level_nodes 3
Walk nodes, collecting dependencies but skipping block bodies.
def _analyze_top_level_nodes(self, nodes: Sequence[Node], block_names: set[str], deps: set[str]) -> None
Parameters
Name Type Description
nodes
block_names
deps
_check_emits_html 1 bool
Check if a node produces any output.
def _check_emits_html(self, node: Node) -> bool
Parameters
Name Type Description
node
Returns
bool
_collect_defs 2
Recursively collect {% def %} signatures from the AST.
def _collect_defs(self, nodes: Sequence[Node], signatures: dict[str, _DefSignature]) -> None
Parameters
Name Type Description
nodes
signatures
_validate_call_nodes 3
Recursively walk nodes and validate FuncCall sites.
def _validate_call_nodes(self, nodes: Sequence[Node], signatures: dict[str, _DefSignature], issues: list[CallValidation]) -> None
Parameters
Name Type Description
nodes
signatures
issues
_check_func_call 3
Check a single expression for FuncCall nodes targeting known defs.
def _check_func_call(self, expr: Node, signatures: dict[str, _DefSignature], issues: list[CallValidation]) -> None
Parameters
Name Type Description
expr
signatures
issues
_DefSignature 5
Internal: extracted signature of a {% def %} for call validation.

Internal: extracted signature of a {% def %} for call validation.

Attributes

Name Type Description
param_names frozenset[str]
required_params tuple[str, ...]
has_vararg bool
has_kwarg bool

Methods

from_def 1 _DefSignature
Build signature from a Def AST node.
staticmethod
def from_def(node: Def) -> _DefSignature
Parameters
Name Type Description
node
Returns
_DefSignature

Functions

_compute_block_hash 1 str
Compute deterministic structural hash for a block AST.
def _compute_block_hash(block_node: Block) -> str
Parameters
Name Type Description
block_node Block
Returns
str