Skip to main content

Minimal, fast templates for Python

Project description

Nano Templates

Minimal, fast, non-evaluating text templates for Python.

Install

TODO:

Example

import nano_template as nt

template = nt.parse("Hello, {{ you }}!")
print(template.render({"you": "World"}))  # Hello, World!

About

Nano Template is a small text templating engine, written as a Python C extension, with syntax familiar to anyone who's used Jinja/Minijinja, Django templates or Liquid.

Unlike those popular template engines, Nano Template forces you to keep application logic out of template text by implementing a reduced feature set. In this scenario, template authors and application developer are likely to be the same person (or team of people).

Syntax

[!NOTE] In Nano templates, there are no filters or tests, no relational or membership operators, and we don't have for loop helpers or {% break %} and {% continue %}.

Instead, you should process your data in Python before rendering a template, or use Minijinja.

Available tags are {% if %}, {% elif %}, {% else %} and {% for %}.

Variables

<div>{{ some.variable }}</div>
<p>{{ other["variable with spaces or special characters"] }}</p>

Conditions

{% if some.variable %}
  more markup
{% elif another.variable %}
  alternative markup
{% else %}
  default markup
{% endif %}

Loops

{% for x in y %}
  more markup with {{ x }}
{% else %}
  default markup (y was empty or not iterable)
{% endfor %}

Logical operators

Logical operators and, or and not use Python truthiness and precedence rules, and terms can be grouped with parentheses.

{% if not a and b %}
  markup with {{ b }} and {{ c }}.
{% endif %}

Logical and and or have last value semantics.

Hello, {{ user.name or "guest" }}!

Strings

String literals and quoted variable path segments can use single or double quotes, and allow JSON-style escape sequences.

{{ greeting or "Hi \uD83D\uDE00!" }}

Output:

Hi 😀!

Whitespace control

Control whitespace before and after markup delimiters with - and ~. ~ will remove newlines but retain space and tab characters. - strips all whitespace.

<ul>
{% for x in y ~%}
  <li>{{ x }}</li>
{% endfor -%}
</ul>

API

render

render(source, data) is a convenience function that parses and immediately renders a template to a string. Use this for testing or when you know you'll be rendering the template just the once.

import nano_template as nt

print(nt.render("Hello, {{ you }}!", {"you", "World"}))

render also accepts serializer and undefined keyword arguments.

parse

parse(source) parses template text and returns an instance of Template for later rendering with the render(self, data) method.

import nano_template as nt

template = nt.parse("Hello, {{ you }}!")
print(template.render({"you": "World"}))  # Hello, World!
print(template.render({"you": "Sue"}))  # Hello, Sue!

parse also accepts serializer and undefined keyword arguments.

Serializing objects

By default, when outputting an object with {{ and }}, lists, dictionaries and tuples are rendered in JSON format. For all other objects we render the result of str(obj).

You can change this behavior by passing a callable to parse or render as the serializer keyword argument. The callable should accept an object and return its string representation suitable for output.

This example shows how one might define a serializer that can dump data classes with json.dumps.

import json
from dataclasses import asdict
from dataclasses import dataclass
from dataclasses import is_dataclass

import nano_template as nt

@dataclass
class SomeData:
    foo: str
    bar: int

def json_default(obj: object) -> object:
    if is_dataclass(obj) and not isinstance(obj, type):
        return asdict(obj)
    raise TypeError(f"Object of type {obj.__class__.__name__} is not JSON serializable")

def my_serializer(obj: object) -> str:
    return (
        json.dumps(obj, default=json_default)
        if isinstance(obj, (list, dict, tuple))
        else str(obj)
    )


template = nt.parse("{{ some_object }}", serializer=my_serializer)
data = {"some_object": [SomeData("hello", 42)]}

print(template.render(data))  # [{"foo": "hello", "bar": 42}]

Undefined variables

When a template variable or property can't be resolved, an instance of the undefined type is used instead. That is, an instance of nano_template.Undefined or a subclass of it.

The default undefined type renders nothing when output, evaluates to False when tested for truthiness and is an empty iterable when looped over. You can pass an alternative undefined type as the undefined keyword argument to parse or render to change this behavior.

Here we use the built-in StrictUndefined.

import nano_template as nt

t = nt.parse("{{ foo.nosuchthing }}", undefined=nt.StrictUndefined)

