Skip to content

Commit 29404b6

Browse files
[3.12] gh-103186: Suppress and assert expected RuntimeWarnings in test_sys_settrace (GH-103244) (#109066)
gh-103186: Suppress and assert expected RuntimeWarnings in test_sys_settrace (GH-103244) Caused as a result of frame manipulation where locals are never assigned / initialised. (cherry picked from commit 3e53ac9) Co-authored-by: Ijtaba Hussain <ijtabahussain@live.com>
1 parent 8c9f5f7 commit 29404b6

File tree

2 files changed

+43
-32
lines changed

2 files changed

+43
-32
lines changed

Lib/test/test_sys_settrace.py

Lines changed: 42 additions & 32 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@
88
from functools import wraps
99
import asyncio
1010
from test.support import import_helper
11+
import contextlib
1112

1213
support.requires_working_socket(module=True)
1314

@@ -1900,6 +1901,8 @@ def no_jump_without_trace_function():
19001901

19011902

19021903
class JumpTestCase(unittest.TestCase):
1904+
unbound_locals = r"assigning None to [0-9]+ unbound local"
1905+
19031906
def setUp(self):
19041907
self.addCleanup(sys.settrace, sys.gettrace())
19051908
sys.settrace(None)
@@ -1911,53 +1914,59 @@ def compare_jump_output(self, expected, received):
19111914
"Received: " + repr(received))
19121915

19131916
def run_test(self, func, jumpFrom, jumpTo, expected, error=None,
1914-
event='line', decorated=False):
1917+
event='line', decorated=False, warning=None):
19151918
tracer = JumpTracer(func, jumpFrom, jumpTo, event, decorated)
19161919
sys.settrace(tracer.trace)
19171920
output = []
1918-
if error is None:
1921+
1922+
with contextlib.ExitStack() as stack:
1923+
if error is not None:
1924+
stack.enter_context(self.assertRaisesRegex(*error))
1925+
if warning is not None:
1926+
stack.enter_context(self.assertWarnsRegex(*warning))
19191927
func(output)
1920-
else:
1921-
with self.assertRaisesRegex(*error):
1922-
func(output)
1928+
19231929
sys.settrace(None)
19241930
self.compare_jump_output(expected, output)
19251931

19261932
def run_async_test(self, func, jumpFrom, jumpTo, expected, error=None,
1927-
event='line', decorated=False):
1933+
event='line', decorated=False, warning=None):
19281934
tracer = JumpTracer(func, jumpFrom, jumpTo, event, decorated)
19291935
sys.settrace(tracer.trace)
19301936
output = []
1931-
if error is None:
1937+
1938+
with contextlib.ExitStack() as stack:
1939+
if error is not None:
1940+
stack.enter_context(self.assertRaisesRegex(*error))
1941+
if warning is not None:
1942+
stack.enter_context(self.assertWarnsRegex(*warning))
19321943
asyncio.run(func(output))
1933-
else:
1934-
with self.assertRaisesRegex(*error):
1935-
asyncio.run(func(output))
1944+
19361945
sys.settrace(None)
19371946
asyncio.set_event_loop_policy(None)
19381947
self.compare_jump_output(expected, output)
19391948

1940-
def jump_test(jumpFrom, jumpTo, expected, error=None, event='line'):
1949+
def jump_test(jumpFrom, jumpTo, expected, error=None, event='line', warning=None):
19411950
"""Decorator that creates a test that makes a jump
19421951
from one place to another in the following code.
19431952
"""
19441953
def decorator(func):
19451954
@wraps(func)
19461955
def test(self):
19471956
self.run_test(func, jumpFrom, jumpTo, expected,
1948-
error=error, event=event, decorated=True)
1957+
error=error, event=event, decorated=True, warning=warning)
19491958
return test
19501959
return decorator
19511960

1952-
def async_jump_test(jumpFrom, jumpTo, expected, error=None, event='line'):
1961+
def async_jump_test(jumpFrom, jumpTo, expected, error=None, event='line', warning=None):
19531962
"""Decorator that creates a test that makes a jump
19541963
from one place to another in the following asynchronous code.
19551964
"""
19561965
def decorator(func):
19571966
@wraps(func)
19581967
def test(self):
19591968
self.run_async_test(func, jumpFrom, jumpTo, expected,
1960-
error=error, event=event, decorated=True)
1969+
error=error, event=event, decorated=True, warning=warning)
19611970
return test
19621971
return decorator
19631972

