# core

URL: /kida/api/template/core/
Section: template
Description: Kida Template — compiled template object ready for rendering.

The Template class wraps a compiled code object and provides the ``render()``
API. Templates are immutable and thread-safe for concurrent rendering.

Architecture:
    ```
    Template
    ├── _env_ref: WeakRef[Environment]  # Prevents circular refs
    ├── _code: code object              # Compiled Python bytecode
    ├── _render_func: callable          # Extracted render() function
    └── _name, _filename                # For error messages
    ```

StringBuilder Pattern:
Generated code uses ``buf.append()`` + ``''.join(buf)``:
    ```python
    def render(ctx, _blocks=None):
        buf = []
        _append = buf.append
        _append("Hello, ")
        _append(_e(_s(ctx["name"])))
        return ''.join(buf)
    ```
This is O(n) vs O(n²) for string concatenation.

Memory Safety:
Uses ``weakref.ref(env)`` to break potential cycles:
``Template → (weak) → Environment → cache → Template``

Thread-Safety:
- Templates are immutable after construction
- ``render()`` creates only local state (buf list)
- Multiple threads can call ``render()`` concurrently

Complexity:
- ``render()``: O(n) where n = output size
- ``_escape()``: O(n) single-pass via ``str.translate()``

---

> For a complete page index, fetch /kida/llms.txt.

Open LLM text
(/kida/api/template/core/index.txt)

Share with AI

