๐Ÿš€ Big News: Socket Acquires Coana to Bring Reachability Analysis to Every Appsec Team.Learn more โ†’
Socket
Book a DemoInstallSign in
Socket

artless-template

Package Overview
Dependencies
Maintainers
1
Alerts
File Explorer

Advanced tools

Socket logo

Install Socket

Detect and block malicious and high-risk dependencies

Install

artless-template

The artless and minimalist templating for Python server-side rendering.

0.6.1
PyPI
Maintainers
1

artless-template

PyPI Version Development Status PyPI - Python Version Downloads PyPI - License

The artless and minimalist templating for Python server-side rendering.

artless-template is a tiny (under 200 lines), dependency-free template engine, designed for generating HTML using either template files or native Python objects.

Perfect for modern, clean server-side rendering with a focus on simplicity, performance, and patterns like HTMX and No-JS.

Why artless-template?

  • ๐Ÿชถ Tiny: Single module, no dependencies, no magic, no bloat
  • โšก Fast & Small: Under 200 LOC, built for speed (see benchmarks)
  • ๐Ÿงน Functional style: Mostly pure functions, no side effects, fully type-annotated
  • ๐Ÿ Modern: Python 3.11+ only
  • โœ… Tested: 100% test coverage.
  • ๐Ÿ“š Well-documented: With usage examples.

Quickstart

Installation

From PyPI:

$ pip install artless-template

From source:

$ git clone https://git.peterbro.su/peter/py3-artless-template
$ cd py3-artless-template
$ pip install .

Template and tags usage

Create templates/index.html with contents:

<!DOCTYPE html>
<html lang="en">
  <head>
    <meta charset="utf-8" />
    <meta name="viewport" content="width=device-width, initial-scale=1" />
    <title>@title</title>
  </head>
  <body>
    <main>
        <section>
            <h1>@header</h1>
            <table>
                <thead>
                    <tr>
                        <th>Name</th>
                        <th>Email</th>
                        <th>Admin</th>
                    </tr>
                </thead>
                @users
            </table>
        </section>
    </main>
  </body>
</html>
from typing import final
from pathlib import Path
from random import randint
from dataclasses import dataclass
from artless_template import read_template, Tag as t

TEMPLATES_DIR: Path = Path(__file__).resolve().parent / "templates"

@final
@dataclass(frozen=True, slots=True, kw_only=True)
class UserModel:
    name: str
    email: str
    is_admin: bool


users = [
    UserModel(
        name=f"User_{_}", email=f"user_{_}@gmail.com", is_admin=bool(randint(0, 1))
    )
    for _ in range(10_000)
]


users_markup = t(
    "tbody",
    [
        t(
            "tr",
            [
                t("td", user.name),
                t("td", user.email),
                t("td", "+" if user.is_admin else "-"),
            ],
        )
        for user in users
    ],
)

context = {
    "title": "Artless-template example",
    "header": "Users list",
    "users": users_markup,
}

template = read_template(TEMPLATES_DIR / "index.html").render(**context)

Template and components usage

<!DOCTYPE html>
<html lang="en">
  ...
  <body>
    <main>
      @main
    </main>
  </body>
</html>
from artless_template import read_template, Component, Tag as t

...

class UsersTableComponent:
    def __init__(self, count: int):
        self.users = [
            UserModel(
                name=f"User_{_}", email=f"user_{_}@gmail.com", is_admin=bool(randint(0, 1))
            )
            for _ in range(count)
        ]

    def view(self):
        return t(
            "table",
            [
                t(
                    "thead",
                    [
                        t(
                            "tr",
                            [
                                t("th", "Name"),
                                t("th", "Email"),
                                t("th", "Admin"),
                            ]
                        )
                    ]
                ),
                t(
                    "tbody",
                    [
                        t(
                            "tr",
                            [
                                t("td", user.name),
                                t("td", user.email),
                                t("td", "+" if user.is_admin else "-"),
                            ],
                        )
                        for user in self.users
                    ]
                )
            ]
        )

template = read_template(TEMPLATES_DIR / "index.html").render(main=UsersTableComponent(100500))

Asynchronous functions

The library provides async version of io-bound function - read_template. An asynchronous function has a prefix and called aread_template.

from artless_template import aread_template

template = await aread_template("some_template.html")
...

Read detailed reference documentation.

Performance

Performance comparison of the most popular template engines and artless-template library. The benchmark render a HTML document with table of 10 thousand user models.

Run benchmark:

$ python -m bemchmarks

Sorted results on i5 laptop (smaller is better):

{
    'mako': 0.05319607999990694,
    'jinja2': 0.27525966498069465,
    'artless': 0.5908581139810849,
    'dtl': 1.034598412021296,
    'fasthtml': 12.420113595988369
}

The performance of artless-template is better than the Django template engine, and much better than FastHTML, but worse than Jinja2 and Mako.

Roadmap

  • Simplify the Tag constructor.
  • Write detailed documentation with Sphinx.
  • Create async version of read_template() - aread_template().
  • Cythonize CPU/RAM-bound of code.
  • artless-core - the artless and ultralight web framework for building minimal APIs and apps.

Keywords

artless-template

FAQs

Did you know?

Socket

Socket for GitHub automatically highlights issues in each pull request and monitors the health of all your open source dependencies. Discover the contents of your packages and block harmful activity before you install or update your dependencies.

Install

Related posts