Skip to content

Commit 0c1d14d

Browse files
committed
Fix tests and coverage
1 parent 7a850cf commit 0c1d14d

File tree

6 files changed

+41
-22
lines changed

6 files changed

+41
-22
lines changed

.github/workflows/ci.yml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -49,7 +49,7 @@ jobs:
4949
python-version: ${{ matrix.python-version }}
5050

5151
- name: Run tests with coverage
52-
run: uv run pytest -vv --cov
52+
run: uv run pytest -vv --cov --cov-fail-under=100
5353

5454
pre-commit:
5555
runs-on: ubuntu-latest

.vscode/settings.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -18,5 +18,5 @@
1818
"tag:yaml.org,2002:python/object/apply:pymdownx.slugs.slugify mapping"
1919
],
2020
"spellright.language": ["en"],
21-
"spellright.documentTypes": ["markdown", "latex", "plaintext", "python"]
21+
"spellright.documentTypes": ["markdown", "latex", "plaintext"]
2222
}

src/async_kernel/kernel.py

Lines changed: 17 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -605,8 +605,9 @@ async def handle_message_request(self, job: Job, /) -> None:
605605
try:
606606
msg_type = MsgType(job["msg"]["header"]["msg_type"])
607607
socket_id = job["socket_id"]
608-
handler = self.get_handler(socket_id, msg_type)
608+
handler = self.get_handler(msg_type)
609609
except (ValueError, TypeError):
610+
self.log.debug("Invalid job %s", job)
610611
return
611612
run_mode = self.get_run_mode(msg_type, socket_id=socket_id, job=job)
612613
self.log.debug("%s %s run mode %s handler: %s", socket_id, msg_type, run_mode, handler)
@@ -702,9 +703,9 @@ def all_concurrency_run_modes(
702703
data_ = zip(*data, strict=True)
703704
return dict(zip(["SocketID", "KernelConcurrencyMode", "MsgType", "RunMode"], data_, strict=True))
704705

705-
def get_handler(self, socket_id: SocketID, msg_type: MsgType) -> HandlerType:
706+
def get_handler(self, msg_type: MsgType) -> HandlerType:
706707
if not callable(f := getattr(self, msg_type, None)):
707-
msg = "A handler was not found for "
708+
msg = f"A handler was not found for {msg_type=}"
708709
raise TypeError(msg)
709710
return f # pyright: ignore[reportReturnType]
710711

@@ -778,11 +779,11 @@ def topic(self, topic) -> bytes:
778779
"""prefixed topic for IOPub messages"""
779780
return (f"kernel.{topic}").encode()
780781

781-
async def kernel_info_request(self, job: Job[Content]) -> Content:
782+
async def kernel_info_request(self, job: Job[Content], /) -> Content:
782783
"""Handle a ke[rnel info request](https://jupyter-client.readthedocs.io/en/stable/messaging.html#kernel-info)."""
783784
return self.kernel_info
784785

785-
async def comm_info_request(self, job: Job[Content]) -> Content:
786+
async def comm_info_request(self, job: Job[Content], /) -> Content:
786787
"""Handle a [comm info request](https://jupyter-client.readthedocs.io/en/stable/messaging.html#comm-info)."""
787788
c = job["msg"]["content"]
788789
target_name = c.get("target_name", None)
@@ -793,7 +794,7 @@ async def comm_info_request(self, job: Job[Content]) -> Content:
793794
}
794795
return {"comms": comms}
795796

796-
async def execute_request(self, job: Job[ExecuteContent]) -> Content:
797+
async def execute_request(self, job: Job[ExecuteContent], /) -> Content:
797798
"""Handle a [execute request](https://jupyter-client.readthedocs.io/en/stable/messaging.html#execute)."""
798799
c = job["msg"]["content"]
799800
if (
@@ -857,7 +858,7 @@ async def execute_request(self, job: Job[ExecuteContent]) -> Content:
857858
self._stop_on_error_time = time.monotonic()
858859
return content
859860

860-
async def complete_request(self, job: Job[Content]) -> Content:
861+
async def complete_request(self, job: Job[Content], /) -> Content:
861862
"""Handle a [completion request](https://jupyter-client.readthedocs.io/en/stable/messaging.html#completion)."""
862863
c = job["msg"]["content"]
863864
code: str = c["code"]
@@ -883,15 +884,15 @@ async def complete_request(self, job: Job[Content]) -> Content:
883884
"metadata": {"_jupyter_types_experimental": comps},
884885
}
885886

