|  | 
| 22 | 22 | 
 | 
| 23 | 23 | TIMEOUT = 0.5 | 
| 24 | 24 | 
 | 
|  | 25 | +STACK_HEADER_STR = r'Stack (most recent call first):' | 
|  | 26 | + | 
|  | 27 | +# Regular expressions | 
|  | 28 | +STACK_HEADER = re.escape(STACK_HEADER_STR) | 
|  | 29 | +THREAD_NAME = r'( \[.*\])?' | 
|  | 30 | +THREAD_ID = fr'Thread 0x[0-9a-f]+{THREAD_NAME}' | 
|  | 31 | +THREAD_HEADER = fr'{THREAD_ID} \(most recent call first\):' | 
|  | 32 | +CURRENT_THREAD_ID = fr'Current thread 0x[0-9a-f]+{THREAD_NAME}' | 
|  | 33 | +CURRENT_THREAD_HEADER = fr'{CURRENT_THREAD_ID} \(most recent call first\):' | 
|  | 34 | + | 
| 25 | 35 | 
 | 
| 26 | 36 | def expected_traceback(lineno1, lineno2, header, min_count=1): | 
| 27 | 37 |     regex = header | 
| @@ -106,18 +116,18 @@ def check_error(self, code, lineno, fatal_error, *, | 
| 106 | 116 |         ) | 
| 107 | 117 |         if all_threads and not all_threads_disabled: | 
| 108 | 118 |             if know_current_thread: | 
| 109 |  | -                header = 'Current thread 0x[0-9a-f]+' | 
|  | 119 | +                header = CURRENT_THREAD_HEADER | 
| 110 | 120 |             else: | 
| 111 |  | -                header = 'Thread 0x[0-9a-f]+' | 
|  | 121 | +                header = THREAD_HEADER | 
| 112 | 122 |         else: | 
| 113 |  | -            header = 'Stack' | 
|  | 123 | +            header = STACK_HEADER | 
| 114 | 124 |         regex = [f'^{fatal_error}'] | 
| 115 | 125 |         if py_fatal_error: | 
| 116 | 126 |             regex.append("Python runtime state: initialized") | 
| 117 | 127 |         regex.append('') | 
| 118 | 128 |         if all_threads_disabled and not py_fatal_error: | 
| 119 | 129 |             regex.append("<Cannot show all threads while the GIL is disabled>") | 
| 120 |  | -        regex.append(fr'{header} \(most recent call first\):') | 
|  | 130 | +        regex.append(fr'{header}') | 
| 121 | 131 |         if support.Py_GIL_DISABLED and py_fatal_error and not know_current_thread: | 
| 122 | 132 |             regex.append("  <tstate is freed>") | 
| 123 | 133 |         else: | 
| @@ -498,7 +508,7 @@ def funcA(): | 
| 498 | 508 |         else: | 
| 499 | 509 |             lineno = 14 | 
| 500 | 510 |         expected = [ | 
| 501 |  | -            'Stack (most recent call first):', | 
|  | 511 | +            f'{STACK_HEADER_STR}', | 
| 502 | 512 |             '  File "<string>", line %s in funcB' % lineno, | 
| 503 | 513 |             '  File "<string>", line 17 in funcA', | 
| 504 | 514 |             '  File "<string>", line 19 in <module>' | 
| @@ -536,7 +546,7 @@ def {func_name}(): | 
| 536 | 546 |             func_name=func_name, | 
| 537 | 547 |         ) | 
| 538 | 548 |         expected = [ | 
| 539 |  | -            'Stack (most recent call first):', | 
|  | 549 | +            f'{STACK_HEADER_STR}', | 
| 540 | 550 |             '  File "<string>", line 4 in %s' % truncated, | 
| 541 | 551 |             '  File "<string>", line 6 in <module>' | 
| 542 | 552 |         ] | 
| @@ -590,18 +600,18 @@ def run(self): | 
| 590 | 600 |             lineno = 10 | 
| 591 | 601 |         # When the traceback is dumped, the waiter thread may be in the | 
| 592 | 602 |         # `self.running.set()` call or in `self.stop.wait()`. | 
| 593 |  | -        regex = r""" | 
| 594 |  | -            ^Thread 0x[0-9a-f]+ \(most recent call first\): | 
|  | 603 | +        regex = fr""" | 
|  | 604 | +            ^{THREAD_HEADER} | 
| 595 | 605 |             (?:  File ".*threading.py", line [0-9]+ in [_a-z]+ | 
| 596 | 606 |             ){{1,3}}  File "<string>", line (?:22|23) in run | 
| 597 | 607 |               File ".*threading.py", line [0-9]+ in _bootstrap_inner | 
| 598 | 608 |               File ".*threading.py", line [0-9]+ in _bootstrap | 
| 599 | 609 | 
 | 
| 600 |  | -            Current thread 0x[0-9a-f]+ \(most recent call first\): | 
|  | 610 | +            {CURRENT_THREAD_HEADER} | 
| 601 | 611 |               File "<string>", line {lineno} in dump | 
| 602 | 612 |               File "<string>", line 28 in <module>$ | 
| 603 | 613 |             """ | 
| 604 |  | -        regex = dedent(regex.format(lineno=lineno)).strip() | 
|  | 614 | +        regex = dedent(regex).strip() | 
| 605 | 615 |         self.assertRegex(output, regex) | 
| 606 | 616 |         self.assertEqual(exitcode, 0) | 
| 607 | 617 | 
 | 
| @@ -667,7 +677,8 @@ def func(timeout, repeat, cancel, file, loops): | 
| 667 | 677 |             count = loops | 
| 668 | 678 |             if repeat: | 
| 669 | 679 |                 count *= 2 | 
| 670 |  | -            header = r'Timeout \(%s\)!\nThread 0x[0-9a-f]+ \(most recent call first\):\n' % timeout_str | 
|  | 680 | +            header = (fr'Timeout \({timeout_str}\)!\n' | 
|  | 681 | +                      fr'{THREAD_HEADER}\n') | 
| 671 | 682 |             regex = expected_traceback(17, 26, header, min_count=count) | 
| 672 | 683 |             self.assertRegex(trace, regex) | 
| 673 | 684 |         else: | 
| @@ -768,9 +779,9 @@ def handler(signum, frame): | 
| 768 | 779 |         trace = '\n'.join(trace) | 
| 769 | 780 |         if not unregister: | 
| 770 | 781 |             if all_threads: | 
| 771 |  | -                regex = r'Current thread 0x[0-9a-f]+ \(most recent call first\):\n' | 
|  | 782 | +                regex = fr'{CURRENT_THREAD_HEADER}\n' | 
| 772 | 783 |             else: | 
| 773 |  | -                regex = r'Stack \(most recent call first\):\n' | 
|  | 784 | +                regex = fr'{STACK_HEADER}\n' | 
| 774 | 785 |             regex = expected_traceback(14, 32, regex) | 
| 775 | 786 |             self.assertRegex(trace, regex) | 
| 776 | 787 |         else: | 
|  | 
0 commit comments