Issue #1686: Fix string.Template when overriding the pattern attribute.

This commit is contained in:
Florent Xicluna 2010-09-18 23:34:07 +00:00
parent 98b46702d2
commit eb19dce085
3 changed files with 39 additions and 9 deletions

View File

@ -145,24 +145,18 @@ class Template(metaclass=_TemplateMetaclass):
mapping = args[0] mapping = args[0]
# Helper function for .sub() # Helper function for .sub()
def convert(mo): def convert(mo):
named = mo.group('named') named = mo.group('named') or mo.group('braced')
if named is not None: if named is not None:
try: try:
# We use this idiom instead of str() because the latter # We use this idiom instead of str() because the latter
# will fail if val is a Unicode containing non-ASCII # will fail if val is a Unicode containing non-ASCII
return '%s' % (mapping[named],) return '%s' % (mapping[named],)
except KeyError: except KeyError:
return self.delimiter + named return mo.group()
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: if mo.group('escaped') is not None:
return self.delimiter return self.delimiter
if mo.group('invalid') is not None: if mo.group('invalid') is not None:
return self.delimiter return mo.group()
raise ValueError('Unrecognized named group in pattern', raise ValueError('Unrecognized named group in pattern',
self.pattern) self.pattern)
return self.pattern.sub(convert, self.template) return self.pattern.sub(convert, self.template)

View File

@ -125,6 +125,40 @@ class TestTemplate(unittest.TestCase):
self.assertRaises(ValueError, s.substitute, {}) self.assertRaises(ValueError, s.substitute, {})
self.assertRaises(ValueError, s.safe_substitute, {}) self.assertRaises(ValueError, s.safe_substitute, {})
def test_braced_override(self):
class MyTemplate(Template):
pattern = r"""
\$(?:
(?P<escaped>$) |
(?P<named>[_a-z][_a-z0-9]*) |
@@(?P<braced>[_a-z][_a-z0-9]*)@@ |
(?P<invalid>) |
)
"""
tmpl = 'PyCon in $@@location@@'
t = MyTemplate(tmpl)
self.assertRaises(KeyError, t.substitute, {})
val = t.substitute({'location': 'Cleveland'})
self.assertEqual(val, 'PyCon in Cleveland')
def test_braced_override_safe(self):
class MyTemplate(Template):
pattern = r"""
\$(?:
(?P<escaped>$) |
(?P<named>[_a-z][_a-z0-9]*) |
@@(?P<braced>[_a-z][_a-z0-9]*)@@ |
(?P<invalid>) |
)
"""
tmpl = 'PyCon in $@@location@@'
t = MyTemplate(tmpl)
self.assertEqual(t.safe_substitute(), tmpl)
val = t.safe_substitute({'location': 'Cleveland'})
self.assertEqual(val, 'PyCon in Cleveland')
def test_unicode_values(self): def test_unicode_values(self):
s = Template('$who likes $what') s = Template('$who likes $what')
d = dict(who='t\xffm', what='f\xfe\fed') d = dict(who='t\xffm', what='f\xfe\fed')

View File

@ -52,6 +52,8 @@ Core and Builtins
Library Library
------- -------
- Issue #1686: Fix string.Template when overriding the pattern attribute.
- Issue #9854: SocketIO objects now observe the RawIOBase interface in - Issue #9854: SocketIO objects now observe the RawIOBase interface in
non-blocking mode: they return None when an operation would block (instead non-blocking mode: they return None when an operation would block (instead
of raising an exception). of raising an exception).