Skip to content

Commit 193760f

Browse files
[3.6] bpo-33041: Add tests for jumps in/out of 'async with' blocks. (GH-6110). (GH-6141)
(cherry picked from commit bc300ce)
1 parent 5bd0fe6 commit 193760f

File tree

1 file changed

+133
-1
lines changed

1 file changed

+133
-1
lines changed

‎Lib/test/test_sys_settrace.py‎

Lines changed: 133 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -7,8 +7,9 @@
77
import gc
88
from functools import wraps
99

10+
1011
class tracecontext:
11-
"""Contex manager that traces its enter and exit."""
12+
"""Context manager that traces its enter and exit."""
1213
def __init__(self, output, value):
1314
self.output = output
1415
self.value = value
@@ -19,6 +20,36 @@ def __enter__(self):
1920
def __exit__(self, *exc_info):
2021
self.output.append(-self.value)
2122

23+
class asynctracecontext:
24+
"""Asynchronous context manager that traces its aenter and aexit."""
25+
def __init__(self, output, value):
26+
self.output = output
27+
self.value = value
28+
29+
async def __aenter__(self):
30+
self.output.append(self.value)
31+
32+
async def __aexit__(self, *exc_info):
33+
self.output.append(-self.value)
34+
35+
def asyncio_run(main):
36+
import asyncio
37+
import asyncio.events
38+
import asyncio.coroutines
39+
assert asyncio.events._get_running_loop() is None
40+
assert asyncio.coroutines.iscoroutine(main)
41+
loop = asyncio.events.new_event_loop()
42+
try:
43+
asyncio.events.set_event_loop(loop)
44+
return loop.run_until_complete(main)
45+
finally:
46+
try:
47+
loop.run_until_complete(loop.shutdown_asyncgens())
48+
finally:
49+
asyncio.events.set_event_loop(None)
50+
loop.close()
51+
52+
2253
# A very basic example. If this fails, we're in deep trouble.
2354
def basic():
2455
return 1
@@ -591,6 +622,19 @@ def run_test(self, func, jumpFrom, jumpTo, expected, error=None,
591622
sys.settrace(None)
592623
self.compare_jump_output(expected, output)
593624

625+
def run_async_test(self, func, jumpFrom, jumpTo, expected, error=None,
626+
event='line', decorated=False):
627+
tracer = JumpTracer(func, jumpFrom, jumpTo, event, decorated)
628+
sys.settrace(tracer.trace)
629+
output = []
630+
if error is None:
631+
asyncio_run(func(output))
632+
else:
633+
with self.assertRaisesRegex(*error):
634+
asyncio_run(func(output))
635+
sys.settrace(None)
636+
self.compare_jump_output(expected, output)
637+
594638
def jump_test(jumpFrom, jumpTo, expected, error=None, event='line'):
595639
"""Decorator that creates a test that makes a jump
596640
from one place to another in the following code.
@@ -603,6 +647,18 @@ def test(self):
603647
return test
604648
return decorator
605649

650+
def async_jump_test(jumpFrom, jumpTo, expected, error=None, event='line'):
651+
"""Decorator that creates a test that makes a jump
652+
from one place to another in the following asynchronous code.
653+
"""
654+
def decorator(func):
655+
@wraps(func)
656+
def test(self):
657+
self.run_async_test(func, jumpFrom, jumpTo, expected,
658+
error=error, event=event, decorated=True)
659+
return test
660+
return decorator
661+
606662
## The first set of 'jump' tests are for things that are allowed:
607663

608664
@jump_test(1, 3, [3])
@@ -698,12 +754,24 @@ def test_jump_forwards_out_of_with_block(output):
698754
output.append(2)
699755
output.append(3)
700756

757+
@async_jump_test(2, 3, [1, 3])
758+
async def test_jump_forwards_out_of_async_with_block(output):
759+
async with asynctracecontext(output, 1):
760+
output.append(2)
761+
output.append(3)
762+
701763
@jump_test(3, 1, [1, 2, 1, 2, 3, -2])
702764
def test_jump_backwards_out_of_with_block(output):
703765
output.append(1)
704766
with tracecontext(output, 2):
705767
output.append(3)
706768

769+
@async_jump_test(3, 1, [1, 2, 1, 2, 3, -2])
770+
async def test_jump_backwards_out_of_async_with_block(output):
771+
output.append(1)
772+
async with asynctracecontext(output, 2):
773+
output.append(3)
774+
707775
@jump_test(2, 5, [5])
708776
def test_jump_forwards_out_of_try_finally_block(output):
709777
try:
@@ -767,6 +835,14 @@ def test_jump_across_with(output):
767835
with tracecontext(output, 4):
768836
output.append(5)
769837

838+
@async_jump_test(2, 4, [1, 4, 5, -4])
839+
async def test_jump_across_async_with(output):
840+
output.append(1)
841+
async with asynctracecontext(output, 2):
842+
output.append(3)
843+
async with asynctracecontext(output, 4):
844+
output.append(5)
845+
770846
@jump_test(4, 5, [1, 3, 5, 6])
771847
def test_jump_out_of_with_block_within_for_block(output):
772848
output.append(1)
@@ -776,6 +852,15 @@ def test_jump_out_of_with_block_within_for_block(output):
776852
output.append(5)
777853
output.append(6)
778854

855+
@async_jump_test(4, 5, [1, 3, 5, 6])
856+
async def test_jump_out_of_async_with_block_within_for_block(output):
857+
output.append(1)
858+
for i in [1]:
859+
async with asynctracecontext(output, 3):
860+
output.append(4)
861+
output.append(5)
862+
output.append(6)
863+
779864
@jump_test(4, 5, [1, 2, 3, 5, -2, 6])
780865
def test_jump_out_of_with_block_within_with_block(output):
781866
output.append(1)
@@ -785,6 +870,15 @@ def test_jump_out_of_with_block_within_with_block(output):
785870
output.append(5)
786871
output.append(6)
787872

873+
@async_jump_test(4, 5, [1, 2, 3, 5, -2, 6])
874+
async def test_jump_out_of_async_with_block_within_with_block(output):
875+
output.append(1)
876+
with tracecontext(output, 2):
877+
async with asynctracecontext(output, 3):
878+
output.append(4)
879+
output.append(5)
880+
output.append(6)
881+
788882
@jump_test(5, 6, [2, 4, 6, 7])
789883
def test_jump_out_of_with_block_within_finally_block(output):
790884
try:
@@ -795,6 +889,16 @@ def test_jump_out_of_with_block_within_finally_block(output):
795889
output.append(6)
796890
output.append(7)
797891

892+
@async_jump_test(5, 6, [2, 4, 6, 7])
893+
async def test_jump_out_of_async_with_block_within_finally_block(output):
894+
try:
895+
output.append(2)
896+
finally:
897+
async with asynctracecontext(output, 4):
898+
output.append(5)
899+
output.append(6)
900+
output.append(7)
901+
798902
@jump_test(8, 11, [1, 3, 5, 11, 12])
799903
def test_jump_out_of_complex_nested_blocks(output):
800904
output.append(1)
@@ -818,6 +922,14 @@ def test_jump_out_of_with_assignment(output):
818922
output.append(4)
819923
output.append(5)
820924

925+
@async_jump_test(3, 5, [1, 2, 5])
926+
async def test_jump_out_of_async_with_assignment(output):
927+
output.append(1)
928+
async with asynctracecontext(output, 2) \
929+
as x:
930+
output.append(4)
931+
output.append(5)
932+
821933
@jump_test(3, 6, [1, 6, 8, 9])
822934
def test_jump_over_return_in_try_finally_block(output):
823935
output.append(1)
@@ -936,12 +1048,24 @@ def test_no_jump_forwards_into_with_block(output):
9361048
with tracecontext(output, 2):
9371049
output.append(3)
9381050

1051+
@async_jump_test(1, 3, [], (ValueError, 'into'))
1052+
async def test_no_jump_forwards_into_async_with_block(output):
1053+
output.append(1)
1054+
async with asynctracecontext(output, 2):
1055+
output.append(3)
1056+
9391057
@jump_test(3, 2, [1, 2, -1], (ValueError, 'into'))
9401058
def test_no_jump_backwards_into_with_block(output):
9411059
with tracecontext(output, 1):
9421060
output.append(2)
9431061
output.append(3)
9441062

1063+
@async_jump_test(3, 2, [1, 2, -1], (ValueError, 'into'))
1064+
async def test_no_jump_backwards_into_async_with_block(output):
1065+
async with asynctracecontext(output, 1):
1066+
output.append(2)
1067+
output.append(3)
1068+
9451069
@jump_test(1, 3, [], (ValueError, 'into'))
9461070
def test_no_jump_forwards_into_try_finally_block(output):
9471071
output.append(1)
@@ -1022,6 +1146,14 @@ def test_no_jump_between_with_blocks(output):
10221146
with tracecontext(output, 4):
10231147
output.append(5)
10241148

1149+
@async_jump_test(3, 5, [1, 2, -2], (ValueError, 'into'))
1150+
async def test_no_jump_between_async_with_blocks(output):
1151+
output.append(1)
1152+
async with asynctracecontext(output, 2):
1153+
output.append(3)
1154+
async with asynctracecontext(output, 4):
1155+
output.append(5)
1156+
10251157
@jump_test(7, 4, [1, 6], (ValueError, 'into'))
10261158
def test_no_jump_into_for_block_before_else(output):
10271159
output.append(1)

0 commit comments

Comments
 (0)