Minimal Liquid-like templating
Project description
micro-liquid
Table of Contents
- Install
- Example
- About
- What's included?
- What's not included?
- Undefined variables
- Serializing objects
- License
Install
pip install micro-liquid
Example
from micro_liquid import Template
template = Template("Hello, {{ you }}!")
print(template.render({"you": "World"})) # Hello, World!
About
Micro Liquid implements minimal, Liquid-like templating. You can think of it as a non-evaluating alternative to f-strings or t-strings, where templates are data and not necessarily string literals inside Python source files.
Full-featured Liquid (Python Liquid or Shopify/liquid, for example) caters for situations where end users manage their own templates. In this scenario, it's reasonable to expect some amount of application/display logic to be embedded within template text. In other scenarios we'd very much want to keep application logic out of template text.
With that in mind, Micro Liquid offers a greatly reduced feature set, implemented in a single Python file, so you can copy and paste it and hack on it if needed.
Here, developers are expected to fully prepare data passed to Template.render() instead of manipulating and inspecting it within template markup.
What's included?
Micro Liquid support variable substitution:
Hello, {{ some_variable }}. How are you?
Conditional expressions:
{% if some_variable %}
more markup
{% elsif another_variable %}
alternative markup
{% else %}
default markup
{% endif %}
And looping:
{% for x in y %}
more markup with {{ x }}
{% else %}
default markup (y was empty or not iterable)
{% endfor %}
Micro Liquid expressions can use logical and, or and not, and group terms with parentheses.
{% if not some_variable and another_variable %}
some markup with {{ some_variable }} and {{ another_variable }}.
{% endif %}
Short circuit evaluation works too, with last value semantics. Here you might use a string literal.
Hello, {{ user.name or "guest" }}!
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>
What's not included?
If you need any of these features, and many more, try Python Liquid or Python Liquid2 instead.
- Assignment, captures and snippets (
includeandrender). Or any tag other thanifandfor. - Relational operators like
==and<. - Membership operators like
containsandin. - Filters.
- Literal Booleans, integers, floats or null/nil/None.
{% break %}and{% continue %}tags.- Nested variables.
forloophelper variables.fortag arguments likelimitandreversed.
Other notable behavior
- We use Python truthiness, not Liquid or Ruby truthiness.
- Any
Iterablecan be looped over with the{% for %}tag. Non-iterable objects are silently ignored. - Looping over dictionaries (or any Mapping) iterates key/value pairs.
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 micro_liquid.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 the Template constructor to change this behavior.
from micro_liquid import StrictUndefined
from micro_liquid import Template
t = Template("{{ foo.nosuchthing }}", undefined=StrictUndefined)
print(t.render({"foo": {}}))
# micro_liquid.UndefinedVariableError: 'foo.nosuchthing' is undefined
# -> '{{ foo.nosuchthing }}':1:3
# |
# 1 | {{ foo.nosuchthing }}
# | ^^^ 'foo.nosuchthing' is undefined
Or implement your own.
from typing import Iterator
from micro_liquid import Template
from micro_liquid import Undefined
class MyUndefined(Undefined):
def __str__(self) -> str:
return "<MISSING>"
def __bool__(self) -> bool:
return False
def __iter__(self) -> Iterator[object]:
yield from ()
t = Template("{{ foo.nosuchthing }}", undefined=MyUndefined)
print(t.render({"foo": {}})) # <MISSING>
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 the Template constructor or render function 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
from micro_liquid import Template
@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 = Template("{{ some_object }}", serializer=my_serializer)
data = {"some_object": [SomeData("hello", 42)]}
print(template.render(data)) # [{"foo": "hello", "bar": 42}]
TODO: Walk syntax tree
License
micro-liquid is distributed under the terms of the MIT license.
Project details
Release history Release notifications | RSS feed
Download files
Download the file for your platform. If you're not sure which to choose, learn more about installing packages.
Source Distribution
Built Distribution
Filter files by name, interpreter, ABI, and platform.
If you're not sure about the file name format, learn more about wheel file names.
Copy a direct link to the current filters
File details
Details for the file micro_liquid-0.1.0.tar.gz.
File metadata
- Download URL: micro_liquid-0.1.0.tar.gz
- Upload date:
- Size: 15.5 kB
- Tags: Source
- Uploaded using Trusted Publishing? No
- Uploaded via: twine/6.1.0 CPython/3.11.10
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
1ccb6f738231f237ab7e2d32f7e642df81bcc4ea786d24976a62e31165ba5d0b
|
|
| MD5 |
1c24fcdad5f23760254a1d64b3948d37
|
|
| BLAKE2b-256 |
f435398c85906f5551d05ba136a87c4ee2cd492695f13b9d51902c1bda484101
|
File details
Details for the file micro_liquid-0.1.0-py3-none-any.whl.
File metadata
- Download URL: micro_liquid-0.1.0-py3-none-any.whl
- Upload date:
- Size: 25.2 kB
- Tags: Python 3
- Uploaded using Trusted Publishing? No
- Uploaded via: twine/6.1.0 CPython/3.11.10
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
aaf4ae7e31d0eff99279ed06de26b85b459e71997c1e1a822f95d1839d098788
|
|
| MD5 |
706a7b1b6c901f751d67f87d1e507725
|
|
| BLAKE2b-256 |
4ff06e3754cbdebce5552411b98dc12d765a3253239ffff785e1f6452648a74c
|