Clabate 0.3.0 is out!

December 3, 2021

Clabate is a minimalistic class-based template engine for the Python programming language. This 0.3.0 is a way too premature release, but I needed it in pypi to ease upgrading my web sites. So it's in production now, including this declassed.art website. There's still a lot to do: add some extras, update documentation, add examples and tests.

Links:

The major improvement in this release was escaping. The Template class provides escape method which should have to be called only once for each processed template string and substitution but it was not possible to achieve this with str.format_map method.

The solution was subclassing string.Formatter, overriding a couple of its methods to ensure escape is always invoked, and adding tracking code to the rendering context class to avoid duplicate escaping.

Sounds tricky? Right, it's tricky. String formatting was not implemented with every use case in mind and that's the libraries are for: to hide complexity. Of course, current implementation is at the initial stage, "make things working", and is far from perfect.

The codebase is now in separate files:

FileSLOC
core.py163
markup.py80
extras/pygments.py38
extras/sequence.py20
extras/invoke.py28

So, the core module is only 163 lines of pure code, without comments and blank lines. With other two modules, markup.py and extras/sequence.py, which now depends on extras/invoke.py, the codebase is bloated with 100 extra lines of code in comparison with 0.2.0 release. That's not good, is it?

The extras/invoke.py module is another major improvement. It's purpose is to allow calling methods of objects in a restricted environment, so in your template you could write something like this:

{pygments:highlight('python', '''
    print('Hello, World!')
''')}

where pygments is an instance of extras.pygments.Pygments class in your template subclass, usually provided by PygmentsMixin and highlight is its method.

The result would be:

print('Hello, World!')

Impressive, isn't it?

But allowing to call anything using, for example, eval built-in function would open a huge security hole, so I had to dig into AST, abstract syntax tree, a module which is famous with its lack of good documentation.

Surprisingly, it did not take much time to implement quite restrictive calls, where only literals are allowed as arguments. And I did not need all that Visitor crap. Although seach engines did not help much, it turned out it's quite easy to work with AST if you look at its source code.

So, extras/invoke.py module resulted in very nice implementations of various mixins

I need to finish a few things to make my template engine in line with the best packaging practices and write a comprehensive article about it. I'll do that in background and now I have to turn to other things.

To paint something, at least.