Skip to main content

An experimental Python binding of the Rust MiniJinja template engine.

Project description

MiniJinja for Python: a powerful template engine for Rust and Python

License Crates.io rustc 1.63.0 Documentation

minijinja-py is an experimental binding of MiniJinja to Python. It has somewhat limited functionality compared to the Rust version. These bindings use maturin and pyo3.

You might want to use MiniJinja instead of Jinja2 when the full feature set of Jinja2 is not required and you want to have the same rendering experience of a data set between Rust and Python.

With these bindings MiniJinja can render some Python objects and values that are passed to templates, but there are clear limitations with regards to what can be done.

To install MiniJinja for Python you can fetch the package from PyPI:

$ pip install minijinja

Basic API

The basic API is hidden behind the Environment object. It behaves almost entirely like in minijinja with some Python specific changes. For instance instead of env.set_debug(True) you use env.debug = True. Additionally instead of using add_template or attaching a source you either pass a dictionary of templates directly to the environment or a loader function.

from minijinja import Environment

env = Environment(templates={
    "template_name": "Template source"
})

To render a template you can use the render_template method:

result = env.render_template('template_name', var1="value 1", var2="value 2")
print(result)

Purpose

MiniJinja attempts a reasonably high level of compatibility with Jinja2, but it does not try to achieve this at all costs. As a result you will notice that quite a few templates will refuse to render with MiniJinja despite the fact that they probably look quite innocent. It is however possible to write templates that render to the same results for both Jinja2 and MiniJinja. This raises the question why you might want to use MiniJinja.

The main benefit would be to achieve the exact same results in both Rust and Python. Additionally MiniJinja has a stronger sandbox than Jinja2 and might perform ever so slightly better in some situations. However you should be aware that due to the marshalling that needs to happen in either direction there is a certain amount of loss of information.

Dynamic Template Loading

MiniJinja's Python bindings inherit the underlying behavior of how MiniJinja loads templates. Templates are loaded on first use and then cached. The templates are loaded via a loader. To trigger a reload you can call env.reload() or alternatively set env.reload_before_render to True.

def my_loader(name):
    segments = []
    for segment in name.split("/"):
        if "\\" in segment or segment in (".", ".."):
            return None
        segments.append(segment)
    try:
        with open(os.path.join(TEMPLATES, *segments)) as f:
            return f.read()
    except (IOError, OSError):
        pass

env = Environment(loader=my_loader)
env.reload_before_render = True
print(env.render_template("index.html"))

Alternatively templates can manually be loaded and unloaded with env.add_template and env.remove_template.

Auto Escaping

The default behavior is to use auto escaping file files ending in .html. You can customize this behavior by overriding the auto_escape_callback:

env = Environment(auto_escape_callback=lambda x: x.endswith((".html", ".foo")))

MiniJinja uses markupsafe if it's available on the Python side. It will honor __html__.

Finalizers

Instead of custom formatters like in MiniJinja, you can define a finalizer instead which is similar to how it works in Jinja2. It's passed a value (or optional also the state as first argument when pass_state is used) and can return a new value. If the special NotImplemented value is returned, the original value is rendered without any modification:

from minijinja import Environment

def finalizer(value):
    if value is None:
	return ""
    return NotImplemented

env = Environment(finalizer=finalizer)
assert env.render_str("{{ none }}") == ""

State Access

Functions passed to the environment such as filters or global functions can optionally have the template state passed by using the pass_state parameter. This is similar to pass_context in Jinja2. It can be used to look at the name of the template or to look up variables in the context.

from minijinja import pass_state

@pass_state
def my_filter(state, value):
    return state.lookup("a_variable") + value

env.add_filter("add_a_variable", my_filter)

Runtime Behavior

MiniJinja uses it's own runtime model which is not matching the Python runtime model. As a result there are gaps in behavior between the two but some limited effort is made to bridge them. For instance you will be able to call some methods of types, but for instance builtins such as dicts and lists do not expose their methods on the MiniJinja side in all cases. A natively generated MiniJinja map (such as with the dict global function) will not have an .items() method, whereas a Python dict passed to MiniJinja will.

