Skip to main content

Static type checking for Jinja templates

Project description

jinja-typed-template

Type-safe Jinja2 templates with compile-time validation — keep your Python code and Jinja templates in sync, fail fast on mismatches, and never ship a broken template again.

Installation

pip install jinja-typed-template

For Flask support:

pip install jinja-typed-template[flask]

Quick Start

1. Annotate your template

Add a header comment declaring every variable the template uses, along with its type:

{#
    name: str
    age: int
    items: list[str]
#}
<h1>Hello {{ name }}!</h1>
<p>You are {{ age }} years old.</p>
<ul>
  {% for item in items %}
    <li>{{ item }}</li>
  {% endfor %}
</ul>

2. Define a typed template class

Subclass TypedTemplate, set the template name, and declare fields with type hints:

from jinja_typed_template import TypedTemplate, env_context
from jinja2 import Environment, FileSystemLoader

class ProfileTemplate(TypedTemplate):
    __template_name__ = "profile.html"
    name: str
    age: int
    items: list[str]

3. Render safely

Wrap usage in env_context to bind a Jinja2 environment, then instantiate and render:

env = Environment(loader=FileSystemLoader("templates"))

with env_context(env):
    t = ProfileTemplate(name="Alice", age=30, items=["apples", "bananas"])
    print(t.render())

What Gets Validated

Every TypedTemplate instance is validated at construction time (__post_init__). Three checks run automatically:

Check Catches
Type checking T(name=123) when name: str — raises TypeError
Variable matching Missing or extra fields vs. what the template actually uses — raises ValueError
Header comment consistency Header declares name: int but class says name: str — raises TypeError

This means you catch mismatches the moment you create the object, not when a user hits the page.

API Reference

TypedTemplate

Base class. Subclass it, set __template_name__, and declare typed fields.

Member Description
render() Render the template to a string
context_dict Dict of all field names → values
copy_updating(**kwargs) Return a new instance with some fields replaced (instances are frozen/immutable)

env_context(env)

Context manager that binds a Jinja2 Environment for the current thread/context. Required before creating or rendering any TypedTemplate.

from jinja_typed_template import env_context

with env_context(env):
    t = MyTemplate(...)

TypedTemplateExtension (Flask)

Flask extension that automatically pushes the app's Jinja2 environment into the context on every request. Context-processor variables are also discovered and excluded from validation, so they can appear in templates without being declared in the header.

from flask import Flask
from jinja_typed_template.extension_flask import TypedTemplateExtension

app = Flask(__name__)
ext = TypedTemplateExtension()
ext.init_app(app)

# Context-processor variables are automatically recognised:
@app.context_processor
def inject_globals():
    return {"app_name": "MyApp"}

Now any TypedTemplate instantiated inside a request will just work — no manual env_context needed.

Header Comment Format

Place a Jinja2 comment at the very top of the template:

{#
    variable_name: TypeName
    another_var: list[str]
    optional_var: str = "default"
#}
  • variable_name must match a field on your TypedTemplate subclass.
  • TypeName uses a short-form representation (str, int, list[str], dict[str, int], etc.) and must match the Python type hint.
  • Default values after = are stripped — they're documentation only.

License

MIT

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

jinja_typed_template-0.2.0.tar.gz (11.9 kB view details)

Uploaded Source

Built Distribution

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

jinja_typed_template-0.2.0-py3-none-any.whl (9.0 kB view details)

Uploaded Python 3

File details

Details for the file jinja_typed_template-0.2.0.tar.gz.

File metadata

  • Download URL: jinja_typed_template-0.2.0.tar.gz
  • Upload date:
  • Size: 11.9 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? No
  • Uploaded via: uv/0.11.17 {"installer":{"name":"uv","version":"0.11.17","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 jinja_typed_template-0.2.0.tar.gz
Algorithm Hash digest
SHA256 a66edc1401751ad122cfdf4cc52fc4d208f5001d44e9b187ecc1c0956e3c7d66
MD5 935aeff231e9fbecd2cff6fa22803010
BLAKE2b-256 2e8927dddb8dd727584ec0bc8379ee815c86a06a5b442aeb2b5d6ea29137f6f9

See more details on using hashes here.

File details

Details for the file jinja_typed_template-0.2.0-py3-none-any.whl.

File metadata

  • Download URL: jinja_typed_template-0.2.0-py3-none-any.whl
  • Upload date:
  • Size: 9.0 kB
  • Tags: Python 3
  • Uploaded using Trusted Publishing? No
  • Uploaded via: uv/0.11.17 {"installer":{"name":"uv","version":"0.11.17","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 jinja_typed_template-0.2.0-py3-none-any.whl
Algorithm Hash digest
SHA256 0e46b6cfdd59ebb2a219860f523aa95293919122dc33a50c9d191a56cd5ce5e3
MD5 84b265bedb17512abc5e0dc126002953
BLAKE2b-256 8f1427543016857666c762c72b370a4b70a28867e21f27c604e9511f088e912d

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