Kida 0.1.2

RenderContext isolation and profiling

Released: January 13, 2026

ContextVar-based state isolation and opt-in profiling for template rendering.

Highlights

  • 🔒 RenderContext — Per-render state isolated from user context
  • 📊 RenderAccumulator — Opt-in profiling with zero overhead when disabled
  • F-string coalescing — 11% faster output-heavy templates
  • 🧹 Clean user context — No more internal key pollution

Added

RenderContext

ContextVar-based per-render state management that isolates internal state from user context:

from kida import get_render_context

# During render, access render state without ctx pollution
ctx = get_render_context()
print(ctx.template_name)  # Current template
print(ctx.line)           # Current line number
print(ctx.include_depth)  # Include nesting level

Benefits:

  • Userctx dicts are now clean (no _template, _line, etc.)
  • No key collision risk (users can use_templateas a variable)
  • Thread-safe via ContextVar
  • Async-safe (ContextVars propagate toasyncio.to_threadin Python 3.14)

RenderAccumulator

Opt-in profiling for debugging slow templates:

from kida import profiled_render

with profiled_render() as metrics:
    html = template.render(page=page)

print(metrics.summary())
# {
#   "total_ms": 12.5,
#   "blocks": {"content": {"ms": 8.2, "calls": 1}},
#   "macros": {"render_card": 15},
#   "includes": {"partials/sidebar.html": 1},
#   "filters": {"escape": 45, "truncate": 12},
# }

Zero overhead when profiling is disabled — get_accumulator() returns None.

F-string Coalescing

Consecutive template outputs are merged into single f-string appends:

# Before: Multiple append calls
_out.append(escape(x))
_out.append(" - ")
_out.append(escape(y))

# After: Single f-string append
_out.append(f"{escape(x)} - {escape(y)}")

~11% faster for output-heavy templates. Controlled via:

  • Environment.fstring_coalescing(enabled by default)
  • Environment.pure_filtersfor custom filter registration

Public API Exports

New exports fromkida:

  • RenderContext, render_context, get_render_context, get_render_context_required
  • RenderAccumulator, profiled_render, get_accumulator, timed_block

Changed

Clean User Context

Template rendering no longer injects internal keys into user context:

Before (0.1.1) After (0.1.2)
ctx["_template"] get_render_context().template_name
ctx["_line"] get_render_context().line
ctx["_include_depth"] get_render_context().include_depth

Users can now safely use_template or _lineas variable names.

Removed

{% do %}Directive

The{% do %} directive has been removed. Use {% set _ = expr %}for side effects:

{# Before #}
{% do my_list.append(item) %}

{# After #}
{% set _ = my_list.append(item) %}

Upgrade Guide

  1. If using{% do %}: Replace with {% set _ = expr %}
  2. If accessingctx["_template"]: Use get_render_context().template_name
  3. If using internal keys as variables: No changes needed (collision risk removed)