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 17 ▼
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: Traversal helpers keep mutable state inContextVarand each call creates a distinct result object. Shared result mappings remain caller-visible and must be treated as read-only while shared.

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_calls_with_external_defs 2 list[CallValidation] ▼
Validate calls against local defs plus imported component metadata. ``external…
def validate_calls_with_external_defs(self, ast: Template, external_defs: dict[str, DefMetadata]) -> list[CallValidation]

Validate calls against local defs plus imported component metadata.

external_defsmaps the name visible in this template to metadata for a{% def %}declared in another template. Dynamic imports are intentionally skipped by callers.

Parameters
Name Type Description
ast —
external_defs —
Returns
list[CallValidation]
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.
validate_call_types_with_external_defs 2 list[TypeMismatch] ▼
Validate literal call arg types against local and imported defs.
def validate_call_types_with_external_defs(self, ast: Template, external_defs: dict[str, DefMetadata]) -> list[TypeMismatch]
Parameters
Name Type Description
ast —
external_defs —
Returns
list[TypeMismatch]
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 8 ▼
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
from_def_metadata 1 _DefSignature ▼
Build a signature from introspection metadata for an imported def.
staticmethod
def from_def_metadata(meta: DefMetadata) -> _DefSignature
Parameters
Name Type Description
meta —
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