Skip to main content

Build Status License Language

Scrippy, my scrangourou friend

scrippy_template

Simplified management of template files for the Scrippy framework.

Prerequisites

  • Python >= 3.11

Python modules

List of required modules

The modules listed below will be automatically installed.

  • jinja2

Installation

Manual

git clone https://codeberg.org/scrippy/scrippy-template.git
cd scrippy-template
python -m pip install -r requirements.txt
make install

With pip

pip install scrippy-template

Usage

This module allows document generation from template files using the Jinja2 rendering engine.

Loading and rendering a template file

The template.Renderer object is instantiated with:

  • base_path: the directory in which template files are searched for,
  • template_filename: the name of the template file, relative to base_path.

By convention, the template files used by the Scrippy framework are stored in the directory defined by the env.templatedir configuration parameter (see the configuration of the Scrippy framework in the relevant documentation).

The template file is checked as soon as it is loaded: a missing or unreadable template file, or a template file with a syntax error, raises a ScrippyTemplateError at instantiation. Unknown filters and tests are only detected at rendering, since they may be added to the Jinja2 environment after the template file has been loaded.

The Renderer.render(params) method returns the rendering of the template file. The variables MUST be supplied to the template file as a dictionary named params, and are accessed from the template file as {{params.<variable>}}.

The template file is compiled at each rendering: a change made to the template file after it has been loaded is taken into account.

The Renderer.load(base_path, template_filename) method allows the same Renderer object to load another template file, possibly from another directory. The previously loaded template file is replaced.

from scrippy_template import template

renderer = template.Renderer("/var/scrippy/templates", "dead_parrot.j2")
print(renderer.render({"user": "Harry Fink"}))

renderer.load("/var/scrippy/other_templates", "cheese_shop.j2")
print(renderer.render({"cheese": "Red Leicester"}))

Undefined variables

Any variable used by the template file MUST be present in the params dictionary: an undefined variable raises a ScrippyTemplateError at rendering.

Optional variables must be explicitly handled in the template file, either with the is defined test or with the default filter:

Hello {{params.user}}{% if params.title is defined %} ({{params.title}}){% endif %}
Sent by {{params.sender | default("Scrippy")}}

HTML/XML escaping

Variables are automatically escaped only in template files whose name ends with one of the following extensions: .html, .htm, .xml, .html.j2, .htm.j2, .xml.j2.

All other template files (.j2, .txt...) are rendered without any escaping.

With the template file report.html.j2:

<p>{{params.msg}}</p>

and params = {"msg": "<b>Spam & eggs</b>"}, the rendering is:

<p>&lt;b&gt;Spam &amp; eggs&lt;/b&gt;</p>

Jinja2 environment

The Jinja2 environment is accessible through the env attribute of the template.Renderer object. It is created at instantiation and kept when another template file is loaded with Renderer.load().

Changes made to the environment (filters, globals, options...) are taken into account at the next rendering:

renderer = template.Renderer("/var/scrippy/templates", "shout.j2")  # {{params.msg | shout}}
renderer.env.filters["shout"] = str.upper
print(renderer.render({"msg": "Spam, spam, spam"}))  # SPAM, SPAM, SPAM

Errors

All errors raise a scrippy_template.ScrippyTemplateError:

Error Raised by Message
Missing template file Renderer(), Renderer.load(), Renderer.render() Template not found: <base_path>/<template_filename>
Syntax error Renderer(), Renderer.load(), Renderer.render() Template syntax error: <base_path>/<template_filename> (line <n>): <message>
Unknown filter Renderer.render() Template syntax error: <base_path>/<template_filename> (line <n>): No filter named '<filter>'.
Unknown test Renderer.render() Unexpected error: [TemplateRuntimeError] No test named '<test>' found.
Undefined variable Renderer.render() Undefined variable: <message>
Any other error Renderer(), Renderer.load(), Renderer.render() Unexpected error: [<exception class>] <message>
from scrippy_template import template, ScrippyTemplateError

try:
  renderer = template.Renderer("/var/scrippy/templates", "dead_parrot.j2")
  print(renderer.render(params))
except ScrippyTemplateError as err:
  print(err)

Simple template file

With the following template file named dead_parrot.j2 located in the directory /var/scrippy/templates:

Hello {{params.user}}

You received this email because you are a member of the functional administrators of {{params.app}}.

The {{params.script}} script execution on {{params.date}} ended with the following error code:
- {{params.error.code}}: {{params.error.msg}}

--
Regards.
{{params.sender}}

The template file can be used as follows:

import datetime
from scrippy_template import template

params = {"user": "Harry Fink",
          "app": "Flying Circus",
          "script": "dead_parrot.py",
          "date": datetime.datetime.now().strftime("%Y/%m/%d"),
          "error": {"code": 42,
                    "msg": "It's not pinin'! It's passed on! This parrot is no more!"},
          "sender": "Luiggi Vercotti"}