886-
async def is_complete_request(self, job: Job[Content]) -> Content:
887+
async def is_complete_request(self, job: Job[Content], /) -> Content:
887888
"""Handle a [is_complete request](https://jupyter-client.readthedocs.io/en/stable/messaging.html#code-completeness)."""
888889
status, indent_spaces = self.shell.input_transformer_manager.check_complete(job["msg"]["content"]["code"])
889890
content = {"status": status}
890891
if status == "incomplete":
891892
content["indent"] = " " * indent_spaces
892893
return content
893894

894-
async def inspect_request(self, job: Job[Content]) -> Content:
895+
async def inspect_request(self, job: Job[Content], /) -> Content:
895896
"""Handle a [inspect request](https://jupyter-client.readthedocs.io/en/stable/messaging.html#introspection)."""
896897
c = job["msg"]["content"]
897898
detail_level = int(c.get("detail_level", 0))
@@ -910,7 +911,7 @@ async def inspect_request(self, job: Job[Content]) -> Content:
910911
content["found"] = False
911912
return content
912913

913-
async def history_request(self, job: Job[Content]) -> Content:
914+
async def history_request(self, job: Job[Content], /) -> Content:
914915
"""Handle a [history request](https://jupyter-client.readthedocs.io/en/stable/messaging.html#history)."""
915916
c = job["msg"]["content"]
916917
history_manager = self.shell.history_manager
@@ -929,19 +930,19 @@ async def history_request(self, job: Job[Content]) -> Content:
929930
hist = []
930931
return {"history": list(hist)}
931932

932-
async def comm_open(self, job: Job[Content]) -> None:
933+
async def comm_open(self, job: Job[Content], /) -> None:
933934
"""Handle a [comm open request](https://jupyter-client.readthedocs.io/en/stable/messaging.html#opening-a-comm)."""
934935
self.comm_manager.comm_open(stream=job["socket"], ident=job["ident"], msg=job["msg"]) # pyright: ignore[reportArgumentType]
935936

936-
async def comm_msg(self, job: Job[Content]) -> None:
937+
async def comm_msg(self, job: Job[Content], /) -> None:
937938
"""Handle a [comm msg request](https://jupyter-client.readthedocs.io/en/stable/messaging.html#comm-messages)."""
938939
self.comm_manager.comm_msg(stream=job["socket"], ident=job["ident"], msg=job["msg"]) # pyright: ignore[reportArgumentType]
939940

940-
async def comm_close(self, job: Job[Content]) -> None:
941+
async def comm_close(self, job: Job[Content], /) -> None:
941942
"""Handle a [comm close request](https://jupyter-client.readthedocs.io/en/stable/messaging.html#tearing-down-comms)."""
942943
self.comm_manager.comm_close(stream=job["socket"], ident=job["ident"], msg=job["msg"]) # pyright: ignore[reportArgumentType]
943944

944-
async def interrupt_request(self, job: Job[Content]) -> Content:
945+
async def interrupt_request(self, job: Job[Content], /) -> Content:
945946
"""Handle a [interrupt request](https://jupyter-client.readthedocs.io/en/stable/messaging.html#kernel-interrupt) (control only)."""
946947
self._interrupt_requested = True
947948
if sys.platform == "win32":
@@ -953,13 +954,13 @@ async def interrupt_request(self, job: Job[Content]) -> Content:
953954
interrupter()
954955
return {}
955956

