Thanks to visit codestin.com
Credit goes to github.com

Skip to content

bpo-38981: Rename re.error to re.ReCompileError for better readability. #17501

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

Closed
wants to merge 5 commits into from
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
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
14 changes: 9 additions & 5 deletions Doc/library/re.rst
Original file line number Diff line number Diff line change
Expand Up @@ -965,13 +965,13 @@ form.
Clear the regular expression cache.


.. exception:: error(msg, pattern=None, pos=None)
.. exception:: ReCompileError(msg, pattern=None, pos=None)
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We need an explicit index reference for error.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

how would I add and explicit index reference ? .. error: on top ?


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
``ReCompileError`` instance has the following additional attributes:

.. attribute:: msg

Expand All @@ -996,6 +996,10 @@ form.
.. versionchanged:: 3.5
Added additional attributes.

.. versionchanged:: 3.9
``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 what:
except re.ReCompileError as what:
args = what.args
msg = args[0]
col = args[1] if len(args) >= 2 else -1
Expand Down
2 changes: 1 addition & 1 deletion Lib/pstats.py
Original file line number Diff line number Diff line change
Expand Up @@ -312,7 +312,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.py
Original file line number Diff line number Diff line change
Expand Up @@ -115,7 +115,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 @@ -135,7 +136,7 @@
"findall", "finditer", "compile", "purge", "template", "escape",
"error", "Pattern", "Match", "A", "I", "L", "M", "S", "X", "U",
"ASCII", "IGNORECASE", "LOCALE", "MULTILINE", "DOTALL", "VERBOSE",
"UNICODE",
"UNICODE", "ReCompileError"
]

__version__ = "2.2.1"
Expand Down Expand Up @@ -178,7 +179,7 @@ def __repr__(self):
globals().update(RegexFlag.__members__)

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

# --------------------------------------------------------------------
# public interface
Expand Down
8 changes: 4 additions & 4 deletions Lib/sre_compile.py
Original file line number Diff line number Diff line change
Expand Up @@ -136,7 +136,7 @@ def _compile(code, pattern, flags):
emit(ANY)
elif op in REPEATING_CODES:
if flags & SRE_FLAG_TEMPLATE:
raise error("internal: unsupported template operator %r" % (op,))
raise ReCompileError(f"internal: unsupported template operator {op!r}")
if _simple(av[2]):
if op is MAX_REPEAT:
emit(REPEAT_ONE)
Expand Down Expand Up @@ -179,7 +179,7 @@ def _compile(code, pattern, flags):
else:
lo, hi = av[1].getwidth()
if lo != hi:
raise error("look-behind requires fixed-width pattern")
raise ReCompileError("look-behind requires fixed-width pattern")
emit(lo) # look behind
_compile(code, av[1], flags)
emit(SUCCESS)
Expand Down Expand Up @@ -244,7 +244,7 @@ def _compile(code, pattern, flags):
else:
code[skipyes] = _len(code) - skipyes + 1
else:
raise error("internal: unsupported operand type %r" % (op,))
raise ReCompileError(f"internal: unsupported operand type {op!r}")

def _compile_charset(charset, flags, code):
# compile charset subprogram
Expand All @@ -270,7 +270,7 @@ def _compile_charset(charset, flags, code):
else:
emit(av)
else:
raise error("internal: unsupported set operator %r" % (op,))
raise ReCompileError(f"internal: unsupported set operator {op!r}")
emit(FAILURE)

def _optimize_charset(charset, iscased=None, fixup=None, fixes=None):
Expand Down
6 changes: 4 additions & 2 deletions Lib/sre_constants.py
Original file line number Diff line number Diff line change
Expand Up @@ -17,10 +17,10 @@

from _sre import MAXREPEAT, MAXGROUPS

# SRE standard exception (access as sre.error)
# SRE standard exception (access as sre.ReCompileError)
# should this really be here?

class error(Exception):
class ReCompileError(Exception):
"""Exception raised for invalid regular expressions.

Attributes:
Expand Down Expand Up @@ -52,6 +52,8 @@ def __init__(self, msg, pattern=None, pos=None):
self.lineno = self.colno = None
super().__init__(msg)

# backward compatibility after renaming in 3.9
error = ReCompileError

class _NamedIntConstant(int):
def __new__(cls, value, name):
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 @@ -36,7 +36,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 @@ -45,14 +45,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 @@ -123,7 +126,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 @@ -689,10 +692,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 @@ -819,14 +822,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 @@ -1151,8 +1154,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 @@ -1174,8 +1177,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 @@ -1545,11 +1548,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 @@ -1590,11 +1593,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 @@ -1960,7 +1963,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 @@ -1972,14 +1975,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 @@ -2229,7 +2232,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 @@
The ``re.error`` exception has been renamed to :exc:`ReCompileError` for
clarity and conformance with pep-8. A ``re.error`` alias has been kept for
backward compatibility.
6 changes: 3 additions & 3 deletions Modules/_xxtestfuzz/fuzzer.c
Original file line number Diff line number Diff line change
Expand Up @@ -130,7 +130,7 @@ PyObject* sre_error_exception = NULL;
int SRE_FLAG_DEBUG = 0;
/* Called by LLVMFuzzerTestOneInput for initialization */
static int init_sre_compile() {
/* 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 @@ -144,7 +144,7 @@ static int init_sre_compile() {
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 @@ -197,7 +197,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
4 changes: 2 additions & 2 deletions Tools/demo/redemo.py
Original file line number Diff line number Diff line change
Expand Up @@ -104,10 +104,10 @@ def recompile(self, event=None):
self.getflags())
bg = self.promptdisplay['background']
self.statusdisplay.config(text="", background=bg)
except re.error as msg:
except re.ReCompileError as msg:
self.compiled = None
self.statusdisplay.config(
text="re.error: %s" % str(msg),
text="re.ReCompileError: %s" % str(msg),
background="red")
self.reevaluate()

Expand Down
2 changes: 1 addition & 1 deletion Tools/scripts/rgrep.py
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,7 @@ def main():
pattern, filename = args
try:
prog = re.compile(pattern, reflags)
except re.error as msg:
except re.ReCompileError as msg:
usage("error in regular expression: %s" % msg)
try:
f = open(filename)
Expand Down