From fbabb2b20bc71fec5e5b489efd2f8d0f5f4c6f9f Mon Sep 17 00:00:00 2001 From: David Brochart Date: Thu, 24 Nov 2022 09:06:54 +0100 Subject: [PATCH 1/8] Remove nest-asyncio --- binder/environment.yml | 2 +- nbclient/tests/test_util.py | 16 ++---- nbclient/util.py | 100 +----------------------------------- pyproject.toml | 2 - 4 files changed, 6 insertions(+), 114 deletions(-) diff --git a/binder/environment.yml b/binder/environment.yml index e3bc3809..64f77d90 100644 --- a/binder/environment.yml +++ b/binder/environment.yml @@ -5,6 +5,6 @@ dependencies: - numpy - pandas - matplotlib - - nteract-scrapbook + - scrapbook - nbformat - nbclient diff --git a/nbclient/tests/test_util.py b/nbclient/tests/test_util.py index dc206826..e40c639c 100644 --- a/nbclient/tests/test_util.py +++ b/nbclient/tests/test_util.py @@ -20,31 +20,23 @@ async def _test(): loop = asyncio.new_event_loop() asyncio.set_event_loop(loop) - try: - event_loop = loop.run_until_complete(_test()) - assert event_loop is loop - finally: - asyncio._set_running_loop(None) # it seems nest_asyncio doesn't reset this + event_loop = loop.run_until_complete(_test()) + assert event_loop is loop def test_nested_asyncio_with_no_ioloop(): asyncio.set_event_loop(None) - try: - assert some_async_function() == 42 - finally: - asyncio._set_running_loop(None) # it seems nest_asyncio doesn't reset this + assert some_async_function() == 42 def test_nested_asyncio_with_tornado(): # This tests if tornado accepts the pure-Python Futures, see # https://github.com/tornadoweb/tornado/issues/2753 - # https://github.com/erdewit/nest_asyncio/issues/23 asyncio.set_event_loop(asyncio.new_event_loop()) ioloop = tornado.ioloop.IOLoop.current() async def some_async_function(): future: asyncio.Future = asyncio.ensure_future(asyncio.sleep(0.1)) - # this future is a different future after nested-asyncio has patched # the asyncio module, check if tornado likes it: ioloop.add_future(future, lambda f: f.result()) # type:ignore await future @@ -56,8 +48,6 @@ def some_sync_function(): async def run(): # calling some_async_function directly should work assert await some_async_function() == 42 - # but via a sync function (using nested-asyncio) can lead to issues: - # https://github.com/tornadoweb/tornado/issues/2753 assert some_sync_function() == 42 ioloop.run_sync(run) diff --git a/nbclient/util.py b/nbclient/util.py index 4d6b689d..480e40eb 100644 --- a/nbclient/util.py +++ b/nbclient/util.py @@ -3,106 +3,10 @@ # Copyright (c) Jupyter Development Team. # Distributed under the terms of the Modified BSD License. -import asyncio import inspect -import sys -from typing import Any, Awaitable, Callable, Optional, TypeVar, Union +from typing import Any, Callable, Optional - -def check_ipython() -> None: - # original from vaex/asyncio.py - IPython = sys.modules.get('IPython') - if IPython: - version_str = IPython.__version__ - # We get rid of any trailing ".dev" - version_str = version_str.replace(".dev", "") - - IPython_version = tuple(map(int, version_str.split('.'))) - if IPython_version < (7, 0, 0): - raise RuntimeError( - f'You are using IPython {IPython.__version__} ' - 'while we require 7.0.0+, please update IPython' - ) - - -def check_patch_tornado() -> None: - """If tornado is imported, add the patched asyncio.Future to its tuple of acceptable Futures""" - # original from vaex/asyncio.py - if 'tornado' in sys.modules: - import tornado.concurrent - - if asyncio.Future not in tornado.concurrent.FUTURES: - tornado.concurrent.FUTURES = tornado.concurrent.FUTURES + ( - asyncio.Future, - ) # type:ignore[assignment] - - -def just_run(coro: Awaitable) -> Any: - """Make the coroutine run, even if there is an event loop running (using nest_asyncio)""" - try: - loop = asyncio.get_running_loop() - except RuntimeError: - loop = None - if loop is None: - had_running_loop = False - loop = asyncio.new_event_loop() - asyncio.set_event_loop(loop) - else: - had_running_loop = True - if had_running_loop: - # if there is a running loop, we patch using nest_asyncio - # to have reentrant event loops - check_ipython() - import nest_asyncio - - nest_asyncio.apply() - check_patch_tornado() - return loop.run_until_complete(coro) - - -T = TypeVar("T") - - -def run_sync(coro: Callable[..., Awaitable[T]]) -> Callable[..., T]: - """Runs a coroutine and blocks until it has executed. - - An event loop is created if no one already exists. If an event loop is - already running, this event loop execution is nested into the already - running one if `nest_asyncio` is set to True. - - Parameters - ---------- - coro : coroutine - The coroutine to be executed. - - Returns - ------- - result : - Whatever the coroutine returns. - """ - - def wrapped(*args, **kwargs): - return just_run(coro(*args, **kwargs)) - - wrapped.__doc__ = coro.__doc__ - return wrapped - - -async def ensure_async(obj: Union[Awaitable, Any]) -> Any: - """Convert a non-awaitable object to a coroutine if needed, - and await it if it was not already awaited. - """ - if inspect.isawaitable(obj): - try: - result = await obj - except RuntimeError as e: - if str(e) == 'cannot reuse already awaited coroutine': - # obj is already the coroutine's result - return obj - raise - return result - # obj doesn't need to be awaited - return obj +from jupyter_core.utils import ensure_async, run_sync # noqa: F401 async def run_hook(hook: Optional[Callable], **kwargs: Any) -> None: diff --git a/pyproject.toml b/pyproject.toml index 62afba3d..7416b1f9 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -37,7 +37,6 @@ classifiers = [ dependencies = [ "jupyter_client>=6.1.12", "nbformat>=5.1", - "nest_asyncio", "traitlets>=5.3", ] @@ -153,7 +152,6 @@ warn_unused_ignores = true [[tool.mypy.overrides]] module = [ "async_generator.*", - "nest_asyncio.*", "testpath", "xmltodict", ] From b77eb065e3db8bf7e1fa93d975b2d3e29cc68aab Mon Sep 17 00:00:00 2001 From: David Brochart Date: Fri, 25 Nov 2022 10:05:14 +0100 Subject: [PATCH 2/8] Add upper bound to dependencies --- pyproject.toml | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/pyproject.toml b/pyproject.toml index 7416b1f9..df51dee5 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -35,9 +35,9 @@ classifiers = [ "Programming Language :: Python :: 3.10", ] dependencies = [ - "jupyter_client>=6.1.12", - "nbformat>=5.1", - "traitlets>=5.3", + "jupyter_client>=6.1.12,<8", + "nbformat>=5.1,<6", + "traitlets>=5.3<6", ] [project.optional-dependencies] From 50dade8f2deda3f34e32326e851b2890f0c2a822 Mon Sep 17 00:00:00 2001 From: David Brochart Date: Fri, 25 Nov 2022 15:17:19 +0100 Subject: [PATCH 3/8] Revert last change --- pyproject.toml | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/pyproject.toml b/pyproject.toml index df51dee5..7416b1f9 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -35,9 +35,9 @@ classifiers = [ "Programming Language :: Python :: 3.10", ] dependencies = [ - "jupyter_client>=6.1.12,<8", - "nbformat>=5.1,<6", - "traitlets>=5.3<6", + "jupyter_client>=6.1.12", + "nbformat>=5.1", + "traitlets>=5.3", ] [project.optional-dependencies] From 1d5810446898dda6ffbe7b85b0b13ab2ee81a3ea Mon Sep 17 00:00:00 2001 From: David Brochart Date: Mon, 28 Nov 2022 14:58:51 +0100 Subject: [PATCH 4/8] Require jupyter_core>=4.12 --- pyproject.toml | 1 + 1 file changed, 1 insertion(+) diff --git a/pyproject.toml b/pyproject.toml index 7416b1f9..dbf77648 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -36,6 +36,7 @@ classifiers = [ ] dependencies = [ "jupyter_client>=6.1.12", + "jupyter_core>=4.12", "nbformat>=5.1", "traitlets>=5.3", ] From 0f7fa8e7d401fee76c896c556a02c76a989ae2ff Mon Sep 17 00:00:00 2001 From: Steven Silvester Date: Mon, 28 Nov 2022 21:06:45 -0600 Subject: [PATCH 5/8] update dep --- pyproject.toml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pyproject.toml b/pyproject.toml index dbf77648..f678ad64 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -36,7 +36,7 @@ classifiers = [ ] dependencies = [ "jupyter_client>=6.1.12", - "jupyter_core>=4.12", + "jupyter_core>=4.12,!=~5.0", "nbformat>=5.1", "traitlets>=5.3", ] From 89e86a465b8055984d43c6a0b09a644dc1728cb9 Mon Sep 17 00:00:00 2001 From: Steven Silvester Date: Mon, 28 Nov 2022 21:07:57 -0600 Subject: [PATCH 6/8] update mypy dep --- .pre-commit-config.yaml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.pre-commit-config.yaml b/.pre-commit-config.yaml index 504fbe67..c5a0eb97 100644 --- a/.pre-commit-config.yaml +++ b/.pre-commit-config.yaml @@ -42,7 +42,7 @@ repos: rev: v0.990 hooks: - id: mypy - additional_dependencies: [jupyter_client, jupyter_core, nbformat, nbconvert] + additional_dependencies: [jupyter_client, jupyter_core>=5.1, nbformat, nbconvert] - repo: https://github.com/abravalheri/validate-pyproject rev: v0.10.1 From 66966fcfddb902e35de7c63b1940f8ac36d6f9a1 Mon Sep 17 00:00:00 2001 From: David Brochart Date: Tue, 29 Nov 2022 09:11:51 +0100 Subject: [PATCH 7/8] Fix mypy --- nbclient/tests/test_util.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/nbclient/tests/test_util.py b/nbclient/tests/test_util.py index e40c639c..3ffe70bd 100644 --- a/nbclient/tests/test_util.py +++ b/nbclient/tests/test_util.py @@ -33,12 +33,12 @@ def test_nested_asyncio_with_tornado(): # This tests if tornado accepts the pure-Python Futures, see # https://github.com/tornadoweb/tornado/issues/2753 asyncio.set_event_loop(asyncio.new_event_loop()) - ioloop = tornado.ioloop.IOLoop.current() + ioloop = tornado.ioloop.IOLoop.current() # type: ignore async def some_async_function(): future: asyncio.Future = asyncio.ensure_future(asyncio.sleep(0.1)) # the asyncio module, check if tornado likes it: - ioloop.add_future(future, lambda f: f.result()) # type:ignore + ioloop.add_future(future, lambda f: f.result()) await future return 42 From 94a6b89df058abe3fa99f8effffd28937837705f Mon Sep 17 00:00:00 2001 From: David Brochart Date: Tue, 29 Nov 2022 09:24:47 +0100 Subject: [PATCH 8/8] Update traceback normalization --- nbclient/tests/test_client.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/nbclient/tests/test_client.py b/nbclient/tests/test_client.py index 86d0fd11..353f2938 100644 --- a/nbclient/tests/test_client.py +++ b/nbclient/tests/test_client.py @@ -35,7 +35,7 @@ # Tracebacks look different in IPython 8, # see: https://github.com/ipython/ipython/blob/master/docs/source/whatsnew/version8.rst#traceback-improvements # noqa ipython8_input_pat = re.compile( - r'((Cell|Input) In \[\d+\]|), (in )?(line \d||\(\))' + r'((Cell|Input) In\[\d+\]|), (in )?(line \d||\(\))' )