A Python version of JavaScript's tagged templates, mixed with Python 3's f-strings.
For a more involved example how this package can be used in practice, see htm.py that implements JSX-like syntax in plain Python.
Installation
$ pip3 install tagged
Usage
This package defines tag, a decorator for creating new tags. Let's define a simple one:
from tagged import tag @tag def t(strings, values): return strings, values
Now t can be called with a template string that can contain any Python 3 expression between { and }. The "static" parts of the string are listed in strings and the evaluated expressions are listed in values.
strings, values = t("1 + {2} equals {1 + 2}") # strings == ('1 + ', ' equals ', '') # values == (2, 3)
Because the expressions are evaluated in the current context they can refer to local variables:
a = [1, 2, 3] strings, values = t("the sum of {a} is {sum(a)}") # strings == ('the sum of ', ' is ', '') # values == ([1, 2, 3], 6)
Double curly brackets are interpreted as a single textual curly bracket:
strings, values = t("Inline a set between {{ and }} like this: {({1, 2, 3})}") # strings == ('Inline a set between { and } like this: ', '') # values == ({1, 2, 3},)
rexample
Let's define a custom tag rex that allows composing regular expressions from strings and other regular expressions.
import re from tagged import tag @tag def rex(strings, values): pattern = strings[0] for value, string in zip(values, strings[1:]): if isinstance(value, re.Pattern): value = value.pattern elif isinstance(value, str): value = re.escape(value) else: raise TypeError("expected re.Pattern or str") pattern += "(?:" + value + ")" + string return re.compile(pattern) greeting = re.compile("Hello|Hi|Greetings") name = "Python 3.7" rex("{greeting}, {name}!") # re.compile('(?:Hello|Hi|Greetings), (?:Python\\ 3\\.7)!')
Development
Running Tests
$ python3 -m unittest discover -s tests
License
This library is licensed under the MIT license. See ./LICENSE.