I haven't been able to find a good example of subclassing string.Template in Python, even though I've seen multiple references to doing so in documentation.
Are there any examples of this on the web?
I want to change the $ to be a different character and maybe change the regex for identifiers.
From python docs:
Advanced usage: you can derive
subclasses of Template to customize
the placeholder syntax, delimiter
character, or the entire regular
expression used to parse template
strings. To do this, you can override
these class attributes:
delimiter – This is the literal string describing a placeholder
introducing delimiter. The default
value $. Note that this should not be
a regular expression, as the
implementation will call re.escape()
on this string as needed.
idpattern – This is the regular expression describing the pattern for
non-braced placeholders (the braces
will be added automatically as
appropriate). The default value is the
regular expression [_a-z][_a-z0-9]*.
Example:
from string import Template
class MyTemplate(Template):
delimiter = '#'
idpattern = r'[a-z][_a-z0-9]*'
>>> s = MyTemplate('#who likes $what')
>>> s.substitute(who='tim', what='kung pao')
'tim likes $what'
In python 3:
New in version 3.2.
Alternatively, you can provide the entire regular expression pattern
by overriding the class attribute pattern. If you do this, the value
must be a regular expression object with four named capturing groups.
The capturing groups correspond to the rules given above, along with
the invalid placeholder rule:
- escaped – This group matches the escape sequence, e.g. $$, in the default pattern.
- named – This group matches the unbraced placeholder name; it should not include the delimiter in capturing group.
- braced – This group matches the brace enclosed placeholder name; it should not include either the delimiter or braces in the capturing
group.
- invalid – This group matches any other delimiter pattern (usually a single delimiter), and it should appear last in the regular
expression.
Example:
from string import Template
import re
class TemplateClone(Template):
delimiter = '$'
pattern = r'''
\$(?:
(?P<escaped>\$) | # Escape sequence of two delimiters
(?P<named>[_a-z][_a-z0-9]*) | # delimiter and a Python identifier
{(?P<braced>[_a-z][_a-z0-9]*)} | # delimiter and a braced identifier
(?P<invalid>) # Other ill-formed delimiter exprs
)
'''
class TemplateAlternative(Template):
delimiter = '[-'
pattern = r'''
\[-(?:
(?P<escaped>-) | # Expression [-- will become [-
(?P<named>[^\[\]\n-]+)-\] | # -, [, ], and \n can't be used in names
\b\B(?P<braced>) | # Braced names disabled
(?P<invalid>) #
)
'''
>>> t = TemplateClone("$hi sir")
>>> t.substitute({"hi": "hello"})
'hello sir'
>>> ta = TemplateAlternative("[-hi-] sir")
>>> ta.substitute({"hi": "have a nice day"})
'have a nice day sir'
>>> ta = TemplateAlternative("[--[-hi-]-]")
>>> ta.substitute({"hi": "have a nice day"})
'[-have a nice day-]'
Apparently it is also possible to just omit any of the regex groups escaped
, named
, braced
or invalid
to disable it.