bpo-33041: Add tests for jumps in/out of 'async with' blocks. (#6110) · python/cpython@bc300ce (original) (raw)

`@@ -6,6 +6,8 @@

`

6

6

`import difflib

`

7

7

`import gc

`

8

8

`from functools import wraps

`

``

9

`+

import asyncio

`

``

10

+

9

11

``

10

12

`class tracecontext:

`

11

13

`"""Context manager that traces its enter and exit."""

`

`@@ -19,6 +21,20 @@ def enter(self):

`

19

21

`def exit(self, *exc_info):

`

20

22

`self.output.append(-self.value)

`

21

23

``

``

24

`+

class asynctracecontext:

`

``

25

`+

"""Asynchronous context manager that traces its aenter and aexit."""

`

``

26

`+

def init(self, output, value):

`

``

27

`+

self.output = output

`

``

28

`+

self.value = value

`

``

29

+

``

30

`+

async def aenter(self):

`

``

31

`+

self.output.append(self.value)

`

``

32

+

``

33

`+

async def aexit(self, *exc_info):

`

``

34

`+

self.output.append(-self.value)

`

``

35

+

``

36

+

``

37

+

22

38

`# A very basic example. If this fails, we're in deep trouble.

`

23

39

`def basic():

`

24

40

`return 1

`

`@@ -636,6 +652,19 @@ def run_test(self, func, jumpFrom, jumpTo, expected, error=None,

`

636

652

`sys.settrace(None)

`

637

653

`self.compare_jump_output(expected, output)

`

638

654

``

``

655

`+

def run_async_test(self, func, jumpFrom, jumpTo, expected, error=None,

`

``

656

`+

event='line', decorated=False):

`

``

657

`+

tracer = JumpTracer(func, jumpFrom, jumpTo, event, decorated)

`

``

658

`+

sys.settrace(tracer.trace)

`

``

659

`+

output = []

`

``

660

`+

if error is None:

`

``

661

`+

asyncio.run(func(output))

`

``

662

`+

else:

`

``

663

`+

with self.assertRaisesRegex(*error):

`

``

664

`+

asyncio.run(func(output))

`

``

665

`+

sys.settrace(None)

`

``

666

`+

self.compare_jump_output(expected, output)

`

``

667

+

639

668

`def jump_test(jumpFrom, jumpTo, expected, error=None, event='line'):

`

640

669

`"""Decorator that creates a test that makes a jump

`

641

670

` from one place to another in the following code.

`

`@@ -648,6 +677,18 @@ def test(self):

`

648

677

`return test

`

649

678

`return decorator

`

650

679

``

``

680

`+

def async_jump_test(jumpFrom, jumpTo, expected, error=None, event='line'):

`

``

681

`+

"""Decorator that creates a test that makes a jump

`

``

682

`+

from one place to another in the following asynchronous code.

`

``

683

`+

"""

`

``

684

`+

def decorator(func):

`

``

685

`+

@wraps(func)

`

``

686

`+

def test(self):

`

``

687

`+

self.run_async_test(func, jumpFrom, jumpTo, expected,

`

``

688

`+

error=error, event=event, decorated=True)

`

``

689

`+

return test

`

``

690

`+

return decorator

`

``

691

+

651

692

`## The first set of 'jump' tests are for things that are allowed:

`

652

693

``

653

694

`@jump_test(1, 3, [3])

`

`@@ -774,12 +815,24 @@ def test_jump_forwards_out_of_with_block(output):

`

774

815

`output.append(2)

`

775

816

`output.append(3)

`

776

817

``

``

818

`+

@async_jump_test(2, 3, [1, 3])

`

``

819

`+

async def test_jump_forwards_out_of_async_with_block(output):

`

``

820

`+

async with asynctracecontext(output, 1):

`

``

821

`+

output.append(2)

`

``

822

`+

output.append(3)

`

``

823

+

777

824

`@jump_test(3, 1, [1, 2, 1, 2, 3, -2])

`

778

825

`def test_jump_backwards_out_of_with_block(output):

`

779

826

`output.append(1)

`

780

827

`with tracecontext(output, 2):

`

781

828

`output.append(3)

`

782

829

``

``

830

`+

@async_jump_test(3, 1, [1, 2, 1, 2, 3, -2])

`

``

831

`+

async def test_jump_backwards_out_of_async_with_block(output):

`

``

832

`+

output.append(1)

`

``

833

`+

async with asynctracecontext(output, 2):

`

``

834

`+

output.append(3)

`

``

835

+

783

836

`@jump_test(2, 5, [5])

`

784

837

`def test_jump_forwards_out_of_try_finally_block(output):

`

785

838

`try:

`

`@@ -843,6 +896,14 @@ def test_jump_across_with(output):

`

843

896

`with tracecontext(output, 4):

`

844

897

`output.append(5)

`

845

898

``

``

899

`+

@async_jump_test(2, 4, [1, 4, 5, -4])

`

``

900

`+

async def test_jump_across_async_with(output):

`

``

901

`+

output.append(1)

`

``

902

`+

async with asynctracecontext(output, 2):

`

``

903

`+

output.append(3)

`

``

904

`+

async with asynctracecontext(output, 4):

`

``

905

`+

output.append(5)

`

``

906

+

846

907

`@jump_test(4, 5, [1, 3, 5, 6])

`

847

908

`def test_jump_out_of_with_block_within_for_block(output):

`

848

909

`output.append(1)

`

`@@ -852,6 +913,15 @@ def test_jump_out_of_with_block_within_for_block(output):

`

852

913

`output.append(5)

`

853

914

`output.append(6)

`

854

915

``

``

916

`+

@async_jump_test(4, 5, [1, 3, 5, 6])

`

``

917

`+

async def test_jump_out_of_async_with_block_within_for_block(output):

`

``

918

`+

output.append(1)

`

``

919

`+

for i in [1]:

`

``

920

`+

async with asynctracecontext(output, 3):

`

``

921

`+

output.append(4)

`

``

922

`+

output.append(5)

`

``

923

`+

output.append(6)

`

``

924

+

855

925

`@jump_test(4, 5, [1, 2, 3, 5, -2, 6])

`

856

926

`def test_jump_out_of_with_block_within_with_block(output):

`

857

927

`output.append(1)

`

`@@ -861,6 +931,15 @@ def test_jump_out_of_with_block_within_with_block(output):

`

861

931

`output.append(5)

`

862

932

`output.append(6)

`

863

933

``

``

934

`+

@async_jump_test(4, 5, [1, 2, 3, 5, -2, 6])

`

``

935

`+

async def test_jump_out_of_async_with_block_within_with_block(output):

`

``

936

`+

output.append(1)

`

``

937

`+

with tracecontext(output, 2):

`

``

938

`+

async with asynctracecontext(output, 3):

`

``

939

`+

output.append(4)

`

``

940

`+

output.append(5)

`

``

941

`+

output.append(6)

`

``

942

+

864

943

`@jump_test(5, 6, [2, 4, 6, 7])

`

865

944

`def test_jump_out_of_with_block_within_finally_block(output):

`

866

945

`try:

`

`@@ -871,6 +950,16 @@ def test_jump_out_of_with_block_within_finally_block(output):

`

871

950

`output.append(6)

`

872

951

`output.append(7)

`

873

952

``

``

953

`+

@async_jump_test(5, 6, [2, 4, 6, 7])

`

``

954

`+

async def test_jump_out_of_async_with_block_within_finally_block(output):

`

``

955

`+

try:

`

``

956

`+

output.append(2)

`

``

957

`+

finally:

`

``

958

`+

async with asynctracecontext(output, 4):

`

``

959

`+

output.append(5)

`

``

960

`+

output.append(6)

`

``

961

`+

output.append(7)

`

``

962

+

874

963

`@jump_test(8, 11, [1, 3, 5, 11, 12])

`

875

964

`def test_jump_out_of_complex_nested_blocks(output):

`

876

965

`output.append(1)

`

`@@ -894,6 +983,14 @@ def test_jump_out_of_with_assignment(output):

`

894

983

`output.append(4)

`

895

984

`output.append(5)

`

896

985

``

``

986

`+

@async_jump_test(3, 5, [1, 2, 5])

`

``

987

`+

async def test_jump_out_of_async_with_assignment(output):

`

``

988

`+

output.append(1)

`

``

989

`+

async with asynctracecontext(output, 2) \

`

``

990

`+

as x:

`

``

991

`+

output.append(4)

`

``

992

`+

output.append(5)

`

``

993

+

897

994

`@jump_test(3, 6, [1, 6, 8, 9])

`

898

995

`def test_jump_over_return_in_try_finally_block(output):

`

899

996

`output.append(1)

`

`@@ -996,12 +1093,24 @@ def test_no_jump_forwards_into_with_block(output):

`

996

1093

`with tracecontext(output, 2):

`

997

1094

`output.append(3)

`

998

1095

``

``

1096

`+

@async_jump_test(1, 3, [], (ValueError, 'into'))

`

``

1097

`+

async def test_no_jump_forwards_into_async_with_block(output):

`

``

1098

`+

output.append(1)

`

``

1099

`+

async with asynctracecontext(output, 2):

`

``

1100

`+

output.append(3)

`

``

1101

+

999

1102

`@jump_test(3, 2, [1, 2, -1], (ValueError, 'into'))

`

1000

1103

`def test_no_jump_backwards_into_with_block(output):

`

1001

1104

`with tracecontext(output, 1):

`

1002

1105

`output.append(2)

`

1003

1106

`output.append(3)

`

1004

1107

``

``

1108

`+

@async_jump_test(3, 2, [1, 2, -1], (ValueError, 'into'))

`

``

1109

`+

async def test_no_jump_backwards_into_async_with_block(output):

`

``

1110

`+

async with asynctracecontext(output, 1):

`

``

1111

`+

output.append(2)

`

``

1112

`+

output.append(3)

`

``

1113

+

1005

1114

`@jump_test(1, 3, [], (ValueError, 'into'))

`

1006

1115

`def test_no_jump_forwards_into_try_finally_block(output):

`

1007

1116

`output.append(1)

`

`@@ -1082,6 +1191,14 @@ def test_no_jump_between_with_blocks(output):

`

1082

1191

`with tracecontext(output, 4):

`

1083

1192

`output.append(5)

`

1084

1193

``

``

1194

`+

@async_jump_test(3, 5, [1, 2, -2], (ValueError, 'into'))

`

``

1195

`+

async def test_no_jump_between_async_with_blocks(output):

`

``

1196

`+

output.append(1)

`

``

1197

`+

async with asynctracecontext(output, 2):

`

``

1198

`+

output.append(3)

`

``

1199

`+

async with asynctracecontext(output, 4):

`

``

1200

`+

output.append(5)

`

``

1201

+

1085

1202

`@jump_test(5, 7, [2, 4], (ValueError, 'finally'))

`

1086

1203

`def test_no_jump_over_return_out_of_finally_block(output):

`

1087

1204

`try:

`