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

Build Status 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.

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.5.0.tar.gz (218.4 kB view details)

Uploaded Source

Built Distributions

minijinja-2.5.0-cp38-abi3-win_amd64.whl (868.5 kB view details)

Uploaded CPython 3.8+ Windows x86-64

minijinja-2.5.0-cp38-abi3-win32.whl (820.1 kB view details)

Uploaded CPython 3.8+ Windows x86

minijinja-2.5.0-cp38-abi3-manylinux_2_17_x86_64.manylinux2014_x86_64.whl (915.6 kB view details)

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

minijinja-2.5.0-cp38-abi3-manylinux_2_17_armv7l.manylinux2014_armv7l.whl (849.6 kB view details)

Uploaded CPython 3.8+ manylinux: glibc 2.17+ ARMv7l

minijinja-2.5.0-cp38-abi3-manylinux_2_17_aarch64.manylinux2014_aarch64.whl (856.0 kB view details)

Uploaded CPython 3.8+ manylinux: glibc 2.17+ ARM64

minijinja-2.5.0-cp38-abi3-manylinux_2_5_i686.manylinux1_i686.whl (991.0 kB view details)

Uploaded CPython 3.8+ manylinux: glibc 2.5+ i686

minijinja-2.5.0-cp38-abi3-macosx_10_12_x86_64.macosx_11_0_arm64.macosx_10_12_universal2.whl (1.7 MB view details)

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

File details

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

File metadata

  • Download URL: minijinja-2.5.0.tar.gz
  • Upload date:
  • Size: 218.4 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? No
  • Uploaded via: uv/0.4.30

File hashes

Hashes for minijinja-2.5.0.tar.gz
Algorithm Hash digest
SHA256 ca97a8d8053aa0111f855d6706883dbfdbda600bd2dd0e152c03077a42c003e3
MD5 3126d0eab5bca9d17a8544740515ffce
BLAKE2b-256 c80e7b76e4a45d5665047bb288a3e5f2520f25a691be58a1662e5a0ca80ae5b5

See more details on using hashes here.

File details

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

File metadata

File hashes

Hashes for minijinja-2.5.0-cp38-abi3-win_amd64.whl
Algorithm Hash digest
SHA256 1ddd1941d0fbf84dbce103f65a3e04eba7d958d08e399f6d3c63bce2fbc1ae0c
MD5 c5ea9d914080617f8874a43c6bbcf881
BLAKE2b-256 928b67c5fc89ec9eec5872e222f28671c36963c635d1d22ad93ecd9ee766d279

See more details on using hashes here.

File details

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

File metadata

  • Download URL: minijinja-2.5.0-cp38-abi3-win32.whl
  • Upload date:
  • Size: 820.1 kB
  • Tags: CPython 3.8+, Windows x86
  • Uploaded using Trusted Publishing? No
  • Uploaded via: uv/0.4.30

File hashes

Hashes for minijinja-2.5.0-cp38-abi3-win32.whl
Algorithm Hash digest
SHA256 d393ca982b5189c2a8f42b82612170885b48f500e4afac6dc127e980b286b798
MD5 696299db2f14b36eef21427470c5ed0d
BLAKE2b-256 86b8208121205af6cc20f802a29df4312d75f332a7501c13ed73790e9fc3df82

See more details on using hashes here.

File details

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

File metadata

File hashes

Hashes for minijinja-2.5.0-cp38-abi3-manylinux_2_17_x86_64.manylinux2014_x86_64.whl
Algorithm Hash digest
SHA256 369d6ed56b571feb25f84b87eec0fb286b1931bb472eed1f148ca69777c596d3
MD5 63816d9d5860a5f796791858d5b9d9f2
BLAKE2b-256 843f6ad712c2943f44781a72d6927063e9c8c4540555d9a5fd92154cf9de8145

See more details on using hashes here.

File details

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

File metadata

File hashes

Hashes for minijinja-2.5.0-cp38-abi3-manylinux_2_17_armv7l.manylinux2014_armv7l.whl
Algorithm Hash digest
SHA256 516e84a4f03b81002fd0eea966341b8c12fd9ebc4b222dc6ebc50a2b7535df13
MD5 e05f13889f02772a1d54f535a0851510
BLAKE2b-256 663f22a11b8ba1f6c514ab50c64d2cbeccc20cf1bc43e1ab01361566e8365b31

See more details on using hashes here.

File details

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

File metadata

File hashes

Hashes for minijinja-2.5.0-cp38-abi3-manylinux_2_17_aarch64.manylinux2014_aarch64.whl
Algorithm Hash digest
SHA256 de15fc9ee8c6e0cd22799460af499520055139a8db3636e1c7136278215fe095
MD5 33c8e0df71434e3694665f68248ddae0
BLAKE2b-256 29d42e8a5cfb701a779e69b5c6e917a96ba70d6fc7f5c358bd645c67cea55716

See more details on using hashes here.

File details

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

File metadata

File hashes

Hashes for minijinja-2.5.0-cp38-abi3-manylinux_2_5_i686.manylinux1_i686.whl
Algorithm Hash digest
SHA256 025c0232bfbb92ff53bd474cfd230b687480fd6b4c4e9b4f5b354d91a62dc144
MD5 514bb5d8889f5584a5df6a91c895ae72
BLAKE2b-256 e58ea008fa6a19e3d3d3e6de731acaa5c258d2bc4b60e3023c6b662f020d20ff

See more details on using hashes here.

File details

Details for the file minijinja-2.5.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.5.0-cp38-abi3-macosx_10_12_x86_64.macosx_11_0_arm64.macosx_10_12_universal2.whl
Algorithm Hash digest
SHA256 888d88ab7328de337581656b220409aaa85c992d3ec25e50095196fb4f0752ae
MD5 5661a1ab188b8c91d504571821725630
BLAKE2b-256 a3d7d5a36cc6e293a91fe8183155c8c1db26b8ca1f34f8126ae0e76cf6639e42

See more details on using hashes here.

Supported by

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