GH-83162: Rename re.error for better clarity. (#101677)

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>
This commit is contained in:
achhina 2023-12-11 15:45:08 -05:00 committed by GitHub
parent 0066ab5bc5
commit a01022af23
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
10 changed files with 53 additions and 34 deletions

View 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

View 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
-------

View file

@ -120,7 +120,7 @@ def _replace_expand(self, m, repl):
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:

View file

@ -84,7 +84,7 @@ def getprog(self):
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

View file

@ -329,7 +329,7 @@ def eval_print_amount(self, sel, list, msg):
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 = []

View file

@ -117,7 +117,8 @@
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 @@
"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

View 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):

View file

@ -20,7 +20,7 @@
# 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 @@ def __init__(self, msg, pattern=None, pos=None):
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)

View file

@ -47,7 +47,7 @@ def recurse(actual, expect):
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 @@ def checkPatternError(self, pattern, errmsg, pos=None):
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 @@ def checkTemplateError(self, pattern, repl, string, errmsg, pos=None):
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 @@ def test_basic_re_sub(self):
(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 @@ def test_other_escapes(self):
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 @@ def test_lookbehind(self):
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 @@ def test_sre_byte_literals(self):
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 @@ def test_sre_byte_class_literals(self):
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 @@ def test_ascii_and_unicode_flag(self):
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 @@ def test_locale_flag(self):
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 @@ def test_locale_compiled(self):
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 @@ def test_error(self):
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 @@ def test_re_tests(self):
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

View file

@ -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.