]> git.ipfire.org Git - thirdparty/Python/cpython.git/commitdiff
GH-83162: Rename re.error for better clarity. (#101677)
authorachhina <amanschhina@gmail.com>
Mon, 11 Dec 2023 20:45:08 +0000 (15:45 -0500)
committerGitHub <noreply@github.com>
Mon, 11 Dec 2023 20:45:08 +0000 (15:45 -0500)
Renamed re.error for clarity, and kept re.error for backward compatibility.
Updated idlelib files at TJR's request.
---------

Co-authored-by: Matthias Bussonnier <mbussonnier@ucmerced.edu>
Co-authored-by: Hugo van Kemenade <hugovk@users.noreply.github.com>
Co-authored-by: Terry Jan Reedy <tjreedy@udel.edu>
Doc/library/re.rst
Doc/whatsnew/3.13.rst
Lib/idlelib/replace.py
Lib/idlelib/searchengine.py
Lib/pstats.py
Lib/re/__init__.py
Lib/re/_compiler.py
Lib/re/_constants.py
Lib/test/test_re.py
Misc/NEWS.d/next/Library/2023-02-08-00-43-29.gh-issue-83162.ufdI9F.rst [new file with mode: 0644]

index 251ec8ca0021a652c873c59429fe5a6e5fa012cf..302f7224de4a7a082b01f23e2a9aab02be28b8fb 100644 (file)
@@ -1093,12 +1093,12 @@ Functions
 Exceptions
 ^^^^^^^^^^
 
-.. exception:: error(msg, pattern=None, pos=None)
+.. exception:: PatternError(msg, pattern=None, pos=None)
 
    Exception raised when a string passed to one of the functions here is not a
    valid regular expression (for example, it might contain unmatched parentheses)
    or when some other error occurs during compilation or matching.  It is never an
-   error if a string contains no match for a pattern.  The error instance has
+   error if a string contains no match for a pattern.  The ``PatternError`` instance has
    the following additional attributes:
 
    .. attribute:: msg
@@ -1124,6 +1124,10 @@ Exceptions
    .. versionchanged:: 3.5
       Added additional attributes.
 
+   .. versionchanged:: 3.13
+      ``PatternError`` was originally named ``error``; the latter is kept as an alias for
+      backward compatibility.
+
 .. _re-objects:
 
 Regular Expression Objects
index 00f396846e29bd0e7e41f7b16188d89464164603..d599ba9ae6fac85df4281394a9a4c0c6a17bb0e0 100644 (file)
@@ -298,6 +298,11 @@ pdb
   command line option or :envvar:`PYTHONSAFEPATH` environment variable).
   (Contributed by Tian Gao and Christian Walther in :gh:`111762`.)
 
+re
+--
+* Rename :exc:`!re.error` to :exc:`re.PatternError` for improved clarity.
+  :exc:`!re.error` is kept for backward compatibility.
+
 sqlite3
 -------
 
index a29ca59142749157f447a82c88172f393af7f004..7997f24f1b0fa6a28928cae93b5c75dfff2b3891 100644 (file)
@@ -120,7 +120,7 @@ class ReplaceDialog(SearchDialogBase):
         if self.engine.isre():
             try:
                 new = m.expand(repl)
-            except re.error:
+            except re.PatternError:
                 self.engine.report_error(repl, 'Invalid Replace Expression')
                 new = None
         else:
index 0684142f43644af5ad3a3a9f98d99111f51ed431..ceb38cfaef900ba4d2f0d6557c5270c5f8da5415 100644 (file)
@@ -84,7 +84,7 @@ class SearchEngine:
             flags = flags | re.IGNORECASE
         try:
             prog = re.compile(pat, flags)
-        except re.error as e:
+        except re.PatternError as e:
             self.report_error(pat, e.msg, e.pos)
             return None
         return prog
index 51bcca8418874009bf1887aa0f3ce6b4ae528f3c..2f054bb4011e7f2576105a61458bab6bc430a86d 100644 (file)
@@ -329,7 +329,7 @@ class Stats:
         if isinstance(sel, str):
             try:
                 rex = re.compile(sel)
-            except re.error:
+            except re.PatternError:
                 msg += "   <Invalid regular expression %r>\n" % sel
                 return new_list, msg
             new_list = []