print(t.render({"foo": {}}))
# nano_template._exceptions.UndefinedVariableError: 'foo.nosuchthing' is undefined
#   -> '{{ foo.nosuchthing }}':1:3
#   |
# 1 | {{ foo.nosuchthing }}
#   |    ^^^ 'foo.nosuchthing' is undefined

Or you can implement you own.

from typing import Iterator
import nano_template as nt


class MyUndefined(nt.Undefined):
    def __str__(self) -> str:
        return "<MISSING>"

    def __bool__(self) -> bool:
        return False

    def __iter__(self) -> Iterator[object]:
        yield from ()


t = nt.parse("{{ foo.nosuchthing }}", undefined=MyUndefined)

print(t.render({"foo": {}}))  # <MISSING>

Preliminary benchmark

TODO: move this

$ python scripts/benchmark.py
(001) Best of 5 rounds with 10000 iterations per round.
parse ext                     : best = 0.092188s | avg = 0.092236s
parse pure                    : best = 2.408759s | avg = 2.416534s
parse and render ext          : best = 0.159726s | avg = 0.159882s
parse and render pure         : best = 2.816334s | avg = 2.822223s
just render ext               : best = 0.062731s | avg = 0.062923s
just render pure              : best = 0.308758s | avg = 0.309301s
(002) Best of 5 rounds with 1000000 iterations per round.
render template               : best = 0.413830s | avg = 0.419547s
format string                 : best = 0.375050s | avg = 0.375237s

Contributing

TODO: move this

ABI 3 Audit

Note that abi3audit ignores target ABI version when auditing .so files.

  • Build a wheel locally with python setup.py bdist_wheel
  • Run abi3audit dist/<NAME>.whl --verbose

Example successful output:

[17:55:59] 💁 nano_template-0.1.0-cp39-abi3-linux_x86_64.whl: 1 extensions scanned; 0 ABI version mismatches and 0 ABI violations found

License

nano-template is distributed under the terms of the MIT license.

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

nano_template-0.1.0.tar.gz (44.3 kB view details)

Uploaded Source

Built Distributions

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

nano_template-0.1.0-cp314-cp314t-win_arm64.whl (34.3 kB view details)

Uploaded CPython 3.14tWindows ARM64

nano_template-0.1.0-cp314-cp314t-win_amd64.whl (36.7 kB view details)

Uploaded CPython 3.14tWindows x86-64

nano_template-0.1.0-cp314-cp314t-win32.whl (33.8 kB view details)

Uploaded CPython 3.14tWindows x86

nano_template-0.1.0-cp314-cp314t-musllinux_1_2_x86_64.whl (151.1 kB view details)

Uploaded CPython 3.14tmusllinux: musl 1.2+ x86-64

nano_template-0.1.0-cp314-cp314t-musllinux_1_2_aarch64.whl (152.5 kB view details)

Uploaded CPython 3.14tmusllinux: musl 1.2+ ARM64

nano_template-0.1.0-cp314-cp314t-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl (153.8 kB view details)

Uploaded CPython 3.14tmanylinux: glibc 2.17+ ARM64manylinux: glibc 2.28+ ARM64

nano_template-0.1.0-cp314-cp314t-manylinux1_x86_64.manylinux_2_28_x86_64.manylinux_2_5_x86_64.whl (150.7 kB view details)

Uploaded CPython 3.14tmanylinux: glibc 2.28+ x86-64manylinux: glibc 2.5+ x86-64

nano_template-0.1.0-cp314-cp314t-macosx_11_0_arm64.whl (34.7 kB view details)

Uploaded CPython 3.14tmacOS 11.0+ ARM64

nano_template-0.1.0-cp314-cp314t-macosx_10_15_x86_64.whl (34.7 kB view details)

Uploaded CPython 3.14tmacOS 10.15+ x86-64

nano_template-0.1.0-cp39-abi3-win_arm64.whl (32.7 kB view details)

Uploaded CPython 3.9+Windows ARM64

nano_template-0.1.0-cp39-abi3-win_amd64.whl (34.2 kB view details)

Uploaded CPython 3.9+Windows x86-64

nano_template-0.1.0-cp39-abi3-win32.whl (31.3 kB view details)

Uploaded CPython 3.9+Windows x86

nano_template-0.1.0-cp39-abi3-musllinux_1_2_x86_64.whl (108.9 kB view details)

