Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

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

Merged
merged 20 commits into from
Dec 11, 2023
Merged
Show file tree
Hide file tree
Changes from 1 commit
Commits
Show all changes
20 commits
Select commit Hold shift + click to select a range
aa576a5
Renamed re.error for clarity, and kept re.error for backward compatib…
achhina Feb 8, 2023
e72dce1
GH-83162: Fix deprecated sre_compile to _compiler.
achhina Feb 8, 2023
5274810
GH-83162: Update _compiler and _constants to new exception name.
achhina Feb 8, 2023
0eca4ac
Adding code review commit suggestions, and adding re.error rename to …
achhina May 29, 2023
db36a4a
Fixed re.error to be a code directive instead of an exception directive.
achhina May 29, 2023
bc44d0f
Update Doc/whatsnew/3.13.rst
achhina Jun 4, 2023
a2a81b5
Update Misc/NEWS.d/next/Library/2023-02-08-00-43-29.gh-issue-83162.uf…
achhina Jun 4, 2023
d5e2c44
Merge branch 'main' into GH-83162
achhina Jun 4, 2023
01a62e4
Merge remote-tracking branch 'upstream/main' into GH-83162
achhina Jun 6, 2023
f82d18a
Renamed ReCompileError to PatternError.
achhina Jun 6, 2023
7b05098
Rename re.error to re.PatternError in idelib relpace.py.
achhina Jun 6, 2023
2e3bcef
Update Modules/_xxtestfuzz/fuzzer.c
achhina Jun 7, 2023
6b0bee2
Update Modules/_xxtestfuzz/fuzzer.c
achhina Jun 7, 2023
09e942b
Reverted patch for fuzzer.c.
achhina Jun 7, 2023
b31d321
Merge remote-tracking branch 'upstream/main' into GH-83162
achhina Jun 7, 2023
aac93f2
GH-83162: Resolved merge conflicts.
achhina Aug 27, 2023
b0d31d7
Merge remote-tracking branch 'upstream/main' into GH-83162
achhina Aug 27, 2023
72480cf
GH-83162: Satisfy merge conflict.
achhina Dec 3, 2023
1d3d472
GH-83162: Unwrap paragraph.
achhina Dec 3, 2023
f0a3cb0
GH-83162: Add space back in.
achhina Dec 3, 2023
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Next Next commit
Renamed re.error for clarity, and kept re.error for backward compatib…
…ility.

Co-authored-by: Matthias Bussonnier <[email protected]>
  • Loading branch information
achhina and Matthias Bussonnier committed May 28, 2023
commit aa576a5d8c295b2d53f8060deb1a25e2b5742f3c
14 changes: 9 additions & 5 deletions Doc/library/re.rst
Original file line number Diff line number Diff line change
Expand Up @@ -1080,13 +1080,13 @@ Functions
Exceptions
^^^^^^^^^^

