Issue #1686: Fix string.Template when overriding the pattern attribute.
This commit is contained in:
parent
98b46702d2
commit
eb19dce085
|
@ -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)
|
||||||
|
|
|
@ -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')
|
||||||
|
|
|
@ -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).
|
||||||
|
|
Loading…
Reference in New Issue