Module

render_context

Kida RenderContext — per-render state isolated from user context.

This module implements ContextVar-based render state management, replacing the internal keys (_template, _line, _include_depth, _cached_blocks, _cached_stats) that were previously injected into the user's ctx dict.

Benefits:

  • Clean user context (no internal key pollution)
  • No key collision risk (user can use _template as variable)
  • Centralized state management
  • Thread-safe via ContextVar
  • Async-safe (ContextVars propagate to asyncio.to_thread in Python 3.14)

RFC: kida-contextvar-patterns

Classes

_NullRenderContext 1
Lightweight stub used when generated code runs outside a render context. Silently absorbs `_rc.lin…

Lightweight stub used when generated code runs outside a render context.

Silently absorbs_rc.line = Nassignments without raising. Provides safe no-opcomponent_stack and template_namefor generated def code that pushes/pops component stack frames.

Methods

Internal Methods 1
__init__ 0
def __init__(self) -> None
RenderContext 26
Per-render state isolated from user context. Replaces the _template, _line, _include_depth, _cache…

Per-render state isolated from user context.

Replaces the _template, _line, _include_depth, _cached_blocks, and _cached_stats keys that were previously injected into the user's ctx dict.

Thread Safety: ContextVars are thread-local by design. Each thread/async task has its own RenderContext instance.

Async Safety: ContextVars propagate correctly to asyncio.to_thread() in Python 3.14, so render_async() works without special handling.

Context Contracts:

  • ctx (render context): User-provided dict passed to render(**ctx).
    Framework keys (e.g. ``site``, ``page``) are documented by the framework.
    
  • _meta: Framework metadata (HTMX, CSRF, etc.). See get_meta().

Attributes

Name Type Description
template_name str | None

Current template name for error messages

filename str | None

Source file path for error messages

source str | None
line int

Current line number (updated during render by generated code)

include_depth int

Current include/embed depth (DoS protection)

max_include_depth int

Maximum allowed include depth

extends_depth int
max_extends_depth int
template_stack list[tuple[str, int]]

Stack of (template_name, line) for error traces

component_stack list[tuple[str, int, str]]
cached_blocks dict[str, str]

Site-scoped block cache (shared across includes)

cached_block_names frozenset[str]

Frozenset of cached block names for O(1) lookup

cache_stats dict[str, int] | None

Optional dict for cache hit/miss tracking

import_stack list[str]
_stacks dict[str, list[str]]
_providers dict[str, list[Any]]
_meta dict[str, object]

Methods

get_meta 2 object
Get framework-specific metadata. Used by frameworks (like Chirp) to pass reque…
def get_meta(self, key: str, default: object = None) -> object

Get framework-specific metadata.

Used by frameworks (like Chirp) to pass request context into templates.

Commonly used for:

  • HTMX headers: hx_request, hx_target, hx_trigger, hx_boosted
  • Security: csrf_token
  • User context: current_user, permissions
Parameters
Name Type Description
key

Metadata key

default

Value to return if key not found

Default:None
Returns
object Metadata value or default
set_meta 2
Set framework-specific metadata.
def set_meta(self, key: str, value: object) -> None
Parameters
Name Type Description
key

Metadata key

value

Metadata value

provide 2
Push a value onto the provider stack for *key*. Used by ``{% provide key = exp…
def provide(self, key: str, value: Any) -> None

Push a value onto the provider stack for key.

Used by{% provide key = expr %}. Stack-based so nested provides shadow outer ones for the same key.

Parameters
Name Type Description
key
value
unprovide 1
Pop the most recent value for *key* from the provider stack. Called in the ``f…
def unprovide(self, key: str) -> None

Pop the most recent value for key from the provider stack.

Called in thefinally block of compiled {% provide %}to guarantee cleanup even when the body raises.

Parameters
Name Type Description
key
consume 2 Any
Read the current value for *key* from the nearest provider. Returns *default* …
def consume(self, key: str, default: Any = None) -> Any

Read the current value for key from the nearest provider.

Returns default if no provider is active for key. Used by theconsume()template function.

Parameters
Name Type Description
key
default Default:None
Returns
Any
check_include_depth 1
Check if include depth limit exceeded.
def check_include_depth(self, template_name: str) -> None
Parameters
Name Type Description
template_name

Name of template being included

check_extends_depth 1
Check if extends chain depth limit exceeded.
def check_extends_depth(self, template_name: str) -> None
Parameters
Name Type Description
template_name

Name of parent template being extended

child_context 2 RenderContext
Create child context for include/embed with incremented depth. Shares cached_b…
def child_context(self, template_name: str | None = None, *, source: str | None = None) -> RenderContext

Create child context for include/embed with incremented depth.

Shares cached_blocks, cache_stats, and _meta with parent (they're document-wide). Child gets a copy of import_stack to avoid shared mutable state under parallel rendering.

Parameters
Name Type Description
template_name

Optional override for child template name

Default:None
source

Optional template source for error snippets in child

Default:None
Returns
RenderContext New RenderContext with incremented include_depth and updated stack
child_context_for_extends 2 RenderContext
Create child context for extends with incremented extends_depth. Used when ren…
def child_context_for_extends(self, parent_name: str, *, source: str | None = None) -> RenderContext

Create child context for extends with incremented extends_depth.

Used when rendering a parent template from {% extends %}. Shares cached_blocks, cache_stats, etc. Does not increment include_depth.

Parameters
Name Type Description
parent_name

Name of parent template being extended

source

Optional template source for error snippets in parent

Default:None
Returns
RenderContext

Functions

get_render_context 0 RenderContext | None
Get current render context (None if not in render).
def get_render_context() -> RenderContext | None
Returns
RenderContext | None
get_render_context_required 0 RenderContext
Get current render context, raise if not in render. Used by generated code for…
def get_render_context_required() -> RenderContext

Get current render context, raise if not in render.

Used by generated code for line tracking.

Returns
RenderContext
_make_render_context 8 RenderContext
Construct and return a RenderContext from the given parameters. Shared by rend…
def _make_render_context(template_name: str | None = None, filename: str | None = None, source: str | None = None, cached_blocks: dict[str, str] | None = None, cache_stats: dict[str, int] | None = None, parent_meta: dict[str, object] | None = None, max_extends_depth: int = 50, max_include_depth: int = 50) -> RenderContext

Construct and return a RenderContext from the given parameters.

Shared by render_context() and async_render_context(). Does NOT touch the ContextVar — callers are responsible for set/reset.

Parameters
Name Type Description
template_name str | None

Template name for error messages

Default:None
filename str | None

Source file path for error messages

Default:None
source str | None

Template source for runtime error snippets

Default:None
cached_blocks dict[str, str] | None

Site-scoped block cache

Default:None
cache_stats dict[str, int] | None

Optional dict for cache hit/miss tracking

Default:None
parent_meta dict[str, object] | None

Metadata from parent context to inherit (for framework integration)

Default:None
max_extends_depth int

Maximum extends nesting depth

Default:50
max_include_depth int

Maximum include nesting depth

Default:50
Returns
RenderContext
render_context 8 Iterator[RenderContext]
Context manager for render-scoped state. Creates a new RenderContext and sets …
def render_context(template_name: str | None = None, filename: str | None = None, source: str | None = None, cached_blocks: dict[str, str] | None = None, cache_stats: dict[str, int] | None = None, parent_meta: dict[str, object] | None = None, max_extends_depth: int = 50, max_include_depth: int = 50) -> Iterator[RenderContext]

Context manager for render-scoped state.

Creates a new RenderContext and sets it as the current context for the duration of the with block. Automatically restores the previous context when exiting.

Parameters
Name Type Description
template_name str | None

Template name for error messages

Default:None
filename str | None

Source file path for error messages

Default:None
source str | None

Template source for runtime error snippets

Default:None
cached_blocks dict[str, str] | None

Site-scoped block cache

Default:None
cache_stats dict[str, int] | None

Optional dict for cache hit/miss tracking

Default:None
parent_meta dict[str, object] | None

Metadata from parent context to inherit (for framework integration)

Default:None
max_extends_depth int Default:50
max_include_depth int Default:50
Returns
Iterator[RenderContext]
async_render_context 8 AsyncIterator[RenderCont…
Async context manager for render-scoped state. Identical to render_context() b…
async
async def async_render_context(template_name: str | None = None, filename: str | None = None, source: str | None = None, cached_blocks: dict[str, str] | None = None, cache_stats: dict[str, int] | None = None, parent_meta: dict[str, object] | None = None, max_extends_depth: int = 50, max_include_depth: int = 50) -> AsyncIterator[RenderContext]

Async context manager for render-scoped state.

Identical to render_context() but for use withasync with. ContextVar reset is synchronous — the async wrapper is structural only.

Part of RFC: rfc-async-rendering.

Parameters
Name Type Description
template_name str | None

Template name for error messages

Default:None
filename str | None

Source file path for error messages

Default:None
source str | None

Template source for runtime error snippets

Default:None
cached_blocks dict[str, str] | None

Site-scoped block cache

Default:None
cache_stats dict[str, int] | None

Optional dict for cache hit/miss tracking

Default:None
parent_meta dict[str, object] | None

Metadata from parent context to inherit (for framework integration)

Default:None
max_extends_depth int Default:50
max_include_depth int Default:50
Returns
AsyncIterator[RenderContext]
set_render_context 1 Token[RenderContext | No…
Set a RenderContext and return the reset token. Low-level function for cases w…
def set_render_context(ctx: RenderContext) -> Token[RenderContext | None]

Set a RenderContext and return the reset token.

Low-level function for cases where the context manager isn't suitable (e.g., nested include/embed calls that need to restore context manually).

Parameters
Name Type Description
ctx RenderContext

The RenderContext to set

Returns
Token[RenderContext | None]
reset_render_context 1 None
Reset render context using a token from set_render_context.
def reset_render_context(token: Token[RenderContext | None]) -> None
Parameters
Name Type Description
token Token[RenderContext | None]

Token returned from set_render_context()