.. exception:: error(msg, pattern=None, pos=None)
.. exception:: ReCompileError(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
the following additional attributes:
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
achhina marked this conversation as resolved.
Show resolved Hide resolved
``ReCompileError`` instance has the following additional attributes:

.. attribute:: msg

Expand All @@ -1111,6 +1111,10 @@ Exceptions
.. versionchanged:: 3.5
Added additional attributes.

.. versionchanged:: 3.12
achhina marked this conversation as resolved.
Show resolved Hide resolved
``ReCompileError`` was originally named ``error``; the latter is kept as an alias for
backward compatibility.

.. _re-objects:

Regular Expression Objects
Expand Down
2 changes: 1 addition & 1 deletion Lib/idlelib/searchengine.py
Original file line number Diff line number Diff line change
Expand Up @@ -84,7 +84,7 @@ def getprog(self):
flags = flags | re.IGNORECASE
try:
prog = re.compile(pat, flags)
except re.error as e:
except re.ReCompileError as e:
self.report_error(pat, e.msg, e.pos)
return None
return prog
Expand Down
2 changes: 1 addition & 1 deletion Lib/pstats.py
Original file line number Diff line number Diff line change
Expand Up @@ -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.ReCompileError:
msg += " <Invalid regular expression %r>\n" % sel
return new_list, msg
new_list = []
Expand Down
7 changes: 4 additions & 3 deletions Lib/re/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -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 'ReCompileError', aliased to 'error' for
backward compatibility.

"""

Expand All @@ -133,7 +134,7 @@
"findall", "finditer", "compile", "purge", "template", "escape",
"error", "Pattern", "Match", "A", "I", "L", "M", "S", "X", "U",
"ASCII", "IGNORECASE", "LOCALE", "MULTILINE", "DOTALL", "VERBOSE",
"UNICODE", "NOFLAG", "RegexFlag",
"UNICODE", "NOFLAG", "RegexFlag", "ReCompileError"
]

__version__ = "2.2.1"
Expand All @@ -156,7 +157,7 @@ class RegexFlag:
_numeric_repr_ = hex

# sre exception
error = _compiler.error
ReCompileError = error = sre_compile.ReCompileError

# --------------------------------------------------------------------
# public interface
Expand Down
47 changes: 25 additions & 22 deletions Lib/test/test_re.py
Original file line number Diff line number Diff line change
Expand Up @@ -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.ReCompileError) as cm:
re.compile(pattern)
with self.subTest(pattern=pattern):
err = cm.exception
Expand All @@ -56,14 +56,17 @@ 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.ReCompileError) as cm:
re.sub(pattern, repl, string)
with self.subTest(pattern=pattern, repl=repl):
err = cm.exception
self.assertEqual(err.msg, errmsg)
if pos is not None:
self.assertEqual(err.pos, pos)

def test_error_is_ReCompileError_alias(self):
assert re.error is re.ReCompileError

def test_keep_buffer(self):
# See bug 14212
b = bytearray(b'x')
Expand Down Expand Up @@ -152,7 +155,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.ReCompileError):
self.assertEqual(re.sub('a', '\\' + c, 'a'), '\\' + c)

self.assertEqual(re.sub(r'^\s*', 'X', 'test'), 'Xtest')
Expand Down Expand Up @@ -775,10 +778,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.ReCompileError, re.compile, '\\%c' % c)
for c in 'ceghijklmopqyzABCEFGHIJKLMNOPQRTVXYZ':
with self.subTest(c):
self.assertRaises(re.error, re.compile, '[\\%c]' % c)
self.assertRaises(re.ReCompileError, re.compile, '[\\%c]' % c)

def test_named_unicode_escapes(self):
# test individual Unicode named escapes
Expand Down Expand Up @@ -909,14 +912,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.ReCompileError, 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.ReCompileError, re.compile, r'(a)b(?<=(.)\2)(c)')
self.assertRaises(re.ReCompileError, re.compile, r'(a)b(?<=(?P<a>.)(?P=a))(c)')
self.assertRaises(re.ReCompileError, re.compile, r'(a)b(?<=(a)(?(2)b|x))(c)')
self.assertRaises(re.ReCompileError, re.compile, r'(a)b(?<=(.)(?<=\2))(c)')

def test_ignore_case(self):
self.assertEqual(re.match("abc", "ABC", re.I).group(0), "ABC")
Expand Down Expand Up @@ -1284,8 +1287,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.ReCompileError, re.compile, br"\u1234")
self.assertRaises(re.ReCompileError, 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"))
Expand All @@ -1307,8 +1310,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.ReCompileError, re.compile, br"[\u1234]")
self.assertRaises(re.ReCompileError, re.compile, br"[\U00012345]")
self.checkPatternError(br"[\567]",
r'octal escape value \567 outside of '
r'range 0-0o377', 1)
Expand Down Expand Up @@ -1640,11 +1643,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.ReCompileError, 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.ReCompileError, re.compile, r'(?au)\w')

def test_locale_flag(self):
enc = locale.getpreferredencoding()
Expand Down Expand Up @@ -1685,11 +1688,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.ReCompileError, 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.ReCompileError, re.compile, b'(?aL)')

def test_scoped_flags(self):
self.assertTrue(re.match(r'(?i:a)b', 'Ab'))
Expand Down Expand Up @@ -2031,7 +2034,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.ReCompileError) as cm:
re.compile('(\u20ac))')
err = cm.exception
self.assertIsInstance(err.pattern, str)
Expand All @@ -2043,14 +2046,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.ReCompileError) 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.ReCompileError) as cm:
re.compile("""
(
abc
Expand Down Expand Up @@ -2717,7 +2720,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.ReCompileError):
re.compile(pattern)
continue

Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
Renamed :exc:`re.error` to :exc:`ReCompileError` for clarity, and kept
:exc:`re.error` for backward compatibility. Patch by Matthias Bussonnier and
achhina marked this conversation as resolved.
Show resolved Hide resolved
Adam Chhina.
6 changes: 3 additions & 3 deletions Modules/_xxtestfuzz/fuzzer.c
Original file line number Diff line number Diff line change
Expand Up @@ -193,7 +193,7 @@ PyObject* sre_error_exception = NULL;
int SRE_FLAG_DEBUG = 0;
/* Called by LLVMFuzzerTestOneInput for initialization */
static int init_sre_compile(void) {
/* Import sre_compile.compile and sre.error */
/* Import sre_compile.compile and sre_constants.ReCompileError */
PyObject* sre_compile_module = PyImport_ImportModule("sre_compile");
if (sre_compile_module == NULL) {
return 0;
Expand All @@ -207,7 +207,7 @@ static int init_sre_compile(void) {
if (sre_constants == NULL) {
return 0;
}
sre_error_exception = PyObject_GetAttrString(sre_constants, "error");
sre_error_exception = PyObject_GetAttrString(sre_constants, "ReCompileError");
if (sre_error_exception == NULL) {
return 0;
}
Expand Down Expand Up @@ -261,7 +261,7 @@ static int fuzz_sre_compile(const char* data, size_t size) {
) {
PyErr_Clear();
}
/* Ignore re.error */
/* Ignore re.ReCompileError */
if (compiled == NULL && PyErr_ExceptionMatches(sre_error_exception)) {
PyErr_Clear();
}
Expand Down