[Python-checkins] bpo-31672: Restore the former behavior when override flags in Template. (#5099)

Serhiy Storchaka webhook-mailer at python.org
Thu Jan 4 12:20:15 EST 2018


https://github.com/python/cpython/commit/87be28f4a1c5b76926c71a3d9f92503f9eb82d51
commit: 87be28f4a1c5b76926c71a3d9f92503f9eb82d51
branch: master
author: Serhiy Storchaka <storchaka at gmail.com>
committer: GitHub <noreply at github.com>
date: 2018-01-04T19:20:11+02:00
summary:

bpo-31672: Restore the former behavior when override flags in Template. (#5099)

Overriding flags to 0 will make the default pattern matching only
lower case letters.

files:
M Doc/library/string.rst
M Lib/string.py
M Lib/test/test_string.py

diff --git a/Doc/library/string.rst b/Doc/library/string.rst
index e9606783ef7..fc3d94bfbfc 100644
--- a/Doc/library/string.rst
+++ b/Doc/library/string.rst
@@ -755,19 +755,14 @@ attributes:
 
 * *idpattern* -- This is the regular expression describing the pattern for
   non-braced placeholders.  The default value is the regular expression
-  ``(?a:[_a-zA-Z][_a-zA-Z0-9]*)``.  If this is given and *braceidpattern* is
+  ``(?a:[_a-z][_a-z0-9]*)``.  If this is given and *braceidpattern* is
   ``None`` this pattern will also apply to braced placeholders.
 
   .. note::
 
      Since default *flags* is ``re.IGNORECASE``, pattern ``[a-z]`` can match
      with some non-ASCII characters. That's why we use the local ``a`` flag
-     here.  Further, with the default *flags* value, including ``A-Z`` in the
-     ranges is redundant, but required for backward compatibility.
-
-     While *flags* is kept to ``re.IGNORECASE`` for backward compatibility,
-     you can override it to ``0`` or ``re.IGNORECASE | re.ASCII`` when
-     subclassing.
+     here.
 
   .. versionchanged:: 3.7
      *braceidpattern* can be used to define separate patterns used inside and
diff --git a/Lib/string.py b/Lib/string.py
index fd4b1f7a62f..b9d6f5eb567 100644
--- a/Lib/string.py
+++ b/Lib/string.py
@@ -82,11 +82,8 @@ class Template(metaclass=_TemplateMetaclass):
     # r'[a-z]' matches to non-ASCII letters when used with IGNORECASE, but
     # without the ASCII flag.  We can't add re.ASCII to flags because of
     # backward compatibility.  So we use the ?a local flag and [a-z] pattern.
-    # We also can't remove the A-Z ranges, because although they are
-    # technically redundant with the IGNORECASE flag, the value is part of the
-    # publicly documented API.
     # See https://bugs.python.org/issue31672
-    idpattern = r'(?a:[_a-zA-Z][_a-zA-Z0-9]*)'
+    idpattern = r'(?a:[_a-z][_a-z0-9]*)'
     braceidpattern = None
     flags = _re.IGNORECASE
 
diff --git a/Lib/test/test_string.py b/Lib/test/test_string.py
index 3480459c282..0be28fdb609 100644
--- a/Lib/test/test_string.py
+++ b/Lib/test/test_string.py
@@ -219,6 +219,16 @@ def test_regular_templates_with_braces(self):
         self.assertRaises(KeyError, s.substitute,
                           dict(who='tim', what='ham'))
 
+    def test_regular_templates_with_upper_case(self):
+        s = Template('$WHO likes ${WHAT} for ${MEAL}')
+        d = dict(WHO='tim', WHAT='ham', MEAL='dinner')
+        self.assertEqual(s.substitute(d), 'tim likes ham for dinner')
+
+    def test_regular_templates_with_non_letters(self):
+        s = Template('$_wh0_ likes ${_w_h_a_t_} for ${mea1}')
+        d = dict(_wh0_='tim', _w_h_a_t_='ham', mea1='dinner')
+        self.assertEqual(s.substitute(d), 'tim likes ham for dinner')
+
     def test_escapes(self):
         eq = self.assertEqual
         s = Template('$who likes to eat a bag of $$what worth $$100')
@@ -288,6 +298,14 @@ class PathPattern(Template):
         s = PathPattern('$bag.foo.who likes to eat a bag of $bag.what')
         self.assertEqual(s.substitute(m), 'tim likes to eat a bag of ham')
 
+    def test_flags_override(self):
+        class MyPattern(Template):
+            flags = 0
+        s = MyPattern('$wHO likes ${WHAT} for ${meal}')
+        d = dict(wHO='tim', WHAT='ham', meal='dinner', w='fred')
+        self.assertRaises(ValueError, s.substitute, d)
+        self.assertEqual(s.safe_substitute(d), 'fredHO likes ${WHAT} for dinner')
+
     def test_idpattern_override_inside_outside(self):
         # bpo-1198569: Allow the regexp inside and outside braces to be
         # different when deriving from Template.



More information about the Python-checkins mailing list