Classes
Compiler
25
▼
Compile Kida AST to Python code objects.
The Compiler transforms a Kida Template AST into an `ast.…
Compiler
25
▼
Compile Kida AST to Python code objects.
The Compiler transforms a Kida Template AST into anast.Module, then
compiles it to a code object ready forexec(). The generated code
defines arender(ctx, _blocks=None)function.
Node Dispatch:
Uses O(1) dict lookup for node type → handler:
python dispatch = { "Data": self._compile_data, "Output": self._compile_output, "If": self._compile_if, ... } handler = dispatch[type(node).__name__]
Line Tracking:
For nodes that can cause runtime errors (Output, For, If, etc.),
generates_get_render_ctx().line = Nbefore the node's code.
This updates the ContextVar-stored RenderContext instead of polluting
the user's ctx dict, enabling rich error messages with source line
numbers while keeping user context clean.
Attributes
| Name | Type | Description |
|---|---|---|
_env |
— |
Parent Environment (for filter/test access) |
_name |
str | None
|
Template name for error messages |
_filename |
str | None
|
Source file path for compile() |
_locals |
set[str]
|
Set of local variable names (loop vars, macro args) |
_blocks |
dict[str, Block]
|
Dict of block_name → Block node (for inheritance) |
_block_counter |
int
|
Counter for unique variable names |
Methods
compile
3
types.CodeType
▼
Compile template AST to code object.
compile
3
types.CodeType
▼
def compile(self, node: TemplateNode, name: str | None = None, filename: str | None = None) -> types.CodeType
Parameters
| Name | Type | Description |
|---|---|---|
node |
— |
Root Template node |
name |
— |
Template name for error messages Default:None
|
filename |
— |
Source filename for error messages Default:None
|
Returns
types.CodeType
Compiled code object ready for exec()
Internal Methods 18 ▼
__init__
1
▼
__init__
1
▼
def __init__(self, env: Environment)
Parameters
| Name | Type | Description |
|---|---|---|
env |
— |
_collect_blocks
1
▼
Recursively collect all Block nodes from the AST.
This ensures nested blocks (…
_collect_blocks
1
▼
def _collect_blocks(self, nodes: Sequence[Node]) -> None
Recursively collect all Block nodes from the AST.
This ensures nested blocks (blocks inside blocks, blocks inside conditionals, etc.) are all registered for compilation.
Parameters
| Name | Type | Description |
|---|---|---|
nodes |
— |
_emit_output
1
ast.stmt
▼
Generate output statement: yield (streaming) or _append (StringBuilder).
All o…
_emit_output
1
ast.stmt
▼
def _emit_output(self, value_expr: ast.expr) -> ast.stmt
Generate output statement: yield (streaming) or _append (StringBuilder).
All output generation in compiled templates flows through this method, allowing the compiler to switch between StringBuilder and generator modes.
Parameters
| Name | Type | Description |
|---|---|---|
value_expr |
— |
Returns
ast.stmt
_compile_template
1
ast.Module
▼
Generate Python module from template.
Produces both StringBuilder functions (r…
_compile_template
1
ast.Module
▼
def _compile_template(self, node: TemplateNode) -> ast.Module
Generate Python module from template.
Produces both StringBuilder functions (render, block) and generator functions (render_stream, block_stream) in a single module. The StringBuilder path is used by Template.render() and the generator path by Template.render_stream().
When async constructs are detected (AsyncFor, Await), also generates async generator functions (render_stream_async, block*_stream_async).
Parameters
| Name | Type | Description |
|---|---|---|
node |
— |
Returns
ast.Module
_make_globals_setup
1
ast.FunctionDef | None
▼
Generate _globals_setup(ctx) from {% globals %}, {% imports %}, and top-level i…
_make_globals_setup
1
ast.FunctionDef | None
▼
def _make_globals_setup(self, node: TemplateNode) -> ast.FunctionDef | None
Generate _globals_setup(ctx) from {% globals %}, {% imports %}, and top-level imports.
Scans the template body for:
- Top-level FromImport and Import nodes (so render_block has macros in scope)
- Globals and Imports nodes (macros/variables for block context)
This function is called by render_block() to inject macros and variables into the block's context. Returns None if neither globals nor top-level imports exist.
Parameters
| Name | Type | Description |
|---|---|---|
node |
— |
Returns
ast.FunctionDef | None
_make_block_preamble
1
list[ast.stmt]
▼
Common setup stmts for block functions.
Non-streaming adds buf and _append for…
_make_block_preamble
1
list[ast.stmt]
▼
def _make_block_preamble(self, streaming: bool) -> list[ast.stmt]
Common setup stmts for block functions.
Non-streaming adds buf and _append for StringBuilder.
Parameters
| Name | Type | Description |
|---|---|---|
streaming |
— |
Returns
list[ast.stmt]
_make_block_function
2
ast.FunctionDef
▼
Generate a block function: _block_name(ctx, _blocks) -> str.
_make_block_function
2
ast.FunctionDef
▼
def _make_block_function(self, name: str, block_node: Block) -> ast.FunctionDef
Parameters
| Name | Type | Description |
|---|---|---|
name |
— |
|
block_node |
— |
Returns
ast.FunctionDef
_make_render_preamble
0
list[ast.stmt]
▼
Shared init block for render functions: if _blocks, _scope_stack, _acc.
_make_render_preamble
0
list[ast.stmt]
▼
def _make_render_preamble(self) -> list[ast.stmt]
Returns
list[ast.stmt]
_make_render_extends_body
5
list[ast.stmt]
▼
Top-level statements, block registration, and extends return/yield.
_make_render_extends_body
5
list[ast.stmt]
▼
def _make_render_extends_body(self, node: TemplateNode, extends_node: Extends, block_names: dict[str, Block], block_suffix: str, extends_helper: str) -> list[ast.stmt]
Parameters
| Name | Type | Description |
|---|---|---|
node |
— |
|
extends_node |
— |
|
block_names |
— |
|
block_suffix |
— |
|
extends_helper |
— |
Returns
list[ast.stmt]
_make_render_direct_body
2
list[ast.stmt]
▼
No-extends path: buf setup (if not streaming), body compile, return vs yield.
_make_render_direct_body
2
list[ast.stmt]
▼
def _make_render_direct_body(self, node: TemplateNode, streaming: bool) -> list[ast.stmt]
Parameters
| Name | Type | Description |
|---|---|---|
node |
— |
|
streaming |
— |
Returns
list[ast.stmt]
_make_render_function
1
ast.FunctionDef
▼
Generate the render(ctx, _blocks=None) function.
Optimization: Cache global fu…
_make_render_function
1
ast.FunctionDef
▼
def _make_render_function(self, node: TemplateNode) -> ast.FunctionDef
Generate the render(ctx, _blocks=None) function.
Optimization: Cache global function references as locals for O(1) LOAD_FAST instead of O(1) LOAD_GLOBAL + hash lookup.
For templates with extends:
def render(ctx, _blocks=None):
if _blocks is None: _blocks = {}
# Register child blocks
_blocks.setdefault('name', _block_name)
# Render parent with blocks
return _extends('parent.html', ctx, _blocks)
Parameters
| Name | Type | Description |
|---|---|---|
node |
— |
Returns
ast.FunctionDef
_make_block_function_stream
2
ast.FunctionDef
▼
Generate a streaming block: _block_name_stream(ctx, _blocks) -> Generator[str].
_make_block_function_stream
2
ast.FunctionDef
▼
def _make_block_function_stream(self, name: str, block_node: Block) -> ast.FunctionDef
Generate a streaming block: _block_name_stream(ctx, _blocks) -> Generator[str].
Parameters
| Name | Type | Description |
|---|---|---|
name |
— |
|
block_node |
— |
Returns
ast.FunctionDef
_make_render_function_stream
2
ast.FunctionDef
▼
Generate render_stream(ctx, _blocks=None) generator function.
For templates wi…
_make_render_function_stream
2
ast.FunctionDef
▼
def _make_render_function_stream(self, node: TemplateNode, blocks: dict[str, Block]) -> ast.FunctionDef
Generate render_stream(ctx, _blocks=None) generator function.
For templates with extends:
yield from _extends_stream('parent.html', ctx, _blocks)
For templates without extends:
yield chunks directly
Parameters
| Name | Type | Description |
|---|---|---|
node |
— |
|
blocks |
— |
Returns
ast.FunctionDef
_make_block_function_stream_async
2
ast.AsyncFunctionDef
▼
Generate async streaming block: _block_name_stream_async(ctx, _blocks).
Mirror…
_make_block_function_stream_async
2
ast.AsyncFunctionDef
▼
def _make_block_function_stream_async(self, name: str, block_node: Block) -> ast.AsyncFunctionDef
Generate async streaming block: _block_name_stream_async(ctx, _blocks).
Mirrors _make_block_function_stream() but produces an async generator function (async def + yield). Used when the template contains async constructs (AsyncFor, Await).
Part of RFC: rfc-async-rendering.
Parameters
| Name | Type | Description |
|---|---|---|
name |
— |
|
block_node |
— |
Returns
ast.AsyncFunctionDef
_make_render_function_stream_async
2
ast.AsyncFunctionDef
▼
Generate async render_stream_async(ctx, _blocks=None) function.
Mirrors _make_…
_make_render_function_stream_async
2
ast.AsyncFunctionDef
▼
def _make_render_function_stream_async(self, node: TemplateNode, blocks: dict[str, Block]) -> ast.AsyncFunctionDef
Generate async render_stream_async(ctx, _blocks=None) function.
Mirrors _make_render_function_stream() but produces an async generator for native async iteration over AsyncFor loops and Await expressions.
For templates with extends:
async for chunk in _extends_stream_async(parent, ctx, _blocks):
yield chunk
For templates without extends:
yield chunks directly via async generator
Part of RFC: rfc-async-rendering.
Parameters
| Name | Type | Description |
|---|---|---|
node |
— |
|
blocks |
— |
Returns
ast.AsyncFunctionDef
_make_line_marker
1
ast.stmt
▼
Generate RenderContext line update for error tracking.
Generates: _get_render_…
_make_line_marker
1
ast.stmt
▼
def _make_line_marker(self, lineno: int) -> ast.stmt
Generate RenderContext line update for error tracking.
Generates: _get_render_ctx().line = lineno
This updates the ContextVar-stored RenderContext instead of polluting the user's ctx dict.
RFC: kida-contextvar-patterns
Parameters
| Name | Type | Description |
|---|---|---|
lineno |
— |
Returns
ast.stmt
_compile_node
1
list[ast.stmt]
▼
Compile a single AST node to Python statements.
Complexity: O(1) type dispatch…
_compile_node
1
list[ast.stmt]
▼
def _compile_node(self, node: Node) -> list[ast.stmt]
Compile a single AST node to Python statements.
Complexity: O(1) type dispatch using class name lookup.
For nodes that can cause runtime errors, injects a line marker statement (ctx['_line'] = N) before the node's code. This enables rich error messages with source line numbers.
Parameters
| Name | Type | Description |
|---|---|---|
node |
— |
Returns
list[ast.stmt]
_get_node_dispatch
0
dict[str, Callable]
▼
Get node type dispatch table (cached on first call).
_get_node_dispatch
0
dict[str, Callable]
▼
def _get_node_dispatch(self) -> dict[str, Callable]
Returns
dict[str, Callable]