]> git.ipfire.org Git - thirdparty/Python/cpython.git/commitdiff
gh-128265: Support WASI/Emscripten on PDB tests, by removing asyncio from pdb tests...
authorThomas Grainger <tagrain@gmail.com>
Sat, 28 Dec 2024 14:59:49 +0000 (14:59 +0000)
committerGitHub <noreply@github.com>
Sat, 28 Dec 2024 14:59:49 +0000 (16:59 +0200)
A part of `Lib/test/test_pdb.py` was previously unable to run on WASI/Emscripten
platforms because it lacked support for `asyncio`.
In fact, these tests could be rewritten without the `asyncio` framework because
`test_pdb` tests the behavior of coroutines, which are not part of `asyncio`.

Now reliance on the availability of `asyncio` has been removed and
part of `test_pdb` that deals with coroutines working on WASI/Emscripten platforms.

Lib/test/support/__init__.py
Lib/test/test_contextlib_async.py
Lib/test/test_inspect/test_inspect.py
Lib/test/test_pdb.py

index 5c738ffaa277139834ecd9120698f5b6864367e0..cf3077f2a4a4092d0f0e40311da5c373559e9975 100644 (file)
@@ -62,6 +62,7 @@ __all__ = [
     "force_not_colorized",
     "BrokenIter",
     "in_systemd_nspawn_sync_suppressed",
+    "run_no_yield_async_fn", "run_yielding_async_fn", "async_yield",
     ]
 
 
@@ -2940,3 +2941,31 @@ def in_systemd_nspawn_sync_suppressed() -> bool:
         os.close(fd)
 
     return False
+
+def run_no_yield_async_fn(async_fn, /, *args, **kwargs):
+    coro = async_fn(*args, **kwargs)
+    try:
+        coro.send(None)
+    except StopIteration as e:
+        return e.value
+    else:
+        raise AssertionError("coroutine did not complete")
+    finally:
+        coro.close()
+
+
+@types.coroutine
+def async_yield(v):
+    return (yield v)
+
+
+def run_yielding_async_fn(async_fn, /, *args, **kwargs):
+    coro = async_fn(*args, **kwargs)
+    try:
+        while True:
+            try:
+                coro.send(None)
+            except StopIteration as e:
+                return e.value
+    finally:
+        coro.close()
index d496aa611d106805cce2d14b5202d2281f3315cc..7750186e56a5ccbe4ef24ddca60a49c1ed7144f1 100644 (file)
@@ -3,24 +3,13 @@ from contextlib import (
     asynccontextmanager, AbstractAsyncContextManager,
     AsyncExitStack, nullcontext, aclosing, contextmanager)
 from test import support
+from test.support import run_no_yield_async_fn as _run_async_fn
 import unittest
 import traceback
 
 from test.test_contextlib import TestBaseExitStack
 
 
-def _run_async_fn(async_fn, /, *args, **kwargs):
-    coro = async_fn(*args, **kwargs)
-    try:
-        coro.send(None)
-    except StopIteration as e:
-        return e.value
-    else:
-        raise AssertionError("coroutine did not complete")
-    finally:
-        coro.close()
-
-
 def _async_test(async_fn):
     """Decorator to turn an async function into a synchronous function"""
     @functools.wraps(async_fn)
@@ -546,7 +535,7 @@ class TestAsyncExitStack(TestBaseExitStack, unittest.TestCase):
     exit_stack = SyncAsyncExitStack
     callback_error_internal_frames = [
         ('__exit__', 'return _run_async_fn(self.__aexit__, *exc_details)'),
-        ('_run_async_fn', 'coro.send(None)'),
+        ('run_no_yield_async_fn', 'coro.send(None)'),
         ('__aexit__', 'raise exc'),
         ('__aexit__', 'cb_suppress = cb(*exc_details)'),
     ]
index d536d04d2e7d88cf0cd4e99ec63386b5320af360..345a57a5cfee2d2c6998f2d8bbfa44d52f0d2b2c 100644 (file)
@@ -36,6 +36,7 @@ except ImportError:
 
 from test.support import cpython_only, import_helper
 from test.support import MISSING_C_DOCSTRINGS, ALWAYS_EQ
+from test.support import run_no_yield_async_fn
 from test.support.import_helper import DirsOnSysPath, ready_to_import
 from test.support.os_helper import TESTFN, temp_cwd
 from test.support.script_helper import assert_python_ok, assert_python_failure, kill_python
@@ -1161,19 +1162,11 @@ class TestBuggyCases(GetSourceBase):
                 sys.modules.pop("inspect_actual")
 
     def test_nested_class_definition_inside_async_function(self):
-        def run(coro):
-            try:
-                coro.send(None)
-            except StopIteration as e:
-                return e.value
-            else:
-                raise RuntimeError("coroutine did not complete synchronously!")
-            finally:
-                coro.close()
+        run = run_no_yield_async_fn
 
-        self.assertSourceEqual(run(mod2.func225()), 226, 227)
+        self.assertSourceEqual(run(mod2.func225), 226, 227)
         self.assertSourceEqual(mod2.cls226, 231, 235)
-        self.assertSourceEqual(run(mod2.cls226().func232()), 233, 234)
+        self.assertSourceEqual(run(mod2.cls226().func232), 233, 234)
 
     def test_class_definition_same_name_diff_methods(self):
         self.assertSourceEqual(mod2.cls296, 296, 298)
index 9b0806d8b2a9bd110e4070001180791e3a57f627..c5ee8c5fb25350cfeeeae9749806410ddcbcadd3 100644 (file)
@@ -20,8 +20,7 @@ from test.support.import_helper import import_module
 from test.support.pty_helper import run_pty, FakeInput
 from unittest.mock import patch
 
-# gh-114275: WASI fails to run asyncio tests, similar skip than test_asyncio.
-SKIP_ASYNCIO_TESTS = (not support.has_socket_support)
+SKIP_CORO_TESTS = False
 
 
 class PdbTestInput(object):
@@ -1987,7 +1986,7 @@ def test_next_until_return_at_return_event():
     """
 
 def test_pdb_next_command_for_generator():
-    """Testing skip unwindng stack on yield for generators for "next" command
+    """Testing skip unwinding stack on yield for generators for "next" command
 
     >>> def test_gen():
     ...     yield 0
@@ -2049,23 +2048,23 @@ def test_pdb_next_command_for_generator():
     finished
     """
 
-if not SKIP_ASYNCIO_TESTS:
+if not SKIP_CORO_TESTS:
     def test_pdb_next_command_for_coroutine():
-        """Testing skip unwindng stack on yield for coroutines for "next" command
+        """Testing skip unwinding stack on yield for coroutines for "next" command
 
-        >>> import asyncio
+        >>> from test.support import run_yielding_async_fn, async_yield
 
         >>> async def test_coro():
-        ...     await asyncio.sleep(0)
-        ...     await asyncio.sleep(0)
-        ...     await asyncio.sleep(0)
+        ...     await async_yield(0)
+        ...     await async_yield(0)
+        ...     await async_yield(0)
 
         >>> async def test_main():
         ...     import pdb; pdb.Pdb(nosigint=True, readrc=False).set_trace()
         ...     await test_coro()
 
         >>> def test_function():
-        ...     asyncio.run(test_main())
+        ...     run_yielding_async_fn(test_main)
         ...     print("finished")
 
         >>> with PdbTestInput(['step',
@@ -2088,13 +2087,13 @@ if not SKIP_ASYNCIO_TESTS:
         -> async def test_coro():
         (Pdb) step
         > <doctest test.test_pdb.test_pdb_next_command_for_coroutine[1]>(2)test_coro()
-        -> await asyncio.sleep(0)
+        -> await async_yield(0)
         (Pdb) next
         > <doctest test.test_pdb.test_pdb_next_command_for_coroutine[1]>(3)test_coro()
-        -> await asyncio.sleep(0)
+        -> await async_yield(0)
         (Pdb) next
         > <doctest test.test_pdb.test_pdb_next_command_for_coroutine[1]>(4)test_coro()
-        -> await asyncio.sleep(0)
+        -> await async_yield(0)
         (Pdb) next
         Internal StopIteration
         > <doctest test.test_pdb.test_pdb_next_command_for_coroutine[2]>(3)test_main()
@@ -2108,13 +2107,13 @@ if not SKIP_ASYNCIO_TESTS:
         """
 
     def test_pdb_next_command_for_asyncgen():
-        """Testing skip unwindng stack on yield for coroutines for "next" command
+        """Testing skip unwinding stack on yield for coroutines for "next" command
 
-        >>> import asyncio
+        >>> from test.support import run_yielding_async_fn, async_yield
 
         >>> async def agen():
         ...     yield 1
-        ...     await asyncio.sleep(0)
+        ...     await async_yield(0)
         ...     yield 2
 
         >>> async def test_coro():
@@ -2126,7 +2125,7 @@ if not SKIP_ASYNCIO_TESTS:
         ...     await test_coro()
 
         >>> def test_function():
-        ...     asyncio.run(test_main())
+        ...     run_yielding_async_fn(test_main)
         ...     print("finished")
 
         >>> with PdbTestInput(['step',
@@ -2163,14 +2162,14 @@ if not SKIP_ASYNCIO_TESTS:
         -> yield 1
         (Pdb) next
         > <doctest test.test_pdb.test_pdb_next_command_for_asyncgen[1]>(3)agen()
-        -> await asyncio.sleep(0)
+        -> await async_yield(0)
         (Pdb) continue
         2
         finished
         """
 
 def test_pdb_return_command_for_generator():
-    """Testing no unwindng stack on yield for generators
+    """Testing no unwinding stack on yield for generators
        for "return" command
 
     >>> def test_gen():
@@ -2228,23 +2227,23 @@ def test_pdb_return_command_for_generator():
     finished
     """
 
-if not SKIP_ASYNCIO_TESTS:
+if not SKIP_CORO_TESTS:
     def test_pdb_return_command_for_coroutine():
-        """Testing no unwindng stack on yield for coroutines for "return" command
+        """Testing no unwinding stack on yield for coroutines for "return" command
 
-        >>> import asyncio
+        >>> from test.support import run_yielding_async_fn, async_yield
 
         >>> async def test_coro():
-        ...     await asyncio.sleep(0)
-        ...     await asyncio.sleep(0)
-        ...     await asyncio.sleep(0)
+        ...     await async_yield(0)
+        ...     await async_yield(0)
+        ...     await async_yield(0)
 
         >>> async def test_main():
         ...     import pdb; pdb.Pdb(nosigint=True, readrc=False).set_trace()
         ...     await test_coro()
 
         >>> def test_function():
-        ...     asyncio.run(test_main())
+        ...     run_yielding_async_fn(test_main)
         ...     print("finished")
 
         >>> with PdbTestInput(['step',
@@ -2264,16 +2263,16 @@ if not SKIP_ASYNCIO_TESTS:
         -> async def test_coro():
         (Pdb) step
         > <doctest test.test_pdb.test_pdb_return_command_for_coroutine[1]>(2)test_coro()
-        -> await asyncio.sleep(0)
+        -> await async_yield(0)
         (Pdb) next
         > <doctest test.test_pdb.test_pdb_return_command_for_coroutine[1]>(3)test_coro()
-        -> await asyncio.sleep(0)
+        -> await async_yield(0)
         (Pdb) continue
         finished
         """
 
 def test_pdb_until_command_for_generator():
-    """Testing no unwindng stack on yield for generators
+    """Testing no unwinding stack on yield for generators
        for "until" command if target breakpoint is not reached
 
     >>> def test_gen():
@@ -2320,20 +2319,20 @@ def test_pdb_until_command_for_generator():
     finished
     """
 
-if not SKIP_ASYNCIO_TESTS:
+if not SKIP_CORO_TESTS:
     def test_pdb_until_command_for_coroutine():
-        """Testing no unwindng stack for coroutines
+        """Testing no unwinding stack for coroutines
         for "until" command if target breakpoint is not reached
 
-        >>> import asyncio
+        >>> from test.support import run_yielding_async_fn, async_yield
 
         >>> async def test_coro():
         ...     print(0)
-        ...     await asyncio.sleep(0)
+        ...     await async_yield(0)
         ...     print(1)
-        ...     await asyncio.sleep(0)
+        ...     await async_yield(0)
         ...     print(2)
-        ...     await asyncio.sleep(0)
+        ...     await async_yield(0)
         ...     print(3)
 
         >>> async def test_main():
@@ -2341,7 +2340,7 @@ if not SKIP_ASYNCIO_TESTS:
         ...     await test_coro()
 
         >>> def test_function():
-        ...     asyncio.run(test_main())
+        ...     run_yielding_async_fn(test_main)
         ...     print("finished")
 
         >>> with PdbTestInput(['step',