]> granicus.if.org Git - python/commitdiff
bpo-31672: Restore the former behavior when override flags in Template. (#5099)
authorSerhiy Storchaka <storchaka@gmail.com>
Thu, 4 Jan 2018 17:20:11 +0000 (19:20 +0200)
committerGitHub <noreply@github.com>
Thu, 4 Jan 2018 17:20:11 +0000 (19:20 +0200)
Overriding flags to 0 will make the default pattern matching only
lower case letters.

Doc/library/string.rst
Lib/string.py
Lib/test/test_string.py

index e9606783ef796afad04f507c3190e65bc9a83442..fc3d94bfbfca00071914fadde717b871415b7aa9 100644 (file)
@@ -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
index fd4b1f7a62f10da5c43b5cc3b1ab658b4135d7fe..b9d6f5eb5675f6f42f26263238b9ae4be59acd1f 100644 (file)
@@ -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
 
index 3480459c282c1df3ec204db6a827580d9edb6620..0be28fdb609eaee79db89d1889cf389529c9ab98 100644 (file)
@@ -219,6 +219,16 @@ class TestTemplate(unittest.TestCase):
         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 TestTemplate(unittest.TestCase):
         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.