index 428d1b0d5fbd8757e145d1d0b8f1368e530f20f1..7e8abbf6ffe15526495a4241ed2153d34a1beba9 100644 (file)
@@ -117,7 +117,8 @@ A, L, and U are mutually exclusive.
     U  UNICODE     For compatibility only. Ignored for string patterns (it
                    is the default), and forbidden for bytes patterns.
 
-This module also defines an exception 'error'.
+This module also defines exception 'PatternError', aliased to 'error' for
+backward compatibility.
 
 """
 
@@ -133,7 +134,7 @@ __all__ = [
     "findall", "finditer", "compile", "purge", "escape",
     "error", "Pattern", "Match", "A", "I", "L", "M", "S", "X", "U",
     "ASCII", "IGNORECASE", "LOCALE", "MULTILINE", "DOTALL", "VERBOSE",
-    "UNICODE", "NOFLAG", "RegexFlag",
+    "UNICODE", "NOFLAG", "RegexFlag", "PatternError"
 ]
 
 __version__ = "2.2.1"
@@ -155,7 +156,7 @@ class RegexFlag:
     _numeric_repr_ = hex
 
 # sre exception
-error = _compiler.error
+PatternError = error = _compiler.PatternError
 
 # --------------------------------------------------------------------
 # public interface
index f87712d6d6f9f896054299e3ea60c13e829bd15d..7b888f877eb3dce94ccf4974eb3078dc41eed626 100644 (file)
@@ -150,7 +150,7 @@ def _compile(code, pattern, flags):
                 if lo > MAXCODE:
                     raise error("looks too much behind")
                 if lo != hi:
-                    raise error("look-behind requires fixed-width pattern")
+                    raise PatternError("look-behind requires fixed-width pattern")
                 emit(lo) # look behind
             _compile(code, av[1], flags)
             emit(SUCCESS)
@@ -209,7 +209,7 @@ def _compile(code, pattern, flags):
             else:
                 code[skipyes] = _len(code) - skipyes + 1
         else:
-            raise error("internal: unsupported operand type %r" % (op,))
+            raise PatternError(f"internal: unsupported operand type {op!r}")
 
 def _compile_charset(charset, flags, code):
     # compile charset subprogram
@@ -235,7 +235,7 @@ def _compile_charset(charset, flags, code):
             else:
                 emit(av)
         else:
-            raise error("internal: unsupported set operator %r" % (op,))
+            raise PatternError(f"internal: unsupported set operator {op!r}")
     emit(FAILURE)
 
 def _optimize_charset(charset, iscased=None, fixup=None, fixes=None):
index d8e483ac4f23b4b1883c5833342c54b268aa43a0..9c3c294ba448b416c6e06c1c41549906e7bb3098 100644 (file)
@@ -20,7 +20,7 @@ from _sre import MAXREPEAT, MAXGROUPS
 # SRE standard exception (access as sre.error)
 # should this really be here?
 
-class error(Exception):
+class PatternError(Exception):
     """Exception raised for invalid regular expressions.
 
     Attributes:
@@ -53,6 +53,9 @@ class error(Exception):
         super().__init__(msg)
 
 
+# Backward compatibility after renaming in 3.13
+error = PatternError
+
 class _NamedIntConstant(int):
     def __new__(cls, value, name):
         self = super(_NamedIntConstant, cls).__new__(cls, value)
index 1eca22f45378df1b3ecb58c18b1b9c0c3a588bf8..993a7d6e264a1f4a10841a8069b33f5795d1b0fb 100644 (file)
@@ -47,7 +47,7 @@ class ReTests(unittest.TestCase):
         recurse(actual, expect)
 
     def checkPatternError(self, pattern, errmsg, pos=None):
-        with self.assertRaises(re.error) as cm:
+        with self.assertRaises(re.PatternError) as cm:
             re.compile(pattern)
         with self.subTest(pattern=pattern):
             err = cm.exception
@@ -56,7 +56,7 @@ class ReTests(unittest.TestCase):
                 self.assertEqual(err.pos, pos)
 
     def checkTemplateError(self, pattern, repl, string, errmsg, pos=None):
-        with self.assertRaises(re.error) as cm:
+        with self.assertRaises(re.PatternError) as cm:
             re.sub(pattern, repl, string)
         with self.subTest(pattern=pattern, repl=repl):
             err = cm.exception
@@ -64,6 +64,9 @@ class ReTests(unittest.TestCase):
             if pos is not None:
                 self.assertEqual(err.pos, pos)
 
+    def test_error_is_PatternError_alias(self):
+        assert re.error is re.PatternError
+
     def test_keep_buffer(self):
         # See bug 14212
         b = bytearray(b'x')
