Skip to main content

Modern template engine for Python 3.14t — AST-native, free-threading ready

Project description

)彡 Kida

PyPI version Build Status Python 3.14+ License: MIT

Modern template engine for Python 3.14t

from kida import Environment

env = Environment()
template = env.from_string("Hello, {{ name }}!")
print(template.render(name="World"))
# Output: Hello, World!

Why Kida?

  • AST-native — Compiles to Python AST directly, no string generation
  • Free-threading ready — Safe for Python 3.14t concurrent execution (PEP 703)
  • Fast — Benchmarks on 3.14t: 3.6x (minimal), 1.7x (small), 1.1x (medium), ~1.0x (large), 1.2x (complex); cold-start +7-8% with bytecode cache (details in performance docs)
  • Modern syntax — Pattern matching, pipeline operator, unified {% end %}
  • Zero dependencies — Pure Python, includes native Markup implementation

Installation

pip install kida-templates

Requires Python 3.14+


Quick Start

Function Description
Environment() Create a template environment
env.from_string(src) Compile template from string
env.get_template(name) Load template from filesystem
template.render(**ctx) Render with context variables

Features

Feature Description Docs
Template Syntax Variables, filters, control flow, pattern matching Syntax →
Inheritance Template extends, blocks, includes Inheritance →
Filters & Tests 40+ built-in filters, custom filter registration Filters →
Async Support Native async for, await in templates Async →
Caching Fragment caching with TTL support Caching →
Extensibility Custom filters, tests, globals, loaders Extending →

📚 Full documentation: lbliii.github.io/kida


Usage

File-based Templates — Load from filesystem
from kida import Environment, FileSystemLoader

env = Environment(loader=FileSystemLoader("templates/"))
template = env.get_template("page.html")
print(template.render(title="Hello", content="World"))
Template Inheritance — Extend base templates

base.html:

<!DOCTYPE html>
<html>
<body>
    {% block content %}{% end %}
</body>
</html>

page.html:

{% extends "base.html" %}
{% block content %}
    <h1>{{ title }}</h1>
    <p>{{ content }}</p>
{% end %}
Control Flow — Conditionals, loops, pattern matching
{% if user.is_active %}
    <p>Welcome, {{ user.name }}!</p>
{% end %}

{% for item in items %}
    <li>{{ item.name }}</li>
{% end %}