Ask Claude
(https://claude.ai/new?q=Please%20help%20me%20understand%20this%20documentation%3A%20%2Fkida%2Fapi%2Ftemplate%2Fcore%2Findex.txt)

Ask ChatGPT
(https://chatgpt.com/?q=Please%20help%20me%20understand%20this%20documentation%3A%20%2Fkida%2Fapi%2Ftemplate%2Fcore%2Findex.txt)

Ask Gemini
(https://gemini.google.com/app?q=Please%20help%20me%20understand%20this%20documentation%3A%20%2Fkida%2Fapi%2Ftemplate%2Fcore%2Findex.txt)

Ask Copilot
(https://copilot.microsoft.com/?q=Please%20help%20me%20understand%20this%20documentation%3A%20%2Fkida%2Fapi%2Ftemplate%2Fcore%2Findex.txt)

Module

#
`template.core`

Kida Template — compiled template object ready for rendering.

The Template class wraps a compiled code object and provides the`render()`
API. Templates are immutable and thread-safe for concurrent rendering.

Architecture:

```
```
Template
├── _env_ref: WeakRef[Environment] # Prevents circular refs
├── _code: code object # Compiled Python bytecode
├── _render_func: callable # Extracted render() function
└── _name, _filename # For error messages
```
```

StringBuilder Pattern:

Generated code uses`buf.append()` + `''.join(buf)`:
`python def render(ctx, _blocks=None): buf = [] _append = buf.append _append("Hello, ") _append(_e(_s(ctx["name"]))) return ''.join(buf) `
This is O(n) vs O(n²) for string concatenation.

Memory Safety:

Uses`weakref.ref(env)`to break potential cycles:
`Template → (weak) → Environment → cache → Template`

Thread-Safety:

- Templates are immutable after construction

- `render()`creates only local state (buf list)

- Multiple threads can call`render()`concurrently

Complexity:

- `render()`: O(n) where n = output size

- `_escape()`: O(n) single-pass via `str.translate()`

3Classes1Function

## Classes

`ErrorDict`

4

▼

Error context exposed to ``{% fallback name %}`` blocks.

Error context exposed to`{% fallback name %}`blocks.

#### Attributes

Name
Type
Description

`message`

`str`

—

`type`

`str`

—

`template`

`str | None`

—

`line`

`int | None`

—

`Template`

28

▼

Compiled template ready for rendering.

Wraps a compiled code object containing a ``render(ctx, _bl…

Compiled template ready for rendering.

Wraps a compiled code object containing a`render(ctx, _blocks)`function.
Templates are immutable and thread-safe for concurrent`render()`calls.

Thread-Safety:

- Template object is immutable after construction

- Each`render()`call creates local state only (buf list)

- Multiple threads can render the same template simultaneously

Memory Safety:
Uses`weakref.ref(env)`to prevent circular reference leaks:
`Template → (weak) → Environment → _cache → Template`

Methods:
render(**context): Render template with given variables
render_async(**context): Async render for templates with await

Error Enhancement:

Runtime errors are caught and enhanced with template context:

```
```
TemplateRuntimeError: 'NoneType' has no attribute 'title'
Location: article.html:15
Expression: {{ post.title }}
Values:
post = None (NoneType)
Suggestion: Check if 'post' is defined before accessing .title
```
```

#### Attributes

Name
Type
Description

`name`

—

Template identifier (for error messages)

`filename`

—

Source file path (for error messages)

#### Methods

`warnings`

0

`list`

▼

Compile-time warnings for this template.

property

`def warnings(self) -> list`

##### Returns

`list`

`name`

0

`str | None`

▼

Template name.

property

`def name(self) -> str | None`

##### Returns

`str | None`

`filename`

0

`str | None`

▼

Source filename.

property

`def filename(self) -> str | None`

##### Returns

`str | None`

`is_async`

0

`bool`

▼

True if this template uses async constructs (async for / await).

Part of RFC: …

property

`def is_async(self) -> bool`

True if this template uses async constructs (async for / await).

Part of RFC: rfc-async-rendering.

##### Returns

`bool`

`render`

2

`str`

▼

Render template with given context.

Context is passed as keyword arguments. Co…

`def render(self, *args: Any, **kwargs: Any) -> str`

Render template with given context.

Context is passed as keyword arguments. Common keys include
`page`, `site`, `user`— types vary by template.

User context is now CLEAN - no internal keys injected.
Internal state (_template, _line, _include_depth, _cached_blocks,
_cached_stats) is managed via RenderContext ContextVar.

##### Parameters

Name
Type
Description

`*args`
`—`

`**kwargs`
`—`

##### Returns

`str`

Rendered template as string

`render_block`

3

`str`

▼

Render a single block from the template.

Context is passed as keyword argument…

`def render_block(self, block_name: str, *args: Any, **kwargs: Any) -> str`

Render a single block from the template.

Context is passed as keyword arguments. Common keys include
`page`, `site`, `user`— types vary by template.

Renders just the named block, useful for caching blocks that
only depend on site-wide context (e.g., navigation, footer).
Supports inherited blocks: descendant templates can render
blocks defined only in a parent by name (e.g. render_block("sidebar")
on a child that extends a base defining a sidebar block it does not override).

##### Parameters

Name
Type
Description

`block_name`
`—`

Name of the block to render (e.g., "nav", "footer") *args: Single dict of context variables **kwargs: Context variables as keyword arguments

`*args`
`—`

`**kwargs`
`—`

##### Returns

`str`

Rendered block HTML as string

`render_with_blocks`

3

`str`

▼

Render this template with pre-rendered HTML injected into blocks.

Enables prog…

`def render_with_blocks(self, block_overrides: dict[str, str], *args: Any, **kwargs: Any) -> str`

Render this template with pre-rendered HTML injected into blocks.

Enables programmatic layout composition: render a page's content,
then inject it as the`content`block of a parent layout template,
without needing`{% extends %}`in the template source.

Each key in block_overrides names a block; the value is a trusted,
pre-rendered HTML string that replaces that block's default content.
Kida injects these strings directly, so callers must escape or sanitize
untrusted content before building the override mapping.

##### Parameters

Name
Type
Description

`block_overrides`
`—`

Mapping of block name → pre-rendered HTML string. *args: Single dict of context variables. **kwargs: Context variables as keyword arguments.

`*args`
`—`

`**kwargs`
`—`

##### Returns

`str`

Rendered template as string with block overrides applied.

`render_stream`

2

`Iterator[str]`

▼

Render template as a generator of HTML chunks.

Yields chunks at every statemen…

`def render_stream(self, *args: Any, **kwargs: Any) -> Iterator[str]`

Render template as a generator of HTML chunks.

Yields chunks at every statement boundary, enabling progressive
delivery via chunked transfer encoding.

##### Parameters

Name
Type
Description

`*args`
`—`

`**kwargs`
`—`

##### Returns

`Iterator[str]`

`list_blocks`

0

`list[str]`

▼

List all blocks available for render_block() (including inherited).

`def list_blocks(self) -> list[str]`

##### Returns

`list[str]`

List of block names available for render_block()

`render_async`

2

`str`

▼

Async wrapper for synchronous templates.

Runs ``render()`` in a thread pool to…

async

`async def render_async(self, *args: Any, **kwargs: Any) -> str`

Async wrapper for synchronous templates.

Runs`render()`in a thread pool to avoid blocking the event loop.
Async templates (those with`{% async for %}` or `{{ await ... }}`)
are not supported by this method. Use`render_stream_async()`for
native async template rendering.

##### Parameters

Name
Type
Description

`*args`
`—`

`**kwargs`
`—`

##### Returns

`str`

`render_stream_async`

2

`AsyncIterator[str]`

▼

Render template as an async generator of HTML chunks.

For templates with async…

async

`async def render_stream_async(self, *args: Any, **kwargs: Any) -> AsyncIterator[str]`

Render template as an async generator of HTML chunks.

For templates with async constructs ({% async for %}, {{ await }}),
this calls the native async render function. For sync templates,
it wraps the sync render_stream() in an async generator.

##### Parameters

Name
Type
Description

`*args`
`—`

`**kwargs`
`—`

##### Returns

`AsyncIterator[str]`

`render_block_stream_async`

3

`AsyncIterator[str]`

▼

Render a single block as an async stream.

Looks up the async streaming block f…

async

`async def render_block_stream_async(self, block_name: str, *args: Any, **kwargs: Any) -> AsyncIterator[str]`

Render a single block as an async stream.

Looks up the async streaming block function first, falls back to
the sync streaming block function wrapped in an async generator.
Supports inherited blocks like render_block().

##### Parameters

Name
Type
Description

`block_name`
`—`

Name of the block to render *args: Single dict of context variables **kwargs: Context variables as keyword arguments

`*args`
`—`

`**kwargs`
`—`

##### Returns

`AsyncIterator[str]`

Internal Methods
14

▼

`_env`

0

`Environment`

▼

Get the Environment (dereferences weak reference).

property

`def _env(self) -> Environment`

##### Returns

`Environment`

`__init__`

7

▼

Initialize template with compiled code.

`def __init__(self, env: Environment, code: types.CodeType, name: str | None, filename: str | None, optimized_ast: TemplateNode | None = None, source: str | None = None, precomputed: list[Any] | None = None)`

##### Parameters

Name
Type
Description

`env`
`—`

Parent Environment (stored as weak reference)

`code`
`—`

Compiled Python code object

`name`
`—`

Template name (for error messages)

`filename`
`—`

Source filename (for error messages)

`optimized_ast`
`—`

Optional preserved AST for introspection. If None, introspection methods return empty results.

Default:`None`

`source`
`—`

Template source for runtime error snippets. Stored for use by enhance_template_error() to provide source context in TemplateRuntimeError exceptions.

Default:`None`

`precomputed`
`—`

Values that the partial evaluator folded but that cannot be stored in`ast.Constant` nodes (dict, list, etc.). Injected into the exec namespace as `_pc_0`, `_pc_1`, ...

Default:`None`

`_collect_declared_definitions`

1

`frozenset[str]`

▼

Return the names of top-level {% def %} / {% region %} nodes.

Returns an empty…

staticmethod

`def _collect_declared_definitions(optimized_ast: TemplateNode | None) -> frozenset[str]`

Return the names of top-level {% def %} / {% region %} nodes.

Returns an empty frozenset when no AST is preserved (e.g.
`preserve_ast=False`and no cached AST).

##### Parameters

Name
Type
Description

`optimized_ast`
`—`

##### Returns

`frozenset[str]`

`_get_env_limits`

0

`tuple[int, int]`

▼

Get max_extends_depth and max_include_depth from Environment (or defaults).

`def _get_env_limits(self) -> tuple[int, int]`

##### Returns

`tuple[int, int]`

`_get_max_output_size`

0

`int | None`

▼

Get max_output_size from sandbox policy, if any.

`def _get_max_output_size(self) -> int | None`

##### Returns

`int | None`

`_check_output_size`

1

`str`

▼

Enforce max_output_size if sandbox policy sets one.

`def _check_output_size(self, output: str) -> str`

##### Parameters

Name
Type
Description

`output`
`—`

##### Returns

`str`

`_build_context`

3

`dict[str, Any]`

▼

Build render context from args and kwargs.

Shared by render, render_block, ren…

`def _build_context(self, args: tuple[Any, ...], kwargs: dict[str, Any], method_name: str) -> dict[str, Any]`

Build render context from args and kwargs.

Shared by render, render_block, render_with_blocks, render_stream,
render_stream_async, render_block_stream_async.

##### Parameters

Name
Type
Description

`args`
`—`

`kwargs`
`—`

`method_name`
`—`

##### Returns

`dict[str, Any]`

`_run_globals_setup_chain`

1

▼

Apply ``_globals_setup`` along the ``{% extends %}`` chain.

``_inheritance_cha…

`def _run_globals_setup_chain(self, ctx: dict[str, Any]) -> None`

Apply`_globals_setup` along the `{% extends %}`chain.

`_inheritance_chain()` is `[leaf, parent, …, root]`. Full `render()`
runs each template's top-level statements (imports, defs,`{% let %}`, …)
before calling`_extends`, so effective order is leaf → root; later
templates win on`ctx`name clashes, matching full-page render.

`render_block` / `render_with_blocks`must mirror that order so fragment
scope matches a full page render for HTMX partials.

##### Parameters

Name
Type
Description

`ctx`
`—`

`_missing_block_error`

2

`TemplateRuntimeError`

▼

Build a structured runtime error for missing fragment blocks.

`def _missing_block_error(self, block_name: str, available: list[str] | set[str]) -> TemplateRuntimeError`

##### Parameters

Name
Type
Description

`block_name`
`—`

`available`
`—`

##### Returns

`TemplateRuntimeError`

`_populate_render_capture`

1

▼

Populate active RenderCapture with this template's render metadata.

`def _populate_render_capture(self, ctx: dict[str, Any]) -> None`

##### Parameters

Name
Type
Description

`ctx`
`—`

`_render_scaffold`

6

`Iterator[tuple[dict[str,…`

▼

Common setup for sync render methods.

Builds context, sets up RenderContext, p…

`def _render_scaffold(self, args: tuple[Any, ...], kwargs: dict[str, Any], method_name: str, *, use_cached_blocks: bool = False, enhance_errors: bool = True, run_globals_setup: bool = False) -> Iterator[tuple[dict[str, Any], Any, Any]]`

Common setup for sync render methods.

Builds context, sets up RenderContext, prepares blocks arg, and
optionally enhances exceptions.

##### Parameters

Name
Type
Description

`args`
`—`

`kwargs`
`—`

`method_name`
`—`

`use_cached_blocks`
`—`

Default:`False`

`enhance_errors`
`—`

Default:`True`

`run_globals_setup`
`—`

Default:`False`

##### Returns

`Iterator[tuple[dict[str, Any], Any, Any]]`

`_fragment_scaffold`

3

`Any`

▼

Sync fragment-render scaffold.

Thin forwarder over ``_render_scaffold`` that s…

`def _fragment_scaffold(self, args: tuple[Any, ...], kwargs: dict[str, Any], method_name: str) -> Any`

Sync fragment-render scaffold.

Thin forwarder over`_render_scaffold`that sets
`run_globals_setup=True`so every sync fragment path binds
top-level`{% let %} / {% def %} / {% region %} / {% from … import %}` onto `ctx`in leaf → root order.

Returns the contextmanager directly (no extra generator frame) so
`render_block`stays in the hot path for Bengal-style repeated
fragment rendering.

##### Parameters

Name
Type
Description

`args`
`—`

`kwargs`
`—`

`method_name`
`—`

##### Returns

`Any`

`_fragment_scaffold_async`

3

`AsyncIterator[tuple[dict…`

▼

Async fragment-render scaffold.

Mirrors ``_fragment_scaffold`` for paths that …

async

`async def _fragment_scaffold_async(self, args: tuple[Any, ...], kwargs: dict[str, Any], method_name: str) -> AsyncIterator[tuple[dict[str, Any], Any]]`

Async fragment-render scaffold.

Mirrors`_fragment_scaffold`for paths that must run inside an
`async_render_context`. Owns the `_run_globals_setup_chain`call.

##### Parameters

Name
Type
Description

`args`
`—`

`kwargs`
`—`

`method_name`
`—`

##### Returns

`AsyncIterator[tuple[dict[str, Any], Any]]`

`__repr__`

0

`str`

▼

`def __repr__(self) -> str`

##### Returns

`str`

`RenderedTemplate`

3

▼

Lazy rendered template with streaming support.

Wraps a Template + context pair. Supports both full…

Lazy rendered template with streaming support.

Wraps a Template + context pair. Supports both full rendering
via`str()` and chunk-by-chunk iteration via `for chunk in rt`.

#### Methods

Internal Methods
3

▼

`__init__`

2

▼

`def __init__(self, template: Template, context: dict[str, Any])`

##### Parameters

Name
Type
Description

`template`
`—`

`context`
`—`

`__str__`

0

`str`

▼

Render and return full string.

`def __str__(self) -> str`

##### Returns

`str`

`__iter__`

0

▼

Iterate over rendered HTML chunks via render_stream().

`def __iter__(self)`

## Functions

`_make_error_dict`

1

`ErrorDict`

▼

Build error dict for {% try %}...{% fallback name %} error binding.

`def _make_error_dict(exc: BaseException) -> ErrorDict`

##### Parameters

Name
Type
Description

`exc`
`BaseException`

##### Returns

`ErrorDict`
