Repository: jupyter/jupyter_client
Pull request #646 (2021-04-27 21:42:44)

Update test kernel with native coroutine, remove async_generator dependency
While updating the Kernel Provisioning PR with all of the recent changes, I ran into a couple of general issues that appear related to some recent updates to ipykernel (`6.0a5`).  Since we're using the `--pre` option to install test dependencies, I thought I'd add these changes to the primary branch since, in all likelihood, the next PR will encounter them.

1. This updates the test kernel subclass `SignalTestKernel` to use a native coroutine that is used in `TestKernelManagerShutDownGracefully`.
2. The return of the tuple from the previously required `async_generator`-decorated method has been removed (as has `yield_`) since we no longer support Python 3.5.
3. I had to conditionally skip the `TestKernelManagerShutDownGracefully` tests that use `shutdown_request` on Python 3.6 since the `ipykernel` updates are not available in that Python release.  These changes are essentially mutually exclusive to those in item 1, so this PR errs on the side of Python 3.7+.


Patch:
diff --git a/setup.py b/setup.py
index 6a5d6d4..63f065b 100644
--- a/setup.py
+++ b/setup.py
@@ -79,7 +79,6 @@ setup_args = dict(
     python_requires='>=3.6.1',
     extras_require={
         'test': [
-            'async_generator',
             'ipykernel',
             'ipython',
             'jedi<0.18; python_version<="3.6"',


Test patch:
diff --git a/jupyter_client/tests/signalkernel.py b/jupyter_client/tests/signalkernel.py
index e26731f..52679f6 100644
--- a/jupyter_client/tests/signalkernel.py
+++ b/jupyter_client/tests/signalkernel.py
@@ -10,7 +10,6 @@ from subprocess import Popen
 from ipykernel.displayhook import ZMQDisplayHook
 from ipykernel.kernelapp import IPKernelApp
 from ipykernel.kernelbase import Kernel
-from tornado.web import gen
 
 
 class SignalTestKernel(Kernel):
@@ -28,10 +27,9 @@ class SignalTestKernel(Kernel):
         if os.environ.get("NO_SIGTERM_REPLY", None) == "1":
             signal.signal(signal.SIGTERM, signal.SIG_IGN)
 
-    @gen.coroutine
-    def shutdown_request(self, stream, ident, parent):
+    async def shutdown_request(self, stream, ident, parent):
         if os.environ.get("NO_SHUTDOWN_REPLY") != "1":
-            yield gen.maybe_future(super().shutdown_request(stream, ident, parent))
+            await super().shutdown_request(stream, ident, parent)
 
     def do_execute(
         self, code, silent, store_history=True, user_expressions=None, allow_stdin=False
diff --git a/jupyter_client/tests/test_kernelmanager.py b/jupyter_client/tests/test_kernelmanager.py
index fc56c5b..44e136c 100644
--- a/jupyter_client/tests/test_kernelmanager.py
+++ b/jupyter_client/tests/test_kernelmanager.py
@@ -11,8 +11,6 @@ import time
 from subprocess import PIPE
 
 import pytest
-from async_generator import async_generator
-from async_generator import yield_
 from jupyter_core import paths
 from traitlets.config.loader import Config
 
@@ -135,11 +133,9 @@ def async_km_subclass(config):
 
 
 @pytest.fixture
-@async_generator  # This is only necessary while Python 3.5 is support afterwhich both it and
-# yield_() can be removed
 async def start_async_kernel():
     km, kc = await start_new_async_kernel(kernel_name="signaltest")
-    await yield_((km, kc))
+    yield km, kc
     kc.stop_channels()
     await km.shutdown_kernel()
     assert km.context.closed
@@ -166,6 +162,9 @@ class TestKernelManagerShutDownGracefully:
     @pytest.mark.skipif(sys.platform == "win32", reason="Windows doesn't support signals")
     @pytest.mark.parametrize(*parameters)
     def test_signal_kernel_subprocesses(self, name, install, expected):
+        # ipykernel doesn't support 3.6 and this test uses async shutdown_request
+        if expected == _ShutdownStatus.ShutdownRequest and sys.version_info < (3, 7):
+            pytest.skip()
         install()
         km, kc = start_new_kernel(kernel_name=name)
         assert km._shutdown_status == _ShutdownStatus.Unset
@@ -180,6 +179,9 @@ class TestKernelManagerShutDownGracefully:
     @pytest.mark.skipif(sys.platform == "win32", reason="Windows doesn't support signals")
     @pytest.mark.parametrize(*parameters)
     async def test_async_signal_kernel_subprocesses(self, name, install, expected):
+        # ipykernel doesn't support 3.6 and this test uses async shutdown_request
+        if expected == _ShutdownStatus.ShutdownRequest and sys.version_info < (3, 7):
+            pytest.skip()
         install()
         km, kc = await start_new_async_kernel(kernel_name=name)
         assert km._shutdown_status == _ShutdownStatus.Unset