]> git.ipfire.org Git - thirdparty/Python/cpython.git/commitdiff
bpo-47066: Convert a warning about flags not at the start of the regular expression...
authorSerhiy Storchaka <storchaka@gmail.com>
Sat, 19 Mar 2022 14:10:44 +0000 (16:10 +0200)
committerGitHub <noreply@github.com>
Sat, 19 Mar 2022 14:10:44 +0000 (16:10 +0200)
Doc/library/re.rst
Doc/whatsnew/3.11.rst
Lib/sre_parse.py
Lib/test/test_re.py
Misc/NEWS.d/next/Library/2022-03-19-14-12-23.bpo-47066.we3YFx.rst [new file with mode: 0644]

index 8d62e3bf4d8d83474bb2502aff9152d7a94bc5a6..950a5b1fdc240f67a717c65ebf28e851401f2c60 100644 (file)
@@ -299,6 +299,9 @@ The special characters are:
    :func:`re.compile` function.  Flags should be used first in the
    expression string.
 
+   .. versionchanged:: 3.11
+      This construction can only be used at the start of the expression.
+
 .. index:: single: (?:; in regular expressions
 
 ``(?:...)``
index 8b3450ed404f21f477b07647727079bf1e49d1c4..b7e9dc6e9e37f8f234b14a8ed3cf8d006b4f02c3 100644 (file)
@@ -688,6 +688,11 @@ Changes in the Python API
   if no locale is specified.
   (Contributed by Victor Stinner in :issue:`46659`.)
 
+* Global inline flags (e.g. ``(?i)``) can now only be used at the start of
+  the regular expressions.  Using them not at the start of expression was
+  deprecated since Python 3.6.
+  (Contributed by Serhiy Storchaka in :issue:`47066`.)
+
 
 Build Changes
 =============
index 53706676e9f7b8ae2dff7ebce28e226d328fd37b..bb951073938706211204d255955366bd3fea108c 100644 (file)
@@ -805,16 +805,9 @@ def _parse(source, state, verbose, nested, first=False):
                     flags = _parse_flags(source, state, char)
                     if flags is None:  # global flags
                         if not first or subpattern:
-                            import warnings
-                            warnings.warn(
-                                'Flags not at the start of the expression %r%s'
-                                ' but at position %d' % (
-                                    source.string[:20],  # truncate long regexes
-                                    ' (truncated)' if len(source.string) > 20 else '',
-                                    start,
-                                ),
-                                DeprecationWarning, stacklevel=nested + 6
-                            )
+                            raise source.error('global flags not at the start '
+                                               'of the expression',
+                                               source.tell() - start)
                         if (state.flags & SRE_FLAG_VERBOSE) and not verbose:
                             raise Verbose
                         continue
index 48dcb16f8fa573337c9958c06c8a23c3a8f66e0a..f8bbe5178219ac6a4761f4fd4b7f2874d1c16fe0 100644 (file)
@@ -1439,66 +1439,22 @@ class ReTests(unittest.TestCase):
         self.assertTrue(re.match('(?x) (?i) ' + upper_char, lower_char))
         self.assertTrue(re.match(' (?x) (?i) ' + upper_char, lower_char, re.X))
 
-        p = upper_char + '(?i)'
-        with self.assertWarns(DeprecationWarning) as warns:
-            self.assertTrue(re.match(p, lower_char))
-        self.assertEqual(
-            str(warns.warnings[0].message),
-            'Flags not at the start of the expression %r'
-            ' but at position 1' % p
-        )
-        self.assertEqual(warns.warnings[0].filename, __file__)
-
-        p = upper_char + '(?i)%s' % ('.?' * 100)
-        with self.assertWarns(DeprecationWarning) as warns:
-            self.assertTrue(re.match(p, lower_char))
-        self.assertEqual(
-            str(warns.warnings[0].message),
-            'Flags not at the start of the expression %r (truncated)'
-            ' but at position 1' % p[:20]
-        )
-        self.assertEqual(warns.warnings[0].filename, __file__)
+        msg = "global flags not at the start of the expression"
+        self.checkPatternError(upper_char + '(?i)', msg, 1)
 
         # bpo-30605: Compiling a bytes instance regex was throwing a BytesWarning
         with warnings.catch_warnings():
             warnings.simplefilter('error', BytesWarning)
-            p = b'A(?i)'
-            with self.assertWarns(DeprecationWarning) as warns:
-                self.assertTrue(re.match(p, b'a'))
-            self.assertEqual(
-                str(warns.warnings[0].message),
-                'Flags not at the start of the expression %r'
-                ' but at position 1' % p
-            )
-            self.assertEqual(warns.warnings[0].filename, __file__)
-
-        with self.assertWarns(DeprecationWarning):
-            self.assertTrue(re.match('(?s).(?i)' + upper_char, '\n' + lower_char))
-        with self.assertWarns(DeprecationWarning):
-            self.assertTrue(re.match('(?i) ' + upper_char + ' (?x)', lower_char))
-        with self.assertWarns(DeprecationWarning):
-            self.assertTrue(re.match(' (?x) (?i) ' + upper_char, lower_char))
-        with self.assertWarns(DeprecationWarning):
-            self.assertTrue(re.match('^(?i)' + upper_char, lower_char))
-        with self.assertWarns(DeprecationWarning):
-            self.assertTrue(re.match('$|(?i)' + upper_char, lower_char))
-        with self.assertWarns(DeprecationWarning) as warns:
-            self.assertTrue(re.match('(?:(?i)' + upper_char + ')', lower_char))
-        self.assertRegex(str(warns.warnings[0].message),
-                         'Flags not at the start')
-        self.assertEqual(warns.warnings[0].filename, __file__)
-        with self.assertWarns(DeprecationWarning) as warns:
-            self.assertTrue(re.fullmatch('(^)?(?(1)(?i)' + upper_char + ')',
-                                         lower_char))
-        self.assertRegex(str(warns.warnings[0].message),
-                         'Flags not at the start')
-        self.assertEqual(warns.warnings[0].filename, __file__)
-        with self.assertWarns(DeprecationWarning) as warns:
-            self.assertTrue(re.fullmatch('($)?(?(1)|(?i)' + upper_char + ')',
-                                         lower_char))
-        self.assertRegex(str(warns.warnings[0].message),
-                         'Flags not at the start')
-        self.assertEqual(warns.warnings[0].filename, __file__)
+            self.checkPatternError(b'A(?i)', msg, 1)
+
+        self.checkPatternError('(?s).(?i)' + upper_char, msg, 5)
+        self.checkPatternError('(?i) ' + upper_char + ' (?x)', msg, 7)
+        self.checkPatternError(' (?x) (?i) ' + upper_char, msg, 1)
+        self.checkPatternError('^(?i)' + upper_char, msg, 1)
+        self.checkPatternError('$|(?i)' + upper_char, msg, 2)
+        self.checkPatternError('(?:(?i)' + upper_char + ')', msg, 3)
+        self.checkPatternError('(^)?(?(1)(?i)' + upper_char + ')', msg, 9)
+        self.checkPatternError('($)?(?(1)|(?i)' + upper_char + ')', msg, 10)
 
 
     def test_dollar_matches_twice(self):
diff --git a/Misc/NEWS.d/next/Library/2022-03-19-14-12-23.bpo-47066.we3YFx.rst b/Misc/NEWS.d/next/Library/2022-03-19-14-12-23.bpo-47066.we3YFx.rst
new file mode 100644 (file)
index 0000000..f28275b
--- /dev/null
@@ -0,0 +1,3 @@
+Global inline flags (e.g. ``(?i)``) can now only be used at the start of the
+regular expressions.  Using them not at the start of expression was
+deprecated since Python 3.6.