956-
async def shutdown_request(self, job: Job[Content]) -> Content:
957+
async def shutdown_request(self, job: Job[Content], /) -> Content:
957958
"""Handle a [shutdown request](https://jupyter-client.readthedocs.io/en/stable/messaging.html#kernel-shutdown) (control only)."""
958959
await self.debugger.disconnect()
959960
Caller().call_no_context(self.stop)
960961
return {"status": "ok", "restart": job["msg"]["content"].get("restart", False)}
961962

962-
async def debug_request(self, job: Job[Content]) -> Content:
963+
async def debug_request(self, job: Job[Content], /) -> Content:
963964
"""Handle a [debug request](https://jupyter-client.readthedocs.io/en/stable/messaging.html#debug-request) (control only)."""
964965
return await self.debugger.process_request(job["msg"]["content"])
965966

tests/conftest.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -32,7 +32,6 @@
3232
@pytest.hookimpl
3333
def pytest_configure(config):
3434
os.environ["PYTEST_TIMEOUT"] = str(1e6) if async_kernel.utils.LAUNCHED_BY_DEBUGPY else str(utils.TIMEOUT)
35-
os.environ["MPLBACKEND"] = utils.MATPLOTLIB_INLINE_BACKEND
3635

3736

3837
@pytest.fixture(scope="module")
@@ -52,6 +51,7 @@ async def kernel(anyio_backend, transport: str, tmp_path_factory):
5251
os.environ["IPYTHONDIR"] = str(tmp_path_factory.mktemp("ipython_config"))
5352
kernel = Kernel()
5453
kernel.connection_file = str(connection_file.resolve())
54+
os.environ["MPLBACKEND"] = utils.MATPLOTLIB_INLINE_BACKEND # Set this implicitly
5555
kernel.transport = transport
5656
async with kernel.start_in_context():
5757
yield kernel

tests/test_debugger.py

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -68,6 +68,9 @@ async def test_debugger(subprocess_kernels_client):
6868
assert reply["status"] == "ok"
6969
assert reply["success"]
7070

71+
reply = await send_debug_request(client, "configurationDone")
72+
assert reply["status"] == "ok"
73+
7174
# Debugger needs to be stopped on a breakpoint
7275
# The steps below expect the 'debugger' to be in a various state (stopped or running)
7376
code = """

tests/test_kernel.py

Lines changed: 18 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@
55

66
from __future__ import annotations
77

8+
import inspect
89
import logging
910
import pathlib
1011
import threading
@@ -349,14 +350,16 @@ async def test_interrupt_request_blocking_exec_request(subprocess_kernels_client
349350

350351

351352
async def test_interrupt_request_blocking_task(subprocess_kernels_client):
352-
code = f"""
353-
{RunMode.task}
354-
time.sleep(100)
353+
code = """
354+
import time
355+
from async_kernel import Caller
356+
await Caller().call_soon(time.sleep, 100)
355357
"""
356358
client = subprocess_kernels_client
357359
msg_id = client.execute(code, reply=False)
358360
await utils.check_pub_message(client, msg_id, execution_state="busy")
359361
await utils.check_pub_message(client, msg_id, msg_type="execute_input")
362+
await anyio.sleep(0.2)
360363
for _ in range(2): # Blocking calls in tasks need to be interrupted twice
361364
await utils.send_control_message(client, MsgType.interrupt_request)
362365
reply = await utils.get_reply(client, msg_id)
@@ -509,6 +512,18 @@ async def test_invalid_message(client, channel):
509512
await utils.clear_iopub(client)
510513

511514

515+
async def test_kernel_get_handler(kernel: Kernel):
516+
with pytest.raises(TypeError):
517+
kernel.get_handler("invalid mode") # pyright: ignore[reportArgumentType]
518+
for msg_type in MsgType:
519+
handler = kernel.get_handler(msg_type)
520+
assert inspect.iscoroutinefunction(handler)
521+
sig = inspect.signature(handler)
522+
assert len(sig.parameters) == 1
523+
param = sig.parameters["job"]
524+
assert param.kind == param.POSITIONAL_ONLY
525+
526+
512527
@pytest.mark.parametrize(
513528
("code", "silent", "socket_id", "expected"),
514529
[

0 commit comments

Comments
 (0)