@@ -1974,7 +1983,7 @@ def test_jump_simple_backwards(output):
19741983
output.append(1)
19751984
output.append(2)
19761985

1977-
@jump_test(3, 5, [2, 5])
1986+
@jump_test(3, 5, [2, 5], warning=(RuntimeWarning, unbound_locals))
19781987
def test_jump_out_of_block_forwards(output):
19791988
for i in 1, 2:
19801989
output.append(2)
@@ -2188,7 +2197,7 @@ def test_jump_within_except_block(output):
21882197
output.append(6)
21892198
output.append(7)
21902199

2191-
@jump_test(6, 1, [1, 5, 1, 5])
2200+
@jump_test(6, 1, [1, 5, 1, 5], warning=(RuntimeWarning, unbound_locals))
21922201
def test_jump_over_try_except(output):
21932202
output.append(1)
21942203
try:
@@ -2284,15 +2293,15 @@ def test_jump_out_of_complex_nested_blocks(output):
22842293
output.append(11)
22852294
output.append(12)
22862295

2287-
@jump_test(3, 5, [1, 2, 5])
2296+
@jump_test(3, 5, [1, 2, 5], warning=(RuntimeWarning, unbound_locals))
22882297
def test_jump_out_of_with_assignment(output):
22892298
output.append(1)
22902299
with tracecontext(output, 2) \
22912300
as x:
22922301
output.append(4)
22932302
output.append(5)
22942303

2295-
@async_jump_test(3, 5, [1, 2, 5])
2304+
@async_jump_test(3, 5, [1, 2, 5], warning=(RuntimeWarning, unbound_locals))
22962305
async def test_jump_out_of_async_with_assignment(output):
22972306
output.append(1)
22982307
async with asynctracecontext(output, 2) \
@@ -2328,7 +2337,7 @@ def test_jump_over_break_in_try_finally_block(output):
23282337
break
23292338
output.append(13)
23302339

2331-
@jump_test(1, 7, [7, 8])
2340+
@jump_test(1, 7, [7, 8], warning=(RuntimeWarning, unbound_locals))
23322341
def test_jump_over_for_block_before_else(output):
23332342
output.append(1)
23342343
if not output: # always false
@@ -2339,7 +2348,7 @@ def test_jump_over_for_block_before_else(output):
23392348
output.append(7)
23402349
output.append(8)
23412350

2342-
@async_jump_test(1, 7, [7, 8])
2351+
@async_jump_test(1, 7, [7, 8], warning=(RuntimeWarning, unbound_locals))
23432352
async def test_jump_over_async_for_block_before_else(output):
23442353
output.append(1)
23452354
if not output: # always false
@@ -2414,6 +2423,7 @@ def test_no_jump_backwards_into_for_block(output):
24142423
output.append(2)
24152424
output.append(3)
24162425

2426+
24172427
@async_jump_test(3, 2, [2, 2], (ValueError, "can't jump into the body of a for loop"))
24182428
async def test_no_jump_backwards_into_async_for_block(output):
24192429
async for i in asynciter([1, 2]):
@@ -2479,7 +2489,7 @@ def test_jump_backwards_into_try_except_block(output):
24792489
output.append(6)
24802490