Here is what this means for some basic types:

  • Python dictionaries and lists (as well as other objects that behave as sequences) appear in the MiniJinja side very similar to how they do in Python.
  • Tuples on the MiniJinja side are represented as lists, but will appear again as tuples if passed back to Python.
  • Python objects are represented in MiniJinja similarly to dicts, but they retain all their meaningful Python APIs. This means they stringify via __str__ and they allow the MiniJinja code to call their non-underscored methods. Note that there is no extra security layer in use at the moment so take care of what you pass there.
  • MiniJinja's python binding understand what __html__ is when it exists on a string subclass. This means that a markupsafe.Markup object will appear as safe string in MiniJinja. This information can also flow back to Python again.
  • Stringification of objects uses __str__ which is why mixed Python and MiniJinja objects can be a bit confusing at times.
  • Where in Jinja2 there is a difference between foo["bar"] and foo.bar which can be used to disambiugate properties and keys, in MiniJinja there is no such difference. However methods are disambiugated so foo.items() works and will correctly call the method in all cases.
  • Operator overloading is not supported. This in particular means that operators like + will not invoke the __add__ method of most objects. This is an intentional limitation of the engine.
  • When MiniJinja objects are exposed to the Python side they lose most of their functionality. For instance plain objects such as functions are currently just represented as strings, maps are dictionaries etc. This also means you cannot call methods on them from the Python side.

Threading

MiniJinja's Python bindin is thread-safe but it uses locks internally on the environment. In particular only one thread can render a template from the same environment at the time. If you want to render templates from multiple threads you should be creating a new environment for each thread.

Sponsor

If you like the project and find it useful you can become a sponsor.

License and Links

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

minijinja-2.11.0.tar.gz (273.0 kB view details)

Uploaded Source

Built Distributions

minijinja-2.11.0-cp38-abi3-win_amd64.whl (992.0 kB view details)

Uploaded CPython 3.8+Windows x86-64

minijinja-2.11.0-cp38-abi3-win32.whl (939.6 kB view details)

Uploaded CPython 3.8+Windows x86

minijinja-2.11.0-cp38-abi3-manylinux_2_17_x86_64.manylinux2014_x86_64.whl (1.1 MB view details)

Uploaded CPython 3.8+manylinux: glibc 2.17+ x86-64

minijinja-2.11.0-cp38-abi3-manylinux_2_17_armv7l.manylinux2014_armv7l.whl (984.0 kB view details)

Uploaded CPython 3.8+manylinux: glibc 2.17+ ARMv7l

minijinja-2.11.0-cp38-abi3-manylinux_2_17_aarch64.manylinux2014_aarch64.whl (996.8 kB view details)

Uploaded CPython 3.8+manylinux: glibc 2.17+ ARM64

minijinja-2.11.0-cp38-abi3-manylinux_2_5_i686.manylinux1_i686.whl (1.1 MB view details)

Uploaded CPython 3.8+manylinux: glibc 2.5+ i686

minijinja-2.11.0-cp38-abi3-macosx_10_12_x86_64.macosx_11_0_arm64.macosx_10_12_universal2.whl (1.9 MB view details)

Uploaded CPython 3.8+macOS 10.12+ universal2 (ARM64, x86-64)macOS 10.12+ x86-64macOS 11.0+ ARM64

File details

Details for the file minijinja-2.11.0.tar.gz.

File metadata

  • Download URL: minijinja-2.11.0.tar.gz
  • Upload date:
  • Size: 273.0 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? No
  • Uploaded via: maturin/1.9.0

File hashes

Hashes for minijinja-2.11.0.tar.gz
Algorithm Hash digest
SHA256 20f6ffdcffc89161b1c9948db4c76bc180fed62c303391ace101df99acaab61c
MD5 86de8df51db645006fcf8251c1b78314
BLAKE2b-256 523ee5fa572176a4c3cd4661191a762a7a1d286c05cd2d8fa977acb6353dfa9f

See more details on using hashes here.

File details

Details for the file minijinja-2.11.0-cp38-abi3-win_amd64.whl.

File metadata

File hashes

Hashes for minijinja-2.11.0-cp38-abi3-win_amd64.whl
Algorithm Hash digest
SHA256 a3f9ad56641ed88c89d5f0e67466d1c272b2c694f3fc92d159fce1ab0f03b2f7
MD5 9b97b70663bf76570812d088e848e778
BLAKE2b-256 488203017e08ce09b8c74f3a95fa6daaa5e5c8dea7949a772e66ee91fa030313