{% match status %}
{% case "active" %}
    Active user
{% case "pending" %}
    Pending verification
{% case _ %}
    Unknown status
{% end %}
Filters & Pipelines — Transform values
{# Traditional syntax #}
{{ title | escape | capitalize | truncate(50) }}

{# Pipeline operator #}
{{ title |> escape |> capitalize |> truncate(50) }}

{# Custom filters #}
{{ items | sort(attribute="name") | first }}
Async Templates — Await in templates
{% async for item in fetch_items() %}
    {{ item }}
{% end %}

{{ await get_user() }}
Fragment Caching — Cache expensive blocks
{% cache "navigation" %}
    {% for item in nav_items %}
        <a href="{{ item.url }}">{{ item.title }}</a>
    {% end %}
{% end %}

Jinja2 Comparison

Feature Kida Jinja2
Compilation AST → AST String generation
Rendering StringBuilder Generator yields
Block endings Unified {% end %} {% endif %}, {% endfor %}
Scoping Explicit let/set/export Implicit
Async Native async for, await auto_await() wrapper
Pattern matching {% match %}...{% case %} N/A
Null coalescing {{ a ?? b }} {{ a | default(b) }}
Optional chaining {{ obj?.attr }} N/A
Pipeline syntax {{ value |> filter }} {{ value | filter }}
Caching {% cache key %}...{% end %} N/A (extension required)
Free-threading Native (PEP 703) N/A

Architecture

Compilation Pipeline — AST-native
Template Source → Lexer → Parser → Kida AST → Compiler → Python AST → exec()

Unlike Jinja2 which generates Python source strings, Kida generates ast.Module objects directly. This enables:

  • Structured code manipulation — Transform and optimize AST nodes
  • Compile-time optimization — Dead code elimination, constant folding
  • Precise error source mapping — Exact line/column in template source
StringBuilder Rendering — O(n) output
# Kida's approach (O(n))
_out.append(...)
return "".join(_out)

# vs Jinja2's approach (higher overhead)
yield ...

25-40% faster than Jinja2's generator yield pattern for typical templates.

Thread Safety — Free-threading ready

All public APIs are thread-safe by design:

  • Template compilation — Idempotent (same input → same output)
  • Rendering — Uses only local state (StringBuilder pattern)
  • Environment — Copy-on-write for filters/tests/globals
  • LRU caches — Atomic operations

Module declares itself GIL-independent via _Py_mod_gil = 0 (PEP 703).


Performance

Metric Kida Jinja2 Improvement
Simple render 0.12ms 0.18ms 33% faster
Complex template 2.1ms 3.2ms 34% faster
Concurrent (8 threads) 0.15ms avg GIL contention Free-threading

Documentation

📚 lbliii.github.io/kida

Section Description
Get Started Installation and quickstart
Syntax Template language reference
Usage Loading, rendering, escaping
Extending Custom filters, tests, loaders
Reference Complete API documentation
Tutorials Jinja2 migration, Flask integration

Development

git clone https://github.com/lbliii/kida.git
cd kida
# Uses Python 3.14t by default (.python-version)
uv sync --group dev --python 3.14t
PYTHON_GIL=0 uv run --python 3.14t pytest

License

MIT License — see LICENSE for details.

Project details


Download files

Download the file for your platform. If you're not sure which to choose, learn more about installing packages.

Source Distribution

kida_templates-0.1.0.tar.gz (238.2 kB view details)

Uploaded Source

Built Distribution

If you're not sure about the file name format, learn more about wheel file names.

kida_templates-0.1.0-py3-none-any.whl (170.9 kB view details)

Uploaded Python 3

File details

Details for the file kida_templates-0.1.0.tar.gz.

File metadata

  • Download URL: kida_templates-0.1.0.tar.gz
  • Upload date:
  • Size: 238.2 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? No
  • Uploaded via: uv/0.9.24 {"installer":{"name":"uv","version":"0.9.24","subcommand":["publish"]},"python":null,"implementation":{"name":null,"version":null},"distro":{"name":"macOS","version":null,"id":null,"libc":null},"system":{"name":null,"release":null},"cpu":null,"openssl_version":null,"setuptools_version":null,"rustc_version":null,"ci":null}

File hashes

Hashes for kida_templates-0.1.0.tar.gz
Algorithm Hash digest
SHA256 4110ce5713e3e3c05fa79ffff4602045e1a602a28f5be664a37eb16b48a29717
MD5 d6cc2ba9c789498a4cf9e7342f47fe87
BLAKE2b-256 732f3c86133bce6128b2b8cad898f52cd527a5019d7e59c8329b53955886dadc

See more details on using hashes here.

File details

Details for the file kida_templates-0.1.0-py3-none-any.whl.

File metadata

  • Download URL: kida_templates-0.1.0-py3-none-any.whl
  • Upload date:
  • Size: 170.9 kB
  • Tags: Python 3
  • Uploaded using Trusted Publishing? No
  • Uploaded via: uv/0.9.24 {"installer":{"name":"uv","version":"0.9.24","subcommand":["publish"]},"python":null,"implementation":{"name":null,"version":null},"distro":{"name":"macOS","version":null,"id":null,"libc":null},"system":{"name":null,"release":null},"cpu":null,"openssl_version":null,"setuptools_version":null,"rustc_version":null,"ci":null}

File hashes

Hashes for kida_templates-0.1.0-py3-none-any.whl
Algorithm Hash digest
SHA256 d5aa81ac300c9dd0a609be0f85b0b61f8cf4be94e5d2c105500a5d50d252c9f9
MD5 0ee65685e57e2c626715d6b0a9bc19ca
BLAKE2b-256 d347a6d7b39d5fbcd4e02c8375d53340c350e4719f0ad1e69279d3431e833293

See more details on using hashes here.

Supported by

AWS Cloud computing and Security Sponsor Datadog Monitoring Depot Continuous Integration Fastly CDN Google Download Analytics Pingdom Monitoring Sentry Error logging StatusPage Status page