trmnl-liquid-py
A Python compatibility layer for usetrmnl/trmnl-liquid, targeting byte-for-byte compatible rendering for the supported TRMNL Liquid 0.8.2 surface.
[!NOTE] The first release target is
trmnl-liquid-py0.1.0, compatible withtrmnl-liquid0.8.2 for the supported non-I18n surface. Rails/ActionView and full I18n behavior are intentionally deferred.
Installation
Once 0.1.0 is published to PyPI:
python -m pip install trmnl-liquid-py
Python 3.11–3.14 is supported.
Quick start
from trmnl_liquid import Environment
env = Environment()
template = env.from_string("Hello {{ name }}!")
print(template.render(name="TRMNL"))
For one-shot rendering:
from trmnl_liquid import render
html = render("{{ value | number_with_delimiter }}", value=1234567)
Inline templates
TRMNL adds an inline {% template %} definition that can later be rendered with Liquid's {% render %} tag:
{% template card %}
<div>{{ title }}</div>
{% endtemplate %}
{% render 'card', title: 'Status' %}
trmnl-liquid-py reproduces TRMNL 0.8.2's raw-body and template-storage semantics, including its exact {% endtemplate %} terminator behavior.
TRMNL filters
The 0.1.0 compatibility surface includes:
append_randomdays_agogroup_byfind_bymarkdown_to_htmlnumber_with_delimiternumber_to_currencyl_wordfallback behaviorl_datefallback behaviormap_to_ipluralizejsonparse_jsonsamplewhere_expordinalizeqr_code
Important TRMNL/Ruby syntax differences are preserved where required. For example, Ruby Liquid's lax filter syntax accepts a leading comma before the first filter argument:
{{ value | qr_code, 11 }}
Markdown
markdown_to_html reproduces the tested output of TRMNL 0.8.2's default Redcarpet 3.6.1 configuration using Mistune on Python.
{{ markdown | markdown_to_html }}
QR codes
qr_code renders the SVG shape expected from TRMNL's RQRCode-based implementation, including compatible QR mask selection/scoring behavior.
{{ 'https://example.com' | qr_code: 11 }}
Compatibility target
The baseline is exactly:
trmnl-liquid0.8.2- Python 3.11, 3.12, 3.13, 3.14
- non-I18n behavior
- Rails/ActionView and full localized
l_word/l_datebehavior deferred - features added after upstream 0.8.2 excluded until a later compatibility target is adopted
Ruby trmnl-liquid 0.8.2 is the reference implementation. Differences in parsing, coercion, formatting, Markdown rendering, QR generation, template behavior, error handling, or rendered output are treated as compatibility issues when they affect the supported scope.
Compatibility evidence
| Gate | Result |
|---|---|
| Ruby 0.8.2 vs Python exact differential corpus | 574/574 |
| Known mismatches in the supported scope | 0 |
| Official TRMNL 0.8.2 RSpec examples mapped | 73/73 |
| Upstream examples covered by exact differential tests | 46 |
| Upstream examples covered by property/unit tests | 16 |
| Upstream examples covered in the initial non-I18n scope | 62/73 |
| Deferred Rails/I18n upstream examples | 11 |
| Python CI matrix | 3.11, 3.12, 3.13, 3.14 |
| Comparison | exact rendered output |
The Compatibility workflow runs the Ruby oracle first and fails on any mismatch. It then checks that this generated report still matches the checked-in corpus and upstream-spec manifest.
See COMPATIBILITY.md for the compatibility contract, upstream spec mapping, and Ruby oracle details.
Development
Install the project with development dependencies, then run the normal quality gates:
python -m pip install -e . pytest ruff mypy build twine \
types-python-dateutil==2.9.0.20260807 \
types-qrcode==8.2.0.20260518
ruff check .
mypy src/trmnl_liquid
pytest
python -m build
twine check dist/*
The Ruby/Python differential suite additionally requires Ruby and the bundle in compatibility/ruby:
bundle install --gemfile compatibility/ruby/Gemfile
python compatibility/compare.py
python -m compatibility.report --check
Release process
Releases are tag-driven. There is no manual publish workflow and no PyPI API token stored in GitHub.
- Update
src/trmnl_liquid/__about__.pyandCHANGELOG.mdin a normal PR. - Merge the PR to
mainand wait for bothCIandCompatibilityto pass onmain. - Create and push a tag whose name is exactly the package version, for example
0.1.0. - The
Releaseworkflow verifies that the tag equals__version__and points to a commit onmain. - The workflow builds and validates the wheel/sdist, publishes them to PyPI through Trusted Publishing, and only after a successful PyPI publish creates the matching GitHub Release with the distributions attached.
A tag such as v0.1.0 is intentionally invalid when __version__ == "0.1.0".
License
MIT. The repository license includes attribution for portions derived from usetrmnl/trmnl-liquid.
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 trmnl_liquid_py-0.1.0.tar.gz.
File metadata
- Download URL: trmnl_liquid_py-0.1.0.tar.gz
- Upload date:
- Size: 22.6 kB
- Tags: Source
- Uploaded using Trusted Publishing? Yes
- Uploaded via:
twine/7.0.0 CPython/3.13.14
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
ec45bc45c9bd34bd8b73c2d38d9f86db9bb404d67843e6516e416181bce16f1c
|
|
| MD5 |
c447b44ee072fc47c4ba3cf12be45d7a
|
|
| BLAKE2b-256 |
bf9b969c19d5ad0875217dc38f1971e872d32ea9ff174e2700b1e0225a5a640b
|
Provenance
The following attestation bundles were made for trmnl_liquid_py-0.1.0.tar.gz:
Publisher:
release.yml on Misiu/trmnl-liquid-py
-
Statement:
-
Statement type:
https://in-toto.io/Statement/v1 -
Predicate type:
https://docs.pypi.org/attestations/publish/v1 -
Subject name:
trmnl_liquid_py-0.1.0.tar.gz -
Subject digest:
ec45bc45c9bd34bd8b73c2d38d9f86db9bb404d67843e6516e416181bce16f1c - Sigstore transparency entry: 2617771596
- Sigstore integration time:
-
Permalink:
Misiu/trmnl-liquid-py@e1b1746b14af4d1aec3377bd74738718ce7b0693 -
Branch / Tag:
refs/tags/0.1.0 - Owner: https://github.com/Misiu
-
Access:
public
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
release.yml@e1b1746b14af4d1aec3377bd74738718ce7b0693 -
Trigger Event:
push
-
Statement type:
File details
Details for the file trmnl_liquid_py-0.1.0-py3-none-any.whl.
File metadata
- Download URL: trmnl_liquid_py-0.1.0-py3-none-any.whl
- Upload date:
- Size: 28.3 kB
- Tags: Python 3
- Uploaded using Trusted Publishing? Yes
- Uploaded via:
twine/7.0.0 CPython/3.13.14
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
14bdc74337831b8c98fe4f9ecdec8362c35d6d04758901a4a45455c44fa33ddc
|
|
| MD5 |
73e2c534c3ef1a6729f1d28291adb6cf
|
|
| BLAKE2b-256 |
c484708d56b84eec04175794fda760ce9382be212946326dfcd41b5e6a5252b3
|
Provenance
The following attestation bundles were made for trmnl_liquid_py-0.1.0-py3-none-any.whl:
Publisher:
release.yml on Misiu/trmnl-liquid-py
-
Statement:
-
Statement type:
https://in-toto.io/Statement/v1 -
Predicate type:
https://docs.pypi.org/attestations/publish/v1 -
Subject name:
trmnl_liquid_py-0.1.0-py3-none-any.whl -
Subject digest:
14bdc74337831b8c98fe4f9ecdec8362c35d6d04758901a4a45455c44fa33ddc - Sigstore transparency entry: 2617771614
- Sigstore integration time:
-
Permalink:
Misiu/trmnl-liquid-py@e1b1746b14af4d1aec3377bd74738718ce7b0693 -
Branch / Tag:
refs/tags/0.1.0 - Owner: https://github.com/Misiu
-
Access:
public
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
release.yml@e1b1746b14af4d1aec3377bd74738718ce7b0693 -
Trigger Event:
push
-
Statement type: