[Python-checkins] [3.7] bpo-33041: Add tests for jumps in/out of 'async with' blocks. (GH-6110). (GH-6140)

Serhiy Storchaka webhook-mailer at python.org
Sun Mar 18 06:31:42 EDT 2018


https://github.com/python/cpython/commit/773573e9ac654d4b5c6682e70360f75864acd80e
commit: 773573e9ac654d4b5c6682e70360f75864acd80e
branch: 3.7
author: Serhiy Storchaka <storchaka at gmail.com>
committer: GitHub <noreply at github.com>
date: 2018-03-18T12:31:37+02:00
summary:

[3.7] bpo-33041: Add tests for jumps in/out of 'async with' blocks. (GH-6110). (GH-6140)

(cherry picked from commit bc300ce205f99acb1ef92c37de06dc76147e073b)

Co-authored-by: Serhiy Storchaka <storchaka at gmail.com>

files:
M Lib/test/test_sys_settrace.py

diff --git a/Lib/test/test_sys_settrace.py b/Lib/test/test_sys_settrace.py
index 44ea7d575b45..bf8c722d0cf7 100644
--- a/Lib/test/test_sys_settrace.py
+++ b/Lib/test/test_sys_settrace.py
@@ -6,6 +6,8 @@
 import difflib
 import gc
 from functools import wraps
+import asyncio
+
 
 class tracecontext:
     """Context manager that traces its enter and exit."""
@@ -19,6 +21,20 @@ def __enter__(self):
     def __exit__(self, *exc_info):
         self.output.append(-self.value)
 
+class asynctracecontext:
+    """Asynchronous context manager that traces its aenter and aexit."""
+    def __init__(self, output, value):
+        self.output = output
+        self.value = value
+
+    async def __aenter__(self):
+        self.output.append(self.value)
+
+    async def __aexit__(self, *exc_info):
+        self.output.append(-self.value)
+
+
+
 # A very basic example.  If this fails, we're in deep trouble.
 def basic():
     return 1
@@ -637,6 +653,19 @@ def run_test(self, func, jumpFrom, jumpTo, expected, error=None,
         sys.settrace(None)
         self.compare_jump_output(expected, output)
 
+    def run_async_test(self, func, jumpFrom, jumpTo, expected, error=None,
+                 event='line', decorated=False):
+        tracer = JumpTracer(func, jumpFrom, jumpTo, event, decorated)
+        sys.settrace(tracer.trace)
+        output = []
+        if error is None:
+            asyncio.run(func(output))
+        else:
+            with self.assertRaisesRegex(*error):
+                asyncio.run(func(output))
+        sys.settrace(None)
+        self.compare_jump_output(expected, output)
+
     def jump_test(jumpFrom, jumpTo, expected, error=None, event='line'):
         """Decorator that creates a test that makes a jump
         from one place to another in the following code.
@@ -649,6 +678,18 @@ def test(self):
             return test
         return decorator
 
+    def async_jump_test(jumpFrom, jumpTo, expected, error=None, event='line'):
+        """Decorator that creates a test that makes a jump
+        from one place to another in the following asynchronous code.
+        """
+        def decorator(func):
+            @wraps(func)
+            def test(self):
+                self.run_async_test(func, jumpFrom, jumpTo, expected,
+                              error=error, event=event, decorated=True)
+            return test
+        return decorator
+
     ## The first set of 'jump' tests are for things that are allowed:
 
     @jump_test(1, 3, [3])
@@ -744,12 +785,24 @@ def test_jump_forwards_out_of_with_block(output):
             output.append(2)
         output.append(3)
 
+    @async_jump_test(2, 3, [1, 3])
+    async def test_jump_forwards_out_of_async_with_block(output):
+        async with asynctracecontext(output, 1):
+            output.append(2)
+        output.append(3)
+
     @jump_test(3, 1, [1, 2, 1, 2, 3, -2])
     def test_jump_backwards_out_of_with_block(output):
         output.append(1)
         with tracecontext(output, 2):
             output.append(3)
 
+    @async_jump_test(3, 1, [1, 2, 1, 2, 3, -2])
+    async def test_jump_backwards_out_of_async_with_block(output):
+        output.append(1)
+        async with asynctracecontext(output, 2):
+            output.append(3)
+
     @jump_test(2, 5, [5])
     def test_jump_forwards_out_of_try_finally_block(output):
         try:
@@ -813,6 +866,14 @@ def test_jump_across_with(output):
         with tracecontext(output, 4):
             output.append(5)
 
+    @async_jump_test(2, 4, [1, 4, 5, -4])
+    async def test_jump_across_async_with(output):
+        output.append(1)
+        async with asynctracecontext(output, 2):
+            output.append(3)
+        async with asynctracecontext(output, 4):
+            output.append(5)
+
     @jump_test(4, 5, [1, 3, 5, 6])
     def test_jump_out_of_with_block_within_for_block(output):
         output.append(1)
@@ -822,6 +883,15 @@ def test_jump_out_of_with_block_within_for_block(output):
             output.append(5)
         output.append(6)
 
+    @async_jump_test(4, 5, [1, 3, 5, 6])
+    async def test_jump_out_of_async_with_block_within_for_block(output):
+        output.append(1)
+        for i in [1]:
+            async with asynctracecontext(output, 3):
+                output.append(4)
+            output.append(5)
+        output.append(6)
+
     @jump_test(4, 5, [1, 2, 3, 5, -2, 6])
     def test_jump_out_of_with_block_within_with_block(output):
         output.append(1)
@@ -831,6 +901,15 @@ def test_jump_out_of_with_block_within_with_block(output):
             output.append(5)
         output.append(6)
 
+    @async_jump_test(4, 5, [1, 2, 3, 5, -2, 6])
+    async def test_jump_out_of_async_with_block_within_with_block(output):
+        output.append(1)
+        with tracecontext(output, 2):
+            async with asynctracecontext(output, 3):
+                output.append(4)
+            output.append(5)
+        output.append(6)
+
     @jump_test(5, 6, [2, 4, 6, 7])
     def test_jump_out_of_with_block_within_finally_block(output):
         try:
@@ -841,6 +920,16 @@ def test_jump_out_of_with_block_within_finally_block(output):
             output.append(6)
         output.append(7)
 
+    @async_jump_test(5, 6, [2, 4, 6, 7])
+    async def test_jump_out_of_async_with_block_within_finally_block(output):
+        try:
+            output.append(2)
+        finally:
+            async with asynctracecontext(output, 4):
+                output.append(5)
+            output.append(6)
+        output.append(7)
+
     @jump_test(8, 11, [1, 3, 5, 11, 12])
     def test_jump_out_of_complex_nested_blocks(output):
         output.append(1)
@@ -864,6 +953,14 @@ def test_jump_out_of_with_assignment(output):
             output.append(4)
         output.append(5)
 
+    @async_jump_test(3, 5, [1, 2, 5])
+    async def test_jump_out_of_async_with_assignment(output):
+        output.append(1)
+        async with asynctracecontext(output, 2) \
+                as x:
+            output.append(4)
+        output.append(5)
+
     @jump_test(3, 6, [1, 6, 8, 9])
     def test_jump_over_return_in_try_finally_block(output):
         output.append(1)
@@ -982,12 +1079,24 @@ def test_no_jump_forwards_into_with_block(output):
         with tracecontext(output, 2):
             output.append(3)
 
+    @async_jump_test(1, 3, [], (ValueError, 'into'))
+    async def test_no_jump_forwards_into_async_with_block(output):
+        output.append(1)
+        async with asynctracecontext(output, 2):
+            output.append(3)
+
     @jump_test(3, 2, [1, 2, -1], (ValueError, 'into'))
     def test_no_jump_backwards_into_with_block(output):
         with tracecontext(output, 1):
             output.append(2)
         output.append(3)
 
+    @async_jump_test(3, 2, [1, 2, -1], (ValueError, 'into'))
+    async def test_no_jump_backwards_into_async_with_block(output):
+        async with asynctracecontext(output, 1):
+            output.append(2)
+        output.append(3)
+
     @jump_test(1, 3, [], (ValueError, 'into'))
     def test_no_jump_forwards_into_try_finally_block(output):
         output.append(1)
@@ -1068,6 +1177,14 @@ def test_no_jump_between_with_blocks(output):
         with tracecontext(output, 4):
             output.append(5)
 
+    @async_jump_test(3, 5, [1, 2, -2], (ValueError, 'into'))
+    async def test_no_jump_between_async_with_blocks(output):
+        output.append(1)
+        async with asynctracecontext(output, 2):
+            output.append(3)
+        async with asynctracecontext(output, 4):
+            output.append(5)
+
     @jump_test(7, 4, [1, 6], (ValueError, 'into'))
     def test_no_jump_into_for_block_before_else(output):
         output.append(1)



More information about the Python-checkins mailing list