aboutsummaryrefslogtreecommitdiffstats
path: root/contrib/python/ipython/py3/IPython/terminal/pt_inputhooks/asyncio.py
diff options
context:
space:
mode:
authornkozlovskiy <nmk@ydb.tech>2023-09-29 12:24:06 +0300
committernkozlovskiy <nmk@ydb.tech>2023-09-29 12:41:34 +0300
commite0e3e1717e3d33762ce61950504f9637a6e669ed (patch)
treebca3ff6939b10ed60c3d5c12439963a1146b9711 /contrib/python/ipython/py3/IPython/terminal/pt_inputhooks/asyncio.py
parent38f2c5852db84c7b4d83adfcb009eb61541d1ccd (diff)
downloadydb-e0e3e1717e3d33762ce61950504f9637a6e669ed.tar.gz
add ydb deps
Diffstat (limited to 'contrib/python/ipython/py3/IPython/terminal/pt_inputhooks/asyncio.py')
-rw-r--r--contrib/python/ipython/py3/IPython/terminal/pt_inputhooks/asyncio.py62
1 files changed, 62 insertions, 0 deletions
diff --git a/contrib/python/ipython/py3/IPython/terminal/pt_inputhooks/asyncio.py b/contrib/python/ipython/py3/IPython/terminal/pt_inputhooks/asyncio.py
new file mode 100644
index 0000000000..d2499e11e6
--- /dev/null
+++ b/contrib/python/ipython/py3/IPython/terminal/pt_inputhooks/asyncio.py
@@ -0,0 +1,62 @@
+"""
+Inputhook for running the original asyncio event loop while we're waiting for
+input.
+
+By default, in IPython, we run the prompt with a different asyncio event loop,
+because otherwise we risk that people are freezing the prompt by scheduling bad
+coroutines. E.g., a coroutine that does a while/true and never yield back
+control to the loop. We can't cancel that.
+
+However, sometimes we want the asyncio loop to keep running while waiting for
+a prompt.
+
+The following example will print the numbers from 1 to 10 above the prompt,
+while we are waiting for input. (This works also because we use
+prompt_toolkit`s `patch_stdout`)::
+
+ In [1]: import asyncio
+
+ In [2]: %gui asyncio
+
+ In [3]: async def f():
+ ...: for i in range(10):
+ ...: await asyncio.sleep(1)
+ ...: print(i)
+
+
+ In [4]: asyncio.ensure_future(f())
+
+"""
+from prompt_toolkit import __version__ as ptk_version
+
+from IPython.core.async_helpers import get_asyncio_loop
+
+PTK3 = ptk_version.startswith("3.")
+
+
+def inputhook(context):
+ """
+ Inputhook for asyncio event loop integration.
+ """
+ # For prompt_toolkit 3.0, this input hook literally doesn't do anything.
+ # The event loop integration here is implemented in `interactiveshell.py`
+ # by running the prompt itself in the current asyncio loop. The main reason
+ # for this is that nesting asyncio event loops is unreliable.
+ if PTK3:
+ return
+
+ # For prompt_toolkit 2.0, we can run the current asyncio event loop,
+ # because prompt_toolkit 2.0 uses a different event loop internally.
+
+ # get the persistent asyncio event loop
+ loop = get_asyncio_loop()
+
+ def stop():
+ loop.stop()
+
+ fileno = context.fileno()
+ loop.add_reader(fileno, stop)
+ try:
+ loop.run_forever()
+ finally:
+ loop.remove_reader(fileno)