@@ -154,7 +157,7 @@ class ReTests(unittest.TestCase):
                          (chr(9)+chr(10)+chr(11)+chr(13)+chr(12)+chr(7)+chr(8)))
         for c in 'cdehijklmopqsuwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ':
             with self.subTest(c):
-                with self.assertRaises(re.error):
+                with self.assertRaises(re.PatternError):
                     self.assertEqual(re.sub('a', '\\' + c, 'a'), '\\' + c)
 
         self.assertEqual(re.sub(r'^\s*', 'X', 'test'), 'Xtest')
@@ -836,10 +839,10 @@ class ReTests(unittest.TestCase):
         re.purge()  # for warnings
         for c in 'ceghijklmopqyzCEFGHIJKLMNOPQRTVXY':
             with self.subTest(c):
-                self.assertRaises(re.error, re.compile, '\\%c' % c)
+                self.assertRaises(re.PatternError, re.compile, '\\%c' % c)
         for c in 'ceghijklmopqyzABCEFGHIJKLMNOPQRTVXYZ':
             with self.subTest(c):
-                self.assertRaises(re.error, re.compile, '[\\%c]' % c)
+                self.assertRaises(re.PatternError, re.compile, '[\\%c]' % c)
 
     def test_named_unicode_escapes(self):
         # test individual Unicode named escapes
@@ -970,14 +973,14 @@ class ReTests(unittest.TestCase):
         self.assertIsNone(re.match(r'(?:(a)|(x))b(?<=(?(1)c|x))c', 'abc'))
         self.assertTrue(re.match(r'(?:(a)|(x))b(?<=(?(1)b|x))c', 'abc'))
         # Group used before defined.
-        self.assertRaises(re.error, re.compile, r'(a)b(?<=(?(2)b|x))(c)')
+        self.assertRaises(re.PatternError, re.compile, r'(a)b(?<=(?(2)b|x))(c)')
         self.assertIsNone(re.match(r'(a)b(?<=(?(1)c|x))(c)', 'abc'))
         self.assertTrue(re.match(r'(a)b(?<=(?(1)b|x))(c)', 'abc'))
         # Group defined in the same lookbehind pattern
-        self.assertRaises(re.error, re.compile, r'(a)b(?<=(.)\2)(c)')
-        self.assertRaises(re.error, re.compile, r'(a)b(?<=(?P<a>.)(?P=a))(c)')
-        self.assertRaises(re.error, re.compile, r'(a)b(?<=(a)(?(2)b|x))(c)')
-        self.assertRaises(re.error, re.compile, r'(a)b(?<=(.)(?<=\2))(c)')
+        self.assertRaises(re.PatternError, re.compile, r'(a)b(?<=(.)\2)(c)')
+        self.assertRaises(re.PatternError, re.compile, r'(a)b(?<=(?P<a>.)(?P=a))(c)')
+        self.assertRaises(re.PatternError, re.compile, r'(a)b(?<=(a)(?(2)b|x))(c)')
+        self.assertRaises(re.PatternError, re.compile, r'(a)b(?<=(.)(?<=\2))(c)')
 
     def test_ignore_case(self):
         self.assertEqual(re.match("abc", "ABC", re.I).group(0), "ABC")
@@ -1318,8 +1321,8 @@ class ReTests(unittest.TestCase):
             self.assertTrue(re.match((r"\x%02x" % i).encode(), bytes([i])))
             self.assertTrue(re.match((r"\x%02x0" % i).encode(), bytes([i])+b"0"))
             self.assertTrue(re.match((r"\x%02xz" % i).encode(), bytes([i])+b"z"))
-        self.assertRaises(re.error, re.compile, br"\u1234")
-        self.assertRaises(re.error, re.compile, br"\U00012345")
+        self.assertRaises(re.PatternError, re.compile, br"\u1234")
+        self.assertRaises(re.PatternError, re.compile, br"\U00012345")
         self.assertTrue(re.match(br"\0", b"\000"))
         self.assertTrue(re.match(br"\08", b"\0008"))
         self.assertTrue(re.match(br"\01", b"\001"))
@@ -1341,8 +1344,8 @@ class ReTests(unittest.TestCase):
             self.assertTrue(re.match((r"[\x%02x]" % i).encode(), bytes([i])))
             self.assertTrue(re.match((r"[\x%02x0]" % i).encode(), bytes([i])))
             self.assertTrue(re.match((r"[\x%02xz]" % i).encode(), bytes([i])))
