import string
class Template(string.Template):
"""
Template with modified functions
-- doctests ----
>>> t = 'this is a $test with $result'
>>> st = Template(t, 'haha')
>>> d = {'test': 'a big test'}
>>> result = st.safe_substitute(d)
>>> expected_result = 'this is a a big test with haha'
>>> test_result = True if expected_result == result else 'expected %s >>> but got <<< %s' % (expected_result, result)
>>> test_result
True
>>> st = Template(t)
>>> d = {'test': 'a big test'}
>>> result = st.safe_substitute(d)
>>> expected_result = 'this is a a big test with $result'
>>> test_result = True if expected_result == result else 'expected %s >>> but got <<< %s' % (expected_result, result)
>>> test_result
True
"""
def __init__(self, template, default_substitution_value = None):
string.Template(template)
self.default_substitution_value = default_substitution_value
self.template = template
def safe_substitute(self, *args, **kws):
'''
Returns template with placeholders substituted
if no substitution value is specified, the
default_substitution_value
is used
'''
if len(args) > 1:
raise TypeError('Too many positional arguments')
if not args:
mapping = kws
elif kws:
mapping = _multimap(kws, args[0])
else:
mapping = args[0]
# Helper function for .sub()
def convert(mo):
named = mo.group('named')
if named is not None:
try:
# We use this idiom instead of str() because the latter
# will fail if val is a Unicode containing non-ASCII
return '%s' % (mapping[named],)
except KeyError:
if self.default_substitution_value:
return self.default_substitution_value
return self.delimiter + named
braced = mo.group('braced')
if braced is not None:
try:
return '%s' % (mapping[braced],)
except KeyError:
return self.delimiter + '{' + braced + '}'
if mo.group('escaped') is not None:
return self.delimiter
if mo.group('invalid') is not None:
return self.delimiter
raise ValueError('Unrecognized named group in pattern',
self.pattern)
return self.pattern.sub(convert, self.template)