base_path = "/var/scrippy/templates"
template_file = "dead_parrot.j2"
renderer = template.Renderer(base_path, template_file)

print(renderer.render(params))

The rendering will be:

Hello Harry Fink

You received this email because you are a member of the functional administrators of Flying Circus.

The dead_parrot.py script execution on 2019/09/15 ended with the following error code:
- 42: It's not pinin'! It's passed on! This parrot is no more!

--
Regards.
Luiggi Vercotti

Template file with control structures

params = {"user": "Harry Fink",
          "app": "Flying Circus",
          "script": "dead_parrot.py",
          "date": datetime.datetime.now().strftime("%Y/%m/%d"),
          "num_errors": 42,
          "sender": "Luiggi Vercotti"}
Hello {{params.user}}

You received this email because you are a member of the functional administrators of {{params.app}}.

The {{params.script}} script execution on {{params.date}} ended
{%- if params.num_errors == 0 %} without error.
{%- else %} with {{params.num_errors}} error(s).
{%- endif %}

--
Regards.
{{params.sender}}

The rendering will be:

Hello Harry Fink

You received this email because you are a member of the functional administrators of Flying Circus.

The dead_parrot.py script execution on 2019/09/15 ended with 42 error(s).

--
Regards.
Luiggi Vercotti

Template file with loop

params = {"user": "Harry Fink",
          "app": "Flying Circus",
          "script": "dead_parrot.py",
          "date": datetime.datetime.now().strftime("%Y/%m/%d"),
          "errors": [{"code": 2, "msg": "It's not pinin'! It's passed on! This parrot is no more!"},
                     {"code": 3, "msg": "Ohh! The cat's eaten it."}],
          "sender": "Luiggi Vercotti"}
Hello {{params.user}}

You received this email because you are a member of the functional administrators of {{params.app}}.

The {{params.script}} script execution on {{params.date}} ended with the following errors:
{% for error in params.errors -%}
- {{error.code}}: {{error.msg}}
{% endfor %}
--
Regards.
{{params.sender}}

The rendering will be:

Hello Harry Fink

You received this email because you are a member of the functional administrators of Flying Circus.

The dead_parrot.py script execution on 2019/09/15 ended with the following errors:
- 2: It's not pinin'! It's passed on! This parrot is no more!
- 3: Ohh! The cat's eaten it.

--
Regards.
Luiggi Vercotti

Metadata

Release files for scrippy-template 2.0.1

For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.

Source distribution (sdist)

Source distribution for scrippy-template 2.0.1
File Size Uploaded
scrippy_template-2.0.1.tar.gz 11.0 kB Details

Built distribution (wheel)

Table of built distributions (wheels) for scrippy-template 2.0.1
File Interpreter ABI Platform
scrippy_template-2.0.1-py3-none-any.whl Python 3 none any Details

Total release size: 18.1 kB

Release files / scrippy_template-2.0.1.tar.gz

Download URL scrippy_template-2.0.1.tar.gz
Size 11.0 kB
Tags Source
SHA-256 checksum
How to use checksums
e5f6915199fe524aa4caea0e3e752dfc52d12007fbd0b684080a6183c844f27c
BLAKE2b-256 checksum
How to use checksums
0c13a59f9d372056c1db4741ea74aa951c62d84e82049710206263bfe210dfa0
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
No
Uploaded via twine/7.0.0 CPython/3.11.17

Release files / scrippy_template-2.0.1-py3-none-any.whl

Download URL scrippy_template-2.0.1-py3-none-any.whl
Size 7.1 kB
Tags Python 3
SHA-256 checksum
How to use checksums
1983a8b1e40b29da2bdcd1fc7bc0d9d3f4c18a60964144d30bd41c4676d9dc24
BLAKE2b-256 checksum
How to use checksums
d3cc5dadb5358939cccde69f579869c959552f8050c716e94b601672dd0270c6
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
No
Uploaded via twine/7.0.0 CPython/3.11.17

Release history Release notifications | RSS feed

This release

2.0.1 This release

2 release files

2.0.0

2 release files

1.1.88

2 release files

1.1.87

2 release files

1.1.84

2 release files

1.1.83

2 release files

1.1.82

2 release files

Anthropic, PBC Visionary sponsor Bloomberg Visionary sponsor Hudson River Trading Visionary sponsor Meta Visionary sponsor NVIDIA Visionary sponsor Microsoft Sustainability sponsor Depot Continuous Integration AWS Cloud computing and Security Sponsor Datadog Monitoring Fastly CDN Google Download Analytics Sentry Error logging StatusPage Status page