Uploaded CPython 3.9+musllinux: musl 1.2+ x86-64

nano_template-0.1.0-cp39-abi3-musllinux_1_2_aarch64.whl (109.7 kB view details)

Uploaded CPython 3.9+musllinux: musl 1.2+ ARM64

nano_template-0.1.0-cp39-abi3-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl (112.5 kB view details)

Uploaded CPython 3.9+manylinux: glibc 2.17+ ARM64manylinux: glibc 2.28+ ARM64

nano_template-0.1.0-cp39-abi3-manylinux1_x86_64.manylinux_2_28_x86_64.manylinux_2_5_x86_64.whl (110.7 kB view details)

Uploaded CPython 3.9+manylinux: glibc 2.28+ x86-64manylinux: glibc 2.5+ x86-64

nano_template-0.1.0-cp39-abi3-macosx_11_0_arm64.whl (33.3 kB view details)

Uploaded CPython 3.9+macOS 11.0+ ARM64

nano_template-0.1.0-cp39-abi3-macosx_10_9_x86_64.whl (33.1 kB view details)

Uploaded CPython 3.9+macOS 10.9+ x86-64

File details

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

File metadata

  • Download URL: nano_template-0.1.0.tar.gz
  • Upload date:
  • Size: 44.3 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? No
  • Uploaded via: twine/6.2.0 CPython/3.14.0

File hashes

Hashes for nano_template-0.1.0.tar.gz
Algorithm Hash digest
SHA256 1827b257ee6fbecf49abeb84501c350fc343a7c08171e18b00b2f642dcbb2476
MD5 4ed079935c6dcfe70bf18736e6e1c0d5
BLAKE2b-256 d49db270d4af33f3632ad080357a4644cd3e14503539377bb7dbbb20bb147aea

See more details on using hashes here.

File details

Details for the file nano_template-0.1.0-cp314-cp314t-win_arm64.whl.

File metadata

File hashes

Hashes for nano_template-0.1.0-cp314-cp314t-win_arm64.whl
Algorithm Hash digest
SHA256 923bde117904a864dea452ba42e2587a6a7b42766add37cac12d647a6a56a147
MD5 a19c747018b77f9fb742378b0c34c52d
BLAKE2b-256 e911705463982ffbec69eb6f34caa39b752d8d8654cfdceddfdea58cfcf2f87f

See more details on using hashes here.

File details

Details for the file nano_template-0.1.0-cp314-cp314t-win_amd64.whl.

File metadata

File hashes

Hashes for nano_template-0.1.0-cp314-cp314t-win_amd64.whl
Algorithm Hash digest
SHA256 de4e690fd4fc7331c7774901b7896e505e15e3119403c4b9dade51266631e47f
MD5 b45993abe6effcfceed20d2769e97f20
BLAKE2b-256 8cdf24569129c556d36ba642d8551311bbca6bf5176b0184d5e7e48fad544403

See more details on using hashes here.

File details

Details for the file nano_template-0.1.0-cp314-cp314t-win32.whl.

File metadata

File hashes

Hashes for nano_template-0.1.0-cp314-cp314t-win32.whl
Algorithm Hash digest
SHA256 a7c31238552ca4dc6a24fe768c450e07f4c3d37fd32528394a488c068398f029
MD5 26d82c4f7851204a6bb504aba676bfc8
BLAKE2b-256 8f653313e6aace68974daa5a2c17ab8bf32071c2dd47284c31a06935439c0c7d

See more details on using hashes here.

File details

Details for the file nano_template-0.1.0-cp314-cp314t-musllinux_1_2_x86_64.whl.

File metadata

File hashes

Hashes for nano_template-0.1.0-cp314-cp314t-musllinux_1_2_x86_64.whl
Algorithm Hash digest
SHA256 7a096a228eb32119fa132343915ee4802e689f4690547fdbe5c5d85f37289c41
MD5 a55df8a55debdad728fd8c1a142bc286
BLAKE2b-256 7044c6e023d0dd78d348e1abf009c7ac51a01acce2efb4a6eee3ca16058fc9d1

See more details on using hashes here.

File details

Details for the file nano_template-0.1.0-cp314-cp314t-musllinux_1_2_aarch64.whl.

File metadata

File hashes

Hashes for nano_template-0.1.0-cp314-cp314t-musllinux_1_2_aarch64.whl
Algorithm Hash digest
SHA256 3610a921925184008ea0801e1757b2dc7b63cf3c8f3f503e7fc12d3ec529c74c
MD5 c7b0f671d60e62f0afdd944f9fd5ff13
BLAKE2b-256 b03777e40d51d55aad5d59046021d39cb5515ff9af507c7149b7f633adcc220c

See more details on using hashes here.

File details

Details for the file nano_template-0.1.0-cp314-cp314t-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl.

File metadata

File hashes

Hashes for nano_template-0.1.0-cp314-cp314t-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl
Algorithm Hash digest
SHA256 58a50940f66cd9057eb7a1ecd02694b7332d15f4be258cd1a5a4956d5552d4dd
MD5 aca619e8b9e9610de1d1a1e7a674fdf6
BLAKE2b-256 b11c2d1640039543bcd90d3db7f3117f766b237f8814ebf34a96d42b8e6621a3

See more details on using hashes here.

File details

Details for the file nano_template-0.1.0-cp314-cp314t-manylinux1_x86_64.manylinux_2_28_x86_64.manylinux_2_5_x86_64.whl.

File metadata

File hashes

Hashes for nano_template-0.1.0-cp314-cp314t-manylinux1_x86_64.manylinux_2_28_x86_64.manylinux_2_5_x86_64.whl
Algorithm Hash digest
SHA256 02ae4440ba7a5730fd108657d94da350b41f6cd7367b8d421da9fca6a71ea920
MD5 58859bda6fcb8e08f1498e5d2b6c2817
BLAKE2b-256 39d93e5cbe0b618439b2874a2b7026620ba38274e27ad5fefc242b01ed7d949e

See more details on using hashes here.

File details

Details for the file nano_template-0.1.0-cp314-cp314t-macosx_11_0_arm64.whl.

File metadata

File hashes

Hashes for nano_template-0.1.0-cp314-cp314t-macosx_11_0_arm64.whl
Algorithm Hash digest
SHA256 4f74beb46f3845cd84adb6635193bd8e47fa64d3d87a7b758e9f2fb32fb24b34
MD5 cc7e089f61b572786e44780ff81cfe96
BLAKE2b-256 76b6b9794a7a253d409a5687c02f468ed709d66ecd1cb8674ec73214884b5426

See more details on using hashes here.

File details

Details for the file nano_template-0.1.0-cp314-cp314t-macosx_10_15_x86_64.whl.

File metadata

File hashes

Hashes for nano_template-0.1.0-cp314-cp314t-macosx_10_15_x86_64.whl
Algorithm Hash digest
SHA256 986cd80c5d57a7a832c1f5f000a70ec6254c8141bfa32d2a94ecc555df2bc89b
MD5 62d99bd620d17556e4a76feaf7e9534e
BLAKE2b-256 687d16e36a07c267c9c293effe8c50d6e7a196e0ede505cf259f846e979d9bd0

See more details on using hashes here.

File details

Details for the file nano_template-0.1.0-cp39-abi3-win_arm64.whl.

File metadata

File hashes

Hashes for nano_template-0.1.0-cp39-abi3-win_arm64.whl
Algorithm Hash digest
SHA256 2fce902365bc262519a573727444c572dae3b818573e6a7dc07d824ca5fa3c22
MD5 a2bfbc8f3ff3ac66c3d11ca5cce083ad
BLAKE2b-256 847fdbf902862fd650c5451bf2d3bf62d36be0e8c5762599b3818074734f9067

See more details on using hashes here.

File details

Details for the file nano_template-0.1.0-cp39-abi3-win_amd64.whl.

File metadata

File hashes

Hashes for nano_template-0.1.0-cp39-abi3-win_amd64.whl
Algorithm Hash digest
SHA256 0b61a9019230605fd0011d739186ace4c51aa61e743638b4670fd4ed081bd8ef
MD5 f0db95305ab05ea5c1c0d3561ff98ce7
BLAKE2b-256 c55c9cedf5fdd76ac5f857587e70920939c16e2b8aec2fd16381e602efea3999

See more details on using hashes here.

File details

Details for the file nano_template-0.1.0-cp39-abi3-win32.whl.

