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 15
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.
validate_call_types 1 list[TypeMismatch]
Validate literal argument types against {% def %} parameter annotations. Walks…
def validate_call_types(self, ast: Template) -> list[TypeMismatch]

Validate literal argument types against {% def %} parameter annotations.

Walks the AST to collect{% def %}signatures (including type annotations), then checks everyFuncCall and {% call %}site. Only literal arguments (Constnodes) are checked — variable arguments are skipped since their type can't be known statically.

Parameters
Name Type Description
ast
Returns
list[TypeMismatch] List of ``TypeMismatch`` results — one per mismatched literal. An empty list means all checked literals match their annotations.
Internal Methods 12
__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 or region node.
def _analyze_block(self, block_node: Block | Region) -> BlockMetadata
Parameters
Name Type Description
block_node
Returns
BlockMetadata
_collect_blocks 1 list[Block | Region]
Recursively collect all Block and Region nodes from AST.
def _collect_blocks(self, ast: Template) -> list[Block | Region]
Parameters
Name Type Description
ast
Returns
list[Block | Region]
_collect_blocks_recursive 2
Recursively find Block and Region nodes.
def _collect_blocks_recursive(self, nodes: Sequence[Node], blocks: list[Block | Region]) -> 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
_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
_validate_type_nodes 3
Recursively walk nodes and check literal arg types at call sites.
def _validate_type_nodes(self, nodes: Sequence[Node], signatures: dict[str, _DefSignature], mismatches: list[TypeMismatch]) -> None
Parameters
Name Type Description
nodes
signatures
mismatches
_check_func_call_types 3
Check literal argument types at a single call site.
def _check_func_call_types(self, expr: Node, signatures: dict[str, _DefSignature], mismatches: list[TypeMismatch]) -> None
Parameters
Name Type Description
expr
signatures
mismatches
_check_literal_type 6
Check a single Const arg against its parameter's annotation.
def _check_literal_type(self, func_name: str, param_name: str, const: Const, annotations: dict[str, str], call_expr: FuncCall, mismatches: list[TypeMismatch]) -> None
Parameters
Name Type Description
func_name
param_name
const
annotations
call_expr
mismatches
_DefSignature 7
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, ...]
ordered_params tuple[str, ...]
param_annotations dict[str, 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
_SurfaceScanResult 3
Result of a merged surface scan (landmarks + emits_html + block_hash).

Result of a merged surface scan (landmarks + emits_html + block_hash).

Attributes

Name Type Description
landmarks frozenset[str]
emits_html bool
block_hash str

Functions

_resolve_annotation_types 1 set[type] | None
Resolve an annotation string to a set of acceptable Python types. Handles simp…
def _resolve_annotation_types(annotation: str) -> set[type] | None

Resolve an annotation string to a set of acceptable Python types.

Handles simple types (str, int) and union types (str | None). Returns None for unrecognized annotations (caller should skip validation).

Parameters
Name Type Description
annotation str
Returns
set[type] | None
_surface_scan 1 _SurfaceScanResult
Single-pass surface scan collecting landmarks, emits_html, and block_hash. Rep…
def _surface_scan(block_node: Block | Region) -> _SurfaceScanResult

Single-pass surface scan collecting landmarks, emits_html, and block_hash.

Replaces three separate AST traversals (LandmarkDetector, _check_emits_html, _compute_block_hash) with one walk.

Parameters
Name Type Description
block_node Block | Region
Returns
_SurfaceScanResult