Skip to content

Commit a3285d6

Browse files
authored
Add more coverage and add Readme badges (#1031)
1 parent 4c0c037 commit a3285d6

File tree

5 files changed

+148
-16
lines changed

5 files changed

+148
-16
lines changed

README.md

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,9 @@
11
# IPython Kernel for Jupyter
22

3+
[![Build Status](https://github.com/ipython/ipykernel/actions/workflows/ci.yml/badge.svg?query=branch%3Amain++)](https://github.com/ipython/ipykernel/actions/workflows/ci.yml/badge.svg?query=branch%3Amain++)
4+
[![codecov](https://codecov.io/gh/ipython/ipykernel/branch/main/graph/badge.svg?token=SyksDOcIJa)](https://codecov.io/gh/ipython/ipykernel)
5+
[![Documentation Status](https://readthedocs.org/projects/ipython/badge/?version=latest)](http://ipython.readthedocs.io/en/latest/?badge=latest)
6+
37
This package provides the IPython kernel for Jupyter.
48

59
## Installation from source

ipykernel/ipkernel.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -659,7 +659,7 @@ def do_clear(self):
659659

660660

661661
class Kernel(IPythonKernel):
662-
def __init__(self, *args, **kwargs):
662+
def __init__(self, *args, **kwargs): # pragma: no cover
663663
import warnings
664664

665665
warnings.warn(

ipykernel/tests/conftest.py

Lines changed: 36 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,9 @@
88
from tornado.ioloop import IOLoop
99
from zmq.eventloop.zmqstream import ZMQStream
1010

11+
from ipykernel.ipkernel import IPythonKernel
1112
from ipykernel.kernelbase import Kernel
13+
from ipykernel.zmqshell import ZMQInteractiveShell
1214

1315
try:
1416
import resource
@@ -37,20 +39,10 @@
3739
asyncio.set_event_loop_policy(asyncio.WindowsSelectorEventLoopPolicy())
3840

3941

40-
class TestKernel(Kernel):
41-
implementation = "test"
42-
implementation_version = "1.0"
43-
language = "no-op"
44-
language_version = "0.1"
45-
language_info = {
46-
"name": "test",
47-
"mimetype": "text/plain",
48-
"file_extension": ".txt",
49-
}
50-
banner = "test kernel"
42+
class KernelMixin:
5143
log = logging.getLogger()
5244

53-
def __init__(self, *args, **kwargs):
45+
def _initialize(self):
5446
self.context = context = zmq.Context()
5547
self.iopub_socket = context.socket(zmq.PUB)
5648
self.session = Session()
@@ -64,7 +56,6 @@ def __init__(self, *args, **kwargs):
6456
self.test_sockets.append(socket)
6557
self.test_streams.append(stream)
6658
setattr(self, f"{name}_stream", stream)
67-
super().__init__(*args, **kwargs)
6859

6960
def do_execute(
7061
self, code, silent, store_history=True, user_expressions=None, allow_stdin=False
@@ -123,9 +114,41 @@ def _send_interupt_children(self):
123114
pass
124115

125116

117+
class TestKernel(KernelMixin, Kernel):
118+
implementation = "test"
119+
implementation_version = "1.0"
120+
language = "no-op"
121+
language_version = "0.1"
122+
language_info = {
123+
"name": "test",
124+
"mimetype": "text/plain",
125+
"file_extension": ".txt",
126+
}
127+
banner = "test kernel"
128+
129+
def __init__(self, *args, **kwargs):
130+
self._initialize()
131+
super().__init__(*args, **kwargs)
132+
133+
134+
class TestIPyKernel(KernelMixin, IPythonKernel):
135+
def __init__(self, *args, **kwargs):
136+
self._initialize()
137+
super().__init__(*args, **kwargs)
138+
139+
126140
@pytest.fixture
127141
async def kernel():
128142
kernel = TestKernel()
129143
kernel.io_loop = IOLoop.current()
130144
yield kernel
131145
kernel.destroy()
146+
147+
148+
@pytest.fixture
149+
async def ipkernel():
150+
kernel = TestIPyKernel()
151+
kernel.io_loop = IOLoop.current()
152+
yield kernel
153+
kernel.destroy()
154+
ZMQInteractiveShell.clear_instance()
Lines changed: 98 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,98 @@
1+
"""Test IPythonKernel directly"""
2+
3+
import asyncio
4+
import os
5+
6+
import pytest
7+
8+
from ipykernel.ipkernel import IPythonKernel
9+
10+
if os.name == "nt":
11+
pytest.skip("skipping tests on windows", allow_module_level=True)
12+
13+
14+
class user_mod:
15+
__dict__ = {}
16+
17+
18+
async def test_properities(ipkernel: IPythonKernel):
19+
ipkernel.user_module = user_mod()
20+
ipkernel.user_ns = {}
21+
22+
23+
async def test_direct_kernel_info_request(ipkernel):
24+
reply = await ipkernel.test_shell_message("kernel_info_request", {})
25+
assert reply["header"]["msg_type"] == "kernel_info_reply"
26+
27+
28+
async def test_direct_execute_request(ipkernel):
29+
reply = await ipkernel.test_shell_message("execute_request", dict(code="hello", silent=False))
30+
assert reply["header"]["msg_type"] == "execute_reply"
31+
32+
33+
async def test_direct_execute_request_aborting(ipkernel):
34+
ipkernel._aborting = True
35+
reply = await ipkernel.test_shell_message("execute_request", dict(code="hello", silent=False))
36+
assert reply["header"]["msg_type"] == "execute_reply"
37+
assert reply["content"]["status"] == "aborted"
38+
39+
40+
async def test_complete_request(ipkernel):
41+
reply = await ipkernel.test_shell_message("complete_request", dict(code="hello", cursor_pos=0))
42+
assert reply["header"]["msg_type"] == "complete_reply"
43+
44+
45+
async def test_inspect_request(ipkernel):
46+
reply = await ipkernel.test_shell_message("inspect_request", dict(code="hello", cursor_pos=0))
47+
assert reply["header"]["msg_type"] == "inspect_reply"
48+
49+
50+
async def test_history_request(ipkernel):
51+
reply = await ipkernel.test_shell_message(
52+
"history_request", dict(hist_access_type="", output="", raw="")
53+
)
54+
assert reply["header"]["msg_type"] == "history_reply"
55+
56+
57+
async def test_comm_info_request(ipkernel):
58+
reply = await ipkernel.test_shell_message("comm_info_request")
59+
assert reply["header"]["msg_type"] == "comm_info_reply"
60+
61+
62+
async def test_direct_interrupt_request(ipkernel):
63+
reply = await ipkernel.test_shell_message("interrupt_request", {})
64+
assert reply["header"]["msg_type"] == "interrupt_reply"
65+
66+
67+
# TODO: this causes deadlock
68+
# async def test_direct_shutdown_request(ipkernel):
69+
# reply = await ipkernel.test_shell_message("shutdown_request", dict(restart=False))
70+
# assert reply["header"]["msg_type"] == "shutdown_reply"
71+
# reply = await ipkernel.test_shell_message("shutdown_request", dict(restart=True))
72+
# assert reply["header"]["msg_type"] == "shutdown_reply"
73+
74+
# TODO: this causes deadlock
75+
# async def test_direct_usage_request(kernel):
76+
# reply = await kernel.test_control_message("usage_request", {})
77+
# assert reply['header']['msg_type'] == 'usage_reply'
78+
79+
80+
async def test_is_complete_request(ipkernel):
81+
reply = await ipkernel.test_shell_message("is_complete_request", dict(code="hello"))
82+
assert reply["header"]["msg_type"] == "is_complete_reply"
83+
84+
85+
async def test_direct_debug_request(ipkernel):
86+
reply = await ipkernel.test_control_message("debug_request", {})
87+
assert reply["header"]["msg_type"] == "debug_reply"
88+
89+
90+
async def test_direct_clear(ipkernel):
91+
ipkernel.do_clear()
92+
93+
94+
async def test_cancel_on_sigint(ipkernel: IPythonKernel):
95+
future = asyncio.Future()
96+
with ipkernel._cancel_on_sigint(future):
97+
pass
98+
future.set_result(None)

pyproject.toml

Lines changed: 9 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -55,6 +55,13 @@ test = [
5555
"pytest-asyncio",
5656
"pytest-timeout"
5757
]
58+
cov = [
59+
"coverage[toml]",
60+
"pytest-cov",
61+
"matplotlib",
62+
"curio",
63+
"trio",
64+
]
5865

5966
[tool.hatch.version]
6067
path = "ipykernel/_version.py"
@@ -80,8 +87,7 @@ test = "python -m pytest -vv {args}"
8087
nowarn = "test -W default {args}"
8188

8289
[tool.hatch.envs.cov]
83-
features = ["test"]
84-
dependencies = ["coverage[toml]", "pytest-cov", "matplotlib", "curio", "trio"]
90+
features = ["test", "cov"]
8591
[tool.hatch.envs.cov.scripts]
8692
test = "python -m pytest -vv --cov ipykernel --cov-branch --cov-report term-missing:skip-covered {args}"
8793
nowarn = "test -W default {args}"
@@ -148,6 +154,7 @@ omit = [
148154
"ipykernel/tests/*",
149155
"ipykernel/debugger.py",
150156
"ipykernel/eventloops.py",
157+
"ipykernel/pickleutil.py"
151158
]
152159

153160
[tool.flake8]

0 commit comments

Comments
 (0)