Skip to content

Commit 5effb8a

Browse files
committed
Suggest to make implementations of some function always return awaitable.
See discussion in ipython#1272; It is not deprected, but being able to always know you can (and must) await should be simpler in the long run. Deprecating now is not the point, but I want to cover our bases, so that we are more confident later when and if we want to enforce those await. In particular many of those branches are not covered in our tests – and I don't even know wether they were ever taken; I changed some of the base methods to be async, but I'm happy to move those back to sync. A few other things use the `if awaitable(...):` pattern but are a bit more complicted, and some do not dates from 2021, so those will be dealt with separately.
1 parent 8c8d7d2 commit 5effb8a

File tree

2 files changed

+55
-4
lines changed

2 files changed

+55
-4
lines changed

ipykernel/ipkernel.py

+2-2
Original file line numberDiff line numberDiff line change
@@ -491,7 +491,7 @@ async def run(execution: Execution) -> None:
491491

492492
return reply_content
493493

494-
def do_complete(self, code, cursor_pos):
494+
async def do_complete(self, code, cursor_pos):
495495
"""Handle code completion."""
496496
if _use_experimental_60_completion and self.use_experimental_completions:
497497
return self._experimental_do_complete(code, cursor_pos)
@@ -625,7 +625,7 @@ def do_history(
625625
"history": list(hist),
626626
}
627627

628-
def do_shutdown(self, restart):
628+
async def do_shutdown(self, restart):
629629
"""Handle kernel shutdown."""
630630
if self.shell:
631631
self.shell.exit_now = True

ipykernel/kernelbase.py

+53-2
Original file line numberDiff line numberDiff line change
@@ -57,6 +57,15 @@
5757
from ._version import kernel_protocol_version
5858
from .iostream import OutStream
5959

60+
_AWAITABLE_MESSAGE = (
61+
"For consistency across implementations, it is recommended that `{func_name}`"
62+
" either be a coroutine function (async def) or return an awaitable object"
63+
" (like a Future) function (`async def`) it might become a requirement in"
64+
" the future."
65+
" Coroutine functions and awaitable have been supported since"
66+
" ipykernel 6.0 (2021).",
67+
)
68+
6069

6170
def _accepts_parameters(meth, param_names):
6271
parameters = inspect.signature(meth).parameters
@@ -742,6 +751,12 @@ async def execute_request(self, socket, ident, parent):
742751

743752
if inspect.isawaitable(reply_content):
744753
reply_content = await reply_content
754+
else:
755+
warnings.warn(
756+
_AWAITABLE_MESSAGE.format(func_name="execute_request"),
757+
PendingDeprecationWarning,
758+
stacklevel=1,
759+
)
745760

746761
# Flush output before sending the reply.
747762
if sys.stdout is not None:
@@ -802,11 +817,17 @@ async def complete_request(self, socket, ident, parent):
802817
matches = self.do_complete(code, cursor_pos)
803818
if inspect.isawaitable(matches):
804819
matches = await matches
820+
else:
821+
warnings.warn(
822+
_AWAITABLE_MESSAGE.format(func_name="do_complete"),
823+
PendingDeprecationWarning,
824+
stacklevel=1,
825+
)
805826

806827
matches = json_clean(matches)
807828
self.session.send(socket, "complete_reply", matches, parent, ident)
808829

809-
def do_complete(self, code, cursor_pos):
830+
async def do_complete(self, code, cursor_pos):
810831
"""Override in subclasses to find completions."""
811832
return {
812833
"matches": [],
@@ -830,6 +851,12 @@ async def inspect_request(self, socket, ident, parent):
830851
)
831852
if inspect.isawaitable(reply_content):
832853
reply_content = await reply_content
854+
else:
855+
warnings.warn(
856+
_AWAITABLE_MESSAGE.format(func_name="inspect_request"),
857+
PendingDeprecationWarning,
858+
stacklevel=1,
859+
)
833860

834861
# Before we send this object over, we scrub it for JSON usage
835862
reply_content = json_clean(reply_content)
@@ -849,6 +876,12 @@ async def history_request(self, socket, ident, parent):
849876
reply_content = self.do_history(**content)
850877
if inspect.isawaitable(reply_content):
851878
reply_content = await reply_content
879+
else:
880+
warnings.warn(
881+
_AWAITABLE_MESSAGE.format(func_name="history_request"),
882+
PendingDeprecationWarning,
883+
stacklevel=1,
884+
)
852885

853886
reply_content = json_clean(reply_content)
854887
msg = self.session.send(socket, "history_reply", reply_content, parent, ident)
@@ -966,6 +999,12 @@ async def shutdown_request(self, socket, ident, parent):
966999
content = self.do_shutdown(parent["content"]["restart"])
9671000
if inspect.isawaitable(content):
9681001
content = await content
1002+
else:
1003+
warnings.warn(
1004+
_AWAITABLE_MESSAGE.format(func_name="do_shutdown"),
1005+
PendingDeprecationWarning,
1006+
stacklevel=1,
1007+
)
9691008
self.session.send(socket, "shutdown_reply", content, parent, ident=ident)
9701009
# same content, but different msg_id for broadcasting on IOPub
9711010
self._shutdown_message = self.session.msg("shutdown_reply", content, parent)
@@ -974,7 +1013,7 @@ async def shutdown_request(self, socket, ident, parent):
9741013

9751014
self.stop()
9761015

977-
def do_shutdown(self, restart):
1016+
async def do_shutdown(self, restart):
9781017
"""Override in subclasses to do things when the frontend shuts down the
9791018
kernel.
9801019
"""
@@ -990,6 +1029,12 @@ async def is_complete_request(self, socket, ident, parent):
9901029
reply_content = self.do_is_complete(code)
9911030
if inspect.isawaitable(reply_content):
9921031
reply_content = await reply_content
1032+
else:
1033+
warnings.warn(
1034+
_AWAITABLE_MESSAGE.format(func_name="do_execute"),
1035+
PendingDeprecationWarning,
1036+
stacklevel=1,
1037+
)
9931038
reply_content = json_clean(reply_content)
9941039
reply_msg = self.session.send(socket, "is_complete_reply", reply_content, parent, ident)
9951040
self.log.debug("%s", reply_msg)
@@ -1006,6 +1051,12 @@ async def debug_request(self, socket, ident, parent):
10061051
reply_content = self.do_debug_request(content)
10071052
if inspect.isawaitable(reply_content):
10081053
reply_content = await reply_content
1054+
else:
1055+
warnings.warn(
1056+
_AWAITABLE_MESSAGE.format(func_name="debug_request"),
1057+
PendingDeprecationWarning,
1058+
stacklevel=1,
1059+
)
10091060
reply_content = json_clean(reply_content)
10101061
reply_msg = self.session.send(socket, "debug_reply", reply_content, parent, ident)
10111062
self.log.debug("%s", reply_msg)

0 commit comments

Comments
 (0)