-        self.assertRaises(re.error, re.compile, br"[\u1234]")
-        self.assertRaises(re.error, re.compile, br"[\U00012345]")
+        self.assertRaises(re.PatternError, re.compile, br"[\u1234]")
+        self.assertRaises(re.PatternError, re.compile, br"[\U00012345]")
         self.checkPatternError(br"[\567]",
                                r'octal escape value \567 outside of '
                                r'range 0-0o377', 1)
@@ -1675,11 +1678,11 @@ class ReTests(unittest.TestCase):
             self.assertIsNone(pat.match(b'\xe0'))
         # Incompatibilities
         self.assertRaises(ValueError, re.compile, br'\w', re.UNICODE)
-        self.assertRaises(re.error, re.compile, br'(?u)\w')
+        self.assertRaises(re.PatternError, re.compile, br'(?u)\w')
         self.assertRaises(ValueError, re.compile, r'\w', re.UNICODE | re.ASCII)
         self.assertRaises(ValueError, re.compile, r'(?u)\w', re.ASCII)
         self.assertRaises(ValueError, re.compile, r'(?a)\w', re.UNICODE)
-        self.assertRaises(re.error, re.compile, r'(?au)\w')
+        self.assertRaises(re.PatternError, re.compile, r'(?au)\w')
 
     def test_locale_flag(self):
         enc = locale.getpreferredencoding()
@@ -1720,11 +1723,11 @@ class ReTests(unittest.TestCase):
             self.assertIsNone(pat.match(bletter))
         # Incompatibilities
         self.assertRaises(ValueError, re.compile, '', re.LOCALE)
-        self.assertRaises(re.error, re.compile, '(?L)')
+        self.assertRaises(re.PatternError, re.compile, '(?L)')
         self.assertRaises(ValueError, re.compile, b'', re.LOCALE | re.ASCII)
         self.assertRaises(ValueError, re.compile, b'(?L)', re.ASCII)
         self.assertRaises(ValueError, re.compile, b'(?a)', re.LOCALE)
-        self.assertRaises(re.error, re.compile, b'(?aL)')
+        self.assertRaises(re.PatternError, re.compile, b'(?aL)')
 
     def test_scoped_flags(self):
         self.assertTrue(re.match(r'(?i:a)b', 'Ab'))
@@ -2060,7 +2063,7 @@ class ReTests(unittest.TestCase):
         self.assertIsNone(p4.match(b'\xc5\xc5'))
 
     def test_error(self):
-        with self.assertRaises(re.error) as cm:
+        with self.assertRaises(re.PatternError) as cm:
             re.compile('(\u20ac))')
         err = cm.exception
         self.assertIsInstance(err.pattern, str)
@@ -2072,14 +2075,14 @@ class ReTests(unittest.TestCase):
         self.assertIn(' at position 3', str(err))
         self.assertNotIn(' at position 3', err.msg)
         # Bytes pattern
-        with self.assertRaises(re.error) as cm:
+        with self.assertRaises(re.PatternError) as cm:
             re.compile(b'(\xa4))')
         err = cm.exception
         self.assertIsInstance(err.pattern, bytes)
         self.assertEqual(err.pattern, b'(\xa4))')
         self.assertEqual(err.pos, 3)
         # Multiline pattern
-        with self.assertRaises(re.error) as cm:
+        with self.assertRaises(re.PatternError) as cm:
             re.compile("""
                 (
                     abc
@@ -2820,7 +2823,7 @@ class ExternalTests(unittest.TestCase):
 
             with self.subTest(pattern=pattern, string=s):
                 if outcome == SYNTAX_ERROR:  # Expected a syntax error
-                    with self.assertRaises(re.error):
+                    with self.assertRaises(re.PatternError):
                         re.compile(pattern)
                     continue
 
diff --git a/Misc/NEWS.d/next/Library/2023-02-08-00-43-29.gh-issue-83162.ufdI9F.rst b/Misc/NEWS.d/next/Library/2023-02-08-00-43-29.gh-issue-83162.ufdI9F.rst
new file mode 100644 (file)
index 0000000..6074dd7
--- /dev/null
@@ -0,0 +1,3 @@
+Renamed :exc:`!re.error` to :exc:`PatternError` for clarity, and kept
+:exc:`!re.error` for backward compatibility. Patch by Matthias Bussonnier and
+Adam Chhina.