File metadata

  • Download URL: nano_template-0.1.0-cp39-abi3-win32.whl
  • Upload date:
  • Size: 31.3 kB
  • Tags: CPython 3.9+, Windows x86
  • Uploaded using Trusted Publishing? No
  • Uploaded via: twine/6.2.0 CPython/3.14.0

File hashes

Hashes for nano_template-0.1.0-cp39-abi3-win32.whl
Algorithm Hash digest
SHA256 c7606e21cf6ff68aacdc18c70cd6e13a56d7fb62a2c370a3e6c5da600f861215
MD5 24d8f950a1f6a07b057253804e17c94f
BLAKE2b-256 6c266613c5cc5317118ea612164f8e5f0f4d8db5c98d4ef8d442bebdc7bc49cd

See more details on using hashes here.

File details

Details for the file nano_template-0.1.0-cp39-abi3-musllinux_1_2_x86_64.whl.

File metadata

File hashes

Hashes for nano_template-0.1.0-cp39-abi3-musllinux_1_2_x86_64.whl
Algorithm Hash digest
SHA256 0adb8c09af87f5033eed01f16a76837cea7179be7f9a0bc1376fb6067c5c2699
MD5 bac97f5a174109422334164126af7371
BLAKE2b-256 5b8e65520242707e5960b85afffcc65f79cf1c88c28416eab10292b73668c7d3

See more details on using hashes here.

File details

Details for the file nano_template-0.1.0-cp39-abi3-musllinux_1_2_aarch64.whl.

File metadata

File hashes

Hashes for nano_template-0.1.0-cp39-abi3-musllinux_1_2_aarch64.whl
Algorithm Hash digest
SHA256 0512c531d2347e55cb8c0cddb554ee763bdb2f89987e88c5267f4aff8feafe95
MD5 4e3d97d1833f756f8d1d0e57c89a373c
BLAKE2b-256 7beff9b4f2a3545752b362fe251275872289c9f8e6d8f3eebbb6f9eeeb81a993

See more details on using hashes here.

File details

Details for the file nano_template-0.1.0-cp39-abi3-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl.

File metadata

File hashes

Hashes for nano_template-0.1.0-cp39-abi3-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl
Algorithm Hash digest
SHA256 bbf1776088433655fd874c0e6f8b6cce1b864592100cdb501101d9971108a4b6
MD5 c0ccaa4f693f8aff35667bc8da4ca195
BLAKE2b-256 59f0972ab73662ac8f95b7c737adc42cd2ac6c4d272b6836c522a5d08100fb77

See more details on using hashes here.

File details

Details for the file nano_template-0.1.0-cp39-abi3-manylinux1_x86_64.manylinux_2_28_x86_64.manylinux_2_5_x86_64.whl.

File metadata

File hashes

Hashes for nano_template-0.1.0-cp39-abi3-manylinux1_x86_64.manylinux_2_28_x86_64.manylinux_2_5_x86_64.whl
Algorithm Hash digest
SHA256 c9f40a76a43365c867236852b61309b1a06444de1881cda8b6203b02dfe1746f
MD5 0b38552bcfec8be09a428c2db1e5d5df
BLAKE2b-256 f0632eb7b8970469a9cf7126cfa2c8530b51318fa366600702d09dafaab010ef

See more details on using hashes here.

File details

Details for the file nano_template-0.1.0-cp39-abi3-macosx_11_0_arm64.whl.

File metadata

File hashes

Hashes for nano_template-0.1.0-cp39-abi3-macosx_11_0_arm64.whl
Algorithm Hash digest
SHA256 8479288564045cd30127272e0424268ea8a5d07c0087ceb6b135424343741575
MD5 1567f5aa1091ebad52be423c33e9fb93
BLAKE2b-256 e2c0b9638c65487055422301e52101b5d832afa255bc6055668181afa93fcda2

See more details on using hashes here.

File details

Details for the file nano_template-0.1.0-cp39-abi3-macosx_10_9_x86_64.whl.

File metadata

File hashes

Hashes for nano_template-0.1.0-cp39-abi3-macosx_10_9_x86_64.whl
Algorithm Hash digest
SHA256 30b784a6981943e8e6577da426472fb0f0c23d3c386dab693cccd85e3f8f3e1d
MD5 08885578daf949131b63241f1989f623
BLAKE2b-256 8f09ba4c1ce558d5bc14380acaa86d041b31d1bf160aee5e1fc57866ed90a9ea

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