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.
This commit is contained in:
Ijtaba Hussain 2023-09-07 12:41:38 +05:00 committed by GitHub
parent babdced23f
commit 3e53ac9903
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
2 changed files with 43 additions and 32 deletions

View File

@ -8,6 +8,7 @@ import gc
from functools import wraps
import asyncio
from test.support import import_helper
import contextlib
support.requires_working_socket(module=True)
@ -1922,6 +1923,8 @@ def no_jump_without_trace_function():
class JumpTestCase(unittest.TestCase):
unbound_locals = r"assigning None to [0-9]+ unbound local"
def setUp(self):
self.addCleanup(sys.settrace, sys.gettrace())
sys.settrace(None)
@ -1933,33 +1936,39 @@ class JumpTestCase(unittest.TestCase):
"Received: " + repr(received))
def run_test(self, func, jumpFrom, jumpTo, expected, error=None,
event='line', decorated=False):
event='line', decorated=False, warning=None):
tracer = JumpTracer(func, jumpFrom, jumpTo, event, decorated)
sys.settrace(tracer.trace)
output = []
if error is None:
with contextlib.ExitStack() as stack:
if error is not None:
stack.enter_context(self.assertRaisesRegex(*error))
if warning is not None:
stack.enter_context(self.assertWarnsRegex(*warning))
func(output)
else:
with self.assertRaisesRegex(*error):
func(output)
sys.settrace(None)
self.compare_jump_output(expected, output)
def run_async_test(self, func, jumpFrom, jumpTo, expected, error=None,
event='line', decorated=False):
event='line', decorated=False, warning=None):
tracer = JumpTracer(func, jumpFrom, jumpTo, event, decorated)
sys.settrace(tracer.trace)
output = []
if error is None:
with contextlib.ExitStack() as stack:
if error is not None:
stack.enter_context(self.assertRaisesRegex(*error))
if warning is not None:
stack.enter_context(self.assertWarnsRegex(*warning))
asyncio.run(func(output))
else:
with self.assertRaisesRegex(*error):
asyncio.run(func(output))
sys.settrace(None)
asyncio.set_event_loop_policy(None)
self.compare_jump_output(expected, output)
def jump_test(jumpFrom, jumpTo, expected, error=None, event='line'):
def jump_test(jumpFrom, jumpTo, expected, error=None, event='line', warning=None):
"""Decorator that creates a test that makes a jump
from one place to another in the following code.
"""
@ -1967,11 +1976,11 @@ class JumpTestCase(unittest.TestCase):
@wraps(func)
def test(self):
self.run_test(func, jumpFrom, jumpTo, expected,
error=error, event=event, decorated=True)
error=error, event=event, decorated=True, warning=warning)
return test
return decorator
def async_jump_test(jumpFrom, jumpTo, expected, error=None, event='line'):
def async_jump_test(jumpFrom, jumpTo, expected, error=None, event='line', warning=None):
"""Decorator that creates a test that makes a jump
from one place to another in the following asynchronous code.
"""
@ -1979,7 +1988,7 @@ class JumpTestCase(unittest.TestCase):
@wraps(func)
def test(self):
self.run_async_test(func, jumpFrom, jumpTo, expected,
error=error, event=event, decorated=True)
error=error, event=event, decorated=True, warning=warning)
return test
return decorator
@ -1996,7 +2005,7 @@ class JumpTestCase(unittest.TestCase):
output.append(1)
output.append(2)
@jump_test(3, 5, [2, 5])
@jump_test(3, 5, [2, 5], warning=(RuntimeWarning, unbound_locals))
def test_jump_out_of_block_forwards(output):
for i in 1, 2:
output.append(2)
@ -2210,7 +2219,7 @@ class JumpTestCase(unittest.TestCase):
output.append(6)
output.append(7)
@jump_test(6, 1, [1, 5, 1, 5])
@jump_test(6, 1, [1, 5, 1, 5], warning=(RuntimeWarning, unbound_locals))
def test_jump_over_try_except(output):
output.append(1)
try:
@ -2306,7 +2315,7 @@ class JumpTestCase(unittest.TestCase):
output.append(11)
output.append(12)
@jump_test(3, 5, [1, 2, 5])
@jump_test(3, 5, [1, 2, 5], warning=(RuntimeWarning, unbound_locals))
def test_jump_out_of_with_assignment(output):
output.append(1)
with tracecontext(output, 2) \
@ -2314,7 +2323,7 @@ class JumpTestCase(unittest.TestCase):
output.append(4)
output.append(5)
@async_jump_test(3, 5, [1, 2, 5])
@async_jump_test(3, 5, [1, 2, 5], warning=(RuntimeWarning, unbound_locals))
async def test_jump_out_of_async_with_assignment(output):
output.append(1)
async with asynctracecontext(output, 2) \
@ -2350,7 +2359,7 @@ class JumpTestCase(unittest.TestCase):
break
output.append(13)
@jump_test(1, 7, [7, 8])
@jump_test(1, 7, [7, 8], warning=(RuntimeWarning, unbound_locals))
def test_jump_over_for_block_before_else(output):
output.append(1)
if not output: # always false
@ -2361,7 +2370,7 @@ class JumpTestCase(unittest.TestCase):
output.append(7)
output.append(8)
@async_jump_test(1, 7, [7, 8])
@async_jump_test(1, 7, [7, 8], warning=(RuntimeWarning, unbound_locals))
async def test_jump_over_async_for_block_before_else(output):
output.append(1)
if not output: # always false
@ -2436,6 +2445,7 @@ class JumpTestCase(unittest.TestCase):
output.append(2)
output.append(3)
@async_jump_test(3, 2, [2, 2], (ValueError, "can't jump into the body of a for loop"))
async def test_no_jump_backwards_into_async_for_block(output):
async for i in asynciter([1, 2]):
@ -2501,7 +2511,7 @@ class JumpTestCase(unittest.TestCase):
output.append(6)
# 'except' with a variable creates an implicit finally block
@jump_test(5, 7, [4, 7, 8])
@jump_test(5, 7, [4, 7, 8], warning=(RuntimeWarning, unbound_locals))
def test_jump_between_except_blocks_2(output):
try:
1/0
@ -2664,7 +2674,7 @@ class JumpTestCase(unittest.TestCase):
output.append(x) # line 1007
return""" % ('\n' * 1000,), d)
f = d['f']
self.run_test(f, 2, 1007, [0])
self.run_test(f, 2, 1007, [0], warning=(RuntimeWarning, self.unbound_locals))
def test_jump_to_firstlineno(self):
# This tests that PDB can jump back to the first line in a
@ -2714,7 +2724,7 @@ output.append(4)
next(gen())
output.append(5)
@jump_test(2, 3, [1, 3])
@jump_test(2, 3, [1, 3], warning=(RuntimeWarning, unbound_locals))
def test_jump_forward_over_listcomp(output):
output.append(1)
x = [i for i in range(10)]
@ -2722,13 +2732,13 @@ output.append(4)
# checking for segfaults.
# See https://github.com/python/cpython/issues/92311
@jump_test(3, 1, [])
@jump_test(3, 1, [], warning=(RuntimeWarning, unbound_locals))
def test_jump_backward_over_listcomp(output):
a = 1
x = [i for i in range(10)]
c = 3
@jump_test(8, 2, [2, 7, 2])
@jump_test(8, 2, [2, 7, 2], warning=(RuntimeWarning, unbound_locals))
def test_jump_backward_over_listcomp_v2(output):
flag = False
output.append(2)
@ -2739,19 +2749,19 @@ output.append(4)
output.append(7)
output.append(8)
@async_jump_test(2, 3, [1, 3])
@async_jump_test(2, 3, [1, 3], warning=(RuntimeWarning, unbound_locals))
async def test_jump_forward_over_async_listcomp(output):
output.append(1)
x = [i async for i in asynciter(range(10))]
output.append(3)
@async_jump_test(3, 1, [])
@async_jump_test(3, 1, [], warning=(RuntimeWarning, unbound_locals))
async def test_jump_backward_over_async_listcomp(output):
a = 1
x = [i async for i in asynciter(range(10))]
c = 3
@async_jump_test(8, 2, [2, 7, 2])
@async_jump_test(8, 2, [2, 7, 2], warning=(RuntimeWarning, unbound_locals))
async def test_jump_backward_over_async_listcomp_v2(output):
flag = False
output.append(2)
@ -2820,13 +2830,13 @@ output.append(4)
)
output.append(15)
@jump_test(2, 3, [1, 3])
@jump_test(2, 3, [1, 3], warning=(RuntimeWarning, unbound_locals))
def test_jump_extended_args_unpack_ex_simple(output):
output.append(1)
_, *_, _ = output.append(2) or "Spam"
output.append(3)
@jump_test(3, 4, [1, 4, 4, 5])
@jump_test(3, 4, [1, 4, 4, 5], warning=(RuntimeWarning, unbound_locals))
def test_jump_extended_args_unpack_ex_tricky(output):
output.append(1)
(
@ -2848,9 +2858,9 @@ output.append(4)
namespace = {}
exec("\n".join(source), namespace)
f = namespace["f"]
self.run_test(f, 2, 100_000, [1, 100_000])
self.run_test(f, 2, 100_000, [1, 100_000], warning=(RuntimeWarning, self.unbound_locals))
@jump_test(2, 3, [1, 3])
@jump_test(2, 3, [1, 3], warning=(RuntimeWarning, unbound_locals))
def test_jump_or_pop(output):
output.append(1)
_ = output.append(2) and "Spam"

View File

@ -0,0 +1 @@
Suppress and assert expected RuntimeWarnings in test_sys_settrace.py