diff --git a/Lib/sre_parse.py b/Lib/sre_parse.py index 3209ce0722c..b56d437c347 100644 --- a/Lib/sre_parse.py +++ b/Lib/sre_parse.py @@ -94,33 +94,45 @@ class SubPattern: self.data = data self.width = None def dump(self, level=0): - nl = 1 + nl = True seqtypes = (tuple, list) for op, av in self.data: - print(level*" " + op, end=' '); nl = 0 - if op == "in": + print(level*" " + op, end='') + if op == IN: # member sublanguage - print(); nl = 1 + print() for op, a in av: print((level+1)*" " + op, a) - elif op == "branch": - print(); nl = 1 - i = 0 - for a in av[1]: - if i > 0: + elif op == BRANCH: + print() + for i, a in enumerate(av[1]): + if i: print(level*" " + "or") - a.dump(level+1); nl = 1 - i = i + 1 + a.dump(level+1) + elif op == GROUPREF_EXISTS: + condgroup, item_yes, item_no = av + print('', condgroup) + item_yes.dump(level+1) + if item_no: + print(level*" " + "else") + item_no.dump(level+1) elif isinstance(av, seqtypes): + nl = False for a in av: if isinstance(a, SubPattern): - if not nl: print() - a.dump(level+1); nl = 1 + if not nl: + print() + a.dump(level+1) + nl = True else: - print(a, end=' ') ; nl = 0 + if not nl: + print(' ', end='') + print(a, end='') + nl = False + if not nl: + print() else: - print(av, end=' ') ; nl = 0 - if not nl: print() + print('', av) def __repr__(self): return repr(self.data) def __len__(self): diff --git a/Lib/test/test_re.py b/Lib/test/test_re.py index 011fba9b91c..e937c8524c4 100644 --- a/Lib/test/test_re.py +++ b/Lib/test/test_re.py @@ -1203,16 +1203,33 @@ class ReTests(unittest.TestCase): self.assertEqual(m.group(2), "y") def test_debug_flag(self): + pat = r'(\.)(?:[ch]|py)(?(1)$|: )' with captured_stdout() as out: - re.compile('foo', re.DEBUG) - self.assertEqual(out.getvalue().splitlines(), - ['literal 102 ', 'literal 111 ', 'literal 111 ']) + re.compile(pat, re.DEBUG) + dump = '''\ +subpattern 1 + literal 46 +subpattern None + branch + in + literal 99 + literal 104 + or + literal 112 + literal 121 +subpattern None + groupref_exists 1 + at at_end + else + literal 58 + literal 32 +''' + self.assertEqual(out.getvalue(), dump) # Debug output is output again even a second time (bypassing # the cache -- issue #20426). with captured_stdout() as out: - re.compile('foo', re.DEBUG) - self.assertEqual(out.getvalue().splitlines(), - ['literal 102 ', 'literal 111 ', 'literal 111 ']) + re.compile(pat, re.DEBUG) + self.assertEqual(out.getvalue(), dump) def test_keyword_parameters(self): # Issue #20283: Accepting the string keyword parameter. diff --git a/Misc/NEWS b/Misc/NEWS index 99e62818a87..cca745ed8f2 100644 --- a/Misc/NEWS +++ b/Misc/NEWS @@ -137,6 +137,9 @@ Core and Builtins Library ------- +- Issue #22423: Fixed debugging output of the GROUPREF_EXISTS opcode in the re + module. + - Issue #22423: Unhandled exception in thread no longer causes unhandled AttributeError when sys.stderr is None.