|
13 | 13 | import sys
|
14 | 14 | from tempfile import TemporaryDirectory
|
15 | 15 | import time
|
| 16 | +import typing as t |
16 | 17 | from warnings import warn
|
17 | 18 |
|
18 | 19 | from typing import Dict as DictType, Any as AnyType
|
|
30 | 31 | Instance,
|
31 | 32 | Any,
|
32 | 33 | )
|
| 34 | +import inspect |
33 | 35 | from traitlets.config import SingletonConfigurable
|
34 | 36 |
|
35 | 37 | from .completer import ZMQCompleter
|
|
76 | 78 | from pygments.util import ClassNotFound
|
77 | 79 | from pygments.token import Token
|
78 | 80 |
|
| 81 | +from jupyter_core.utils import run_sync as _run_sync |
| 82 | + |
| 83 | + |
| 84 | +T = t.TypeVar("T") |
| 85 | + |
| 86 | + |
| 87 | +def run_sync(coro: t.Callable[..., t.Union[T, t.Awaitable[T]]]) -> t.Callable[..., T]: |
| 88 | + """Wraps coroutine in a function that blocks until it has executed. |
| 89 | +
|
| 90 | + Parameters |
| 91 | + ---------- |
| 92 | + coro : coroutine-function |
| 93 | + The coroutine-function to be executed. |
| 94 | +
|
| 95 | + Returns |
| 96 | + ------- |
| 97 | + result : |
| 98 | + Whatever the coroutine-function returns. |
| 99 | + """ |
| 100 | + if not inspect.iscoroutinefunction(coro): |
| 101 | + return t.cast(t.Callable[..., T], coro) |
| 102 | + return _run_sync(coro) |
| 103 | + |
| 104 | + |
79 | 105 |
|
80 | 106 | def ask_yes_no(prompt, default=None, interrupt=None):
|
81 | 107 | """Asks a question and returns a boolean (y/n) answer.
|
@@ -314,7 +340,7 @@ class ZMQTerminalInteractiveShell(SingletonConfigurable):
|
314 | 340 | ),
|
315 | 341 | default_value="multicolumn",
|
316 | 342 | ).tag(config=True)
|
317 |
| - |
| 343 | + |
318 | 344 | prompt_includes_vi_mode = Bool(True,
|
319 | 345 | help="Display the current vi mode (when using vi editing mode)."
|
320 | 346 | ).tag(config=True)
|
@@ -372,7 +398,7 @@ def vi_mode(self):
|
372 | 398 | and self.prompt_includes_vi_mode):
|
373 | 399 | return '['+str(self.pt_cli.app.vi_state.input_mode)[3:6]+'] '
|
374 | 400 | return ''
|
375 |
| - |
| 401 | + |
376 | 402 | def get_prompt_tokens(self, ec=None):
|
377 | 403 | if ec is None:
|
378 | 404 | ec = self.execution_count
|
@@ -705,8 +731,8 @@ def run_cell(self, cell, store_history=True):
|
705 | 731 | return
|
706 | 732 |
|
707 | 733 | # flush stale replies, which could have been ignored, due to missed heartbeats
|
708 |
| - while self.client.shell_channel.msg_ready(): |
709 |
| - self.client.shell_channel.get_msg() |
| 734 | + while run_sync(self.client.shell_channel.msg_ready)(): |
| 735 | + run_sync(self.client.shell_channel.get_msg)() |
710 | 736 | # execute takes 'hidden', which is the inverse of store_hist
|
711 | 737 | msg_id = self.client.execute(cell, not store_history)
|
712 | 738 |
|
@@ -740,7 +766,7 @@ def run_cell(self, cell, store_history=True):
|
740 | 766 |
|
741 | 767 | def handle_execute_reply(self, msg_id, timeout=None):
|
742 | 768 | kwargs = {"timeout": timeout}
|
743 |
| - msg = self.client.shell_channel.get_msg(**kwargs) |
| 769 | + msg = run_sync(self.client.shell_channel.get_msg)(**kwargs) |
744 | 770 | if msg["parent_header"].get("msg_id", None) == msg_id:
|
745 | 771 |
|
746 | 772 | self.handle_iopub(msg_id)
|
@@ -780,7 +806,7 @@ def handle_is_complete_reply(self, msg_id, timeout=None):
|
780 | 806 | msg = None
|
781 | 807 | try:
|
782 | 808 | kwargs = {"timeout": timeout}
|
783 |
| - msg = self.client.shell_channel.get_msg(**kwargs) |
| 809 | + msg = run_sync(self.client.shell_channel.get_msg)(**kwargs) |
784 | 810 | except Empty:
|
785 | 811 | warn('The kernel did not respond to an is_complete_request. '
|
786 | 812 | 'Setting `use_kernel_is_complete` to False.')
|
@@ -849,8 +875,8 @@ def handle_iopub(self, msg_id=''):
|
849 | 875 |
|
850 | 876 | It only displays output that is caused by this session.
|
851 | 877 | """
|
852 |
| - while self.client.iopub_channel.msg_ready(): |
853 |
| - sub_msg = self.client.iopub_channel.get_msg() |
| 878 | + while run_sync(self.client.iopub_channel.msg_ready)(): |
| 879 | + sub_msg = run_sync(self.client.iopub_channel.get_msg)() |
854 | 880 | msg_type = sub_msg['header']['msg_type']
|
855 | 881 |
|
856 | 882 | # Update execution_count in case it changed in another session
|
@@ -1003,7 +1029,7 @@ def handle_image_callable(self, data, mime):
|
1003 | 1029 | def handle_input_request(self, msg_id, timeout=0.1):
|
1004 | 1030 | """ Method to capture raw_input
|
1005 | 1031 | """
|
1006 |
| - req = self.client.stdin_channel.get_msg(timeout=timeout) |
| 1032 | + req = run_sync(self.client.stdin_channel.get_msg)(timeout=timeout) |
1007 | 1033 | # in case any iopub came while we were waiting:
|
1008 | 1034 | self.handle_iopub(msg_id)
|
1009 | 1035 | if msg_id == req["parent_header"].get("msg_id"):
|
@@ -1032,6 +1058,6 @@ def double_int(sig, frame):
|
1032 | 1058 |
|
1033 | 1059 | # only send stdin reply if there *was not* another request
|
1034 | 1060 | # or execution finished while we were reading.
|
1035 |
| - if not (self.client.stdin_channel.msg_ready() or |
1036 |
| - self.client.shell_channel.msg_ready()): |
| 1061 | + if not (run_sync(self.client.stdin_channel.msg_ready)() or |
| 1062 | + run_sync(self.client.shell_channel.msg_ready)()): |
1037 | 1063 | self.client.input(raw_data)
|
0 commit comments