See more details on using hashes here.

File details

Details for the file minijinja-2.11.0-cp38-abi3-win32.whl.

File metadata

  • Download URL: minijinja-2.11.0-cp38-abi3-win32.whl
  • Upload date:
  • Size: 939.6 kB
  • Tags: CPython 3.8+, Windows x86
  • Uploaded using Trusted Publishing? No
  • Uploaded via: maturin/1.9.0

File hashes

Hashes for minijinja-2.11.0-cp38-abi3-win32.whl
Algorithm Hash digest
SHA256 62a162271723a14b0df1d3cd1fbf4657dc3f1268c98eba3f143ee81199b981df
MD5 9b1d56dbbff4e8739b6d79c709d82a7c
BLAKE2b-256 aa905c855effcde1678c13a8836d3801002ab59b2e2d90a7f987391759c633ac

See more details on using hashes here.

File details

Details for the file minijinja-2.11.0-cp38-abi3-manylinux_2_17_x86_64.manylinux2014_x86_64.whl.

File metadata

File hashes

Hashes for minijinja-2.11.0-cp38-abi3-manylinux_2_17_x86_64.manylinux2014_x86_64.whl
Algorithm Hash digest
SHA256 e606bd731364797d77b97d00d9b2dac15ffba15e03c3d075363f857d81cf91e0
MD5 779ce6ff2b016f4bc7400fbaf697c82f
BLAKE2b-256 b94c7daca19d79a0d9ad231aea1c42a60146eb60ed11f2b91ab96d5c207ae894

See more details on using hashes here.

File details

Details for the file minijinja-2.11.0-cp38-abi3-manylinux_2_17_armv7l.manylinux2014_armv7l.whl.

File metadata

File hashes

Hashes for minijinja-2.11.0-cp38-abi3-manylinux_2_17_armv7l.manylinux2014_armv7l.whl
Algorithm Hash digest
SHA256 e0d9b3cd53ce6cc58b4ddba6ff57085736c35b86fd8a4dc92e3b04a1c9f45eaf
MD5 7d7a81f99069845ab69ebba156ed51cd
BLAKE2b-256 be52cdf0dd5413ebe319ad86923e3ef9e4fe945c5a1d1b324df02aab7944dd84

See more details on using hashes here.

File details

Details for the file minijinja-2.11.0-cp38-abi3-manylinux_2_17_aarch64.manylinux2014_aarch64.whl.

File metadata

File hashes

Hashes for minijinja-2.11.0-cp38-abi3-manylinux_2_17_aarch64.manylinux2014_aarch64.whl
Algorithm Hash digest
SHA256 630fa6964392ce9be4b2499fb50142281c8d444450e1ededffb1b6c92dec2788
MD5 d7c3c4173e0de49521aaf3ec0ae413a5
BLAKE2b-256 fde94957061f56d7c0540069209885709ca7d2d01f7b4a499188bca93ca8621e

See more details on using hashes here.

File details

Details for the file minijinja-2.11.0-cp38-abi3-manylinux_2_5_i686.manylinux1_i686.whl.

File metadata

File hashes

Hashes for minijinja-2.11.0-cp38-abi3-manylinux_2_5_i686.manylinux1_i686.whl
Algorithm Hash digest
SHA256 fa3c5c22ddf035e71890a2a4615b0637aca08f5eeb03192ea321b395c5439833
MD5 03fac7df9e8740bcd4c83eb3799098b9
BLAKE2b-256 7922c79fe9a127340f62c4d9b54c8957475857e90e536044c0409616afec0add

See more details on using hashes here.

File details

Details for the file minijinja-2.11.0-cp38-abi3-macosx_10_12_x86_64.macosx_11_0_arm64.macosx_10_12_universal2.whl.

File metadata

File hashes

Hashes for minijinja-2.11.0-cp38-abi3-macosx_10_12_x86_64.macosx_11_0_arm64.macosx_10_12_universal2.whl
Algorithm Hash digest
SHA256 900ad73945ed7bc5c371e0fd4e6faf1fb6a6aaa413575d90f82fcad6b80e199c
MD5 52aea4283a3c4813c962b9d3fb215a64
BLAKE2b-256 69d89520c28494d46a42a6a2d6187233433d783aca3b689dc90ea77f27311a0a

See more details on using hashes here.

Supported by

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