24812491
# 'except' with a variable creates an implicit finally block
2482-
@jump_test(5, 7, [4, 7, 8])
2492+
@jump_test(5, 7, [4, 7, 8], warning=(RuntimeWarning, unbound_locals))
24832493
def test_jump_between_except_blocks_2(output):
24842494
try:
24852495
1/0
@@ -2642,7 +2652,7 @@ def test_large_function(self):
26422652
output.append(x) # line 1007
26432653
return""" % ('\n' * 1000,), d)
26442654
f = d['f']
2645-
self.run_test(f, 2, 1007, [0])
2655+
self.run_test(f, 2, 1007, [0], warning=(RuntimeWarning, self.unbound_locals))
26462656

26472657
def test_jump_to_firstlineno(self):
26482658
# This tests that PDB can jump back to the first line in a
@@ -2692,21 +2702,21 @@ def gen():
26922702
next(gen())
26932703
output.append(5)
26942704

2695-
@jump_test(2, 3, [1, 3])
2705+
@jump_test(2, 3, [1, 3], warning=(RuntimeWarning, unbound_locals))
26962706
def test_jump_forward_over_listcomp(output):
26972707
output.append(1)
26982708
x = [i for i in range(10)]
26992709
output.append(3)
27002710

27012711
# checking for segfaults.
27022712
# See https://github.com/python/cpython/issues/92311
2703-
@jump_test(3, 1, [])
2713+
@jump_test(3, 1, [], warning=(RuntimeWarning, unbound_locals))
27042714
def test_jump_backward_over_listcomp(output):
27052715
a = 1
27062716
x = [i for i in range(10)]
27072717
c = 3
27082718

2709-
@jump_test(8, 2, [2, 7, 2])
2719+
@jump_test(8, 2, [2, 7, 2], warning=(RuntimeWarning, unbound_locals))
27102720
def test_jump_backward_over_listcomp_v2(output):
27112721
flag = False
27122722
output.append(2)
@@ -2717,19 +2727,19 @@ def test_jump_backward_over_listcomp_v2(output):
27172727
output.append(7)
27182728
output.append(8)
27192729

2720-
@async_jump_test(2, 3, [1, 3])
2730+
@async_jump_test(2, 3, [1, 3], warning=(RuntimeWarning, unbound_locals))
27212731
async def test_jump_forward_over_async_listcomp(output):
27222732
output.append(1)
27232733
x = [i async for i in asynciter(range(10))]
27242734
output.append(3)
27252735

2726-
@async_jump_test(3, 1, [])
2736+
@async_jump_test(3, 1, [], warning=(RuntimeWarning, unbound_locals))
27272737
async def test_jump_backward_over_async_listcomp(output):
27282738
a = 1
27292739
x = [i async for i in asynciter(range(10))]
27302740
c = 3
27312741

2732-
@async_jump_test(8, 2, [2, 7, 2])
2742+
@async_jump_test(8, 2, [2, 7, 2], warning=(RuntimeWarning, unbound_locals))
27332743
async def test_jump_backward_over_async_listcomp_v2(output):
27342744
flag = False
27352745
output.append(2)
@@ -2798,13 +2808,13 @@ def test_jump_with_null_on_stack_load_attr(output):
27982808
)
27992809
output.append(15)
28002810

2801-
@jump_test(2, 3, [1, 3])
2811+
@jump_test(2, 3, [1, 3], warning=(RuntimeWarning, unbound_locals))
28022812
def test_jump_extended_args_unpack_ex_simple(output):
28032813
output.append(1)
28042814
_, *_, _ = output.append(2) or "Spam"
28052815
output.append(3)
28062816

2807-
@jump_test(3, 4, [1, 4, 4, 5])
2817+
@jump_test(3, 4, [1, 4, 4, 5], warning=(RuntimeWarning, unbound_locals))
28082818
def test_jump_extended_args_unpack_ex_tricky(output):
28092819
output.append(1)
28102820
(
@@ -2826,9 +2836,9 @@ def test_jump_extended_args_for_iter(self):
28262836
namespace = {}
28272837
exec("\n".join(source), namespace)
28282838
f = namespace["f"]
2829-
self.run_test(f, 2, 100_000, [1, 100_000])
2839+
self.run_test(f, 2, 100_000, [1, 100_000], warning=(RuntimeWarning, self.unbound_locals))
28302840

2831-
@jump_test(2, 3, [1, 3])
2841+
@jump_test(2, 3, [1, 3], warning=(RuntimeWarning, unbound_locals))
28322842
def test_jump_or_pop(output):
28332843
output.append(1)
28342844
_ = output.append(2) and "Spam"
Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
Suppress and assert expected RuntimeWarnings in test_sys_settrace.py

0 commit comments

Comments
 (0)