Skip to content

Commit 5a68cb3

Browse files
Drop Python 3.8, test PyPy 3.10 (#323)
* Drop Python 3.8, test PyPy 3.10 * Fix lint * Require nbconvert>=7.1.0 in tests * Fix tests * Skip test Interrupt.ipynb on PyPy
1 parent a6628b8 commit 5a68cb3

File tree

5 files changed

+20
-16
lines changed

5 files changed

+20
-16
lines changed

.github/workflows/main.yml

Lines changed: 2 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -42,16 +42,10 @@ jobs:
4242
fail-fast: false
4343
matrix:
4444
os: ["ubuntu-latest", "macos-latest", "windows-latest"]
45-
python-version: ["3.8", "3.11"]
45+
python-version: ["3.9", "3.10", "3.11", "3.12", "3.13"]
4646
include:
47-
- os: windows-latest
48-
python-version: "3.9"
4947
- os: ubuntu-latest
50-
python-version: "pypy-3.8"
51-
- os: ubuntu-latest
52-
python-version: "3.12"
53-
- os: macos-latest
54-
python-version: "3.10"
48+
python-version: "pypy-3.10"
5549
steps:
5650
- name: Checkout
5751
uses: actions/checkout@v4

nbclient/_version.py

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,14 +1,15 @@
11
"""Version info."""
2+
from __future__ import annotations
3+
24
import re
3-
from typing import List, Union
45

56
__version__ = "0.10.1"
67

78
# Build up version_info tuple for backwards compatibility
89
pattern = r"(?P<major>\d+).(?P<minor>\d+).(?P<patch>\d+)(?P<rest>.*)"
910
match = re.match(pattern, __version__)
1011
if match:
11-
parts: List[Union[int, str]] = [int(match[part]) for part in ["major", "minor", "patch"]]
12+
parts: list[int | str] = [int(match[part]) for part in ["major", "minor", "patch"]]
1213
if match["rest"]:
1314
parts.append(match["rest"])
1415
else:

pyproject.toml

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,7 @@ dynamic = [
1212
description = "A client library for executing notebooks. Formerly nbconvert's ExecutePreprocessor."
1313
readme = "README.md"
1414
license = { file = "LICENSE" }
15-
requires-python = ">=3.8.0"
15+
requires-python = ">=3.9.0"
1616
authors = [
1717
{ name = "Jupyter Development Team", email = "[email protected]" },
1818
]
@@ -29,10 +29,11 @@ classifiers = [
2929
"License :: OSI Approved :: BSD License",
3030
"Programming Language :: Python",
3131
"Programming Language :: Python :: 3",
32-
"Programming Language :: Python :: 3.8",
3332
"Programming Language :: Python :: 3.9",
3433
"Programming Language :: Python :: 3.10",
3534
"Programming Language :: Python :: 3.11",
35+
"Programming Language :: Python :: 3.12",
36+
"Programming Language :: Python :: 3.13",
3637
]
3738
dependencies = [
3839
"jupyter_client>=6.1.12",
@@ -47,7 +48,7 @@ test = [
4748
"ipykernel>=6.19.3",
4849
"ipython",
4950
"ipywidgets",
50-
"nbconvert>=7.0.0",
51+
"nbconvert>=7.1.0",
5152
"pytest-asyncio",
5253
"pytest-cov>=4.0",
5354
"pytest>=7.0,<8",

tests/test_cli.py

Lines changed: 8 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,4 @@
1+
import sys
12
from pathlib import Path
23
from subprocess import CalledProcessError, check_output
34
from unittest.mock import call, mock_open, patch
@@ -6,6 +7,11 @@
67

78
from nbclient.cli import NbClientApp
89

10+
if sys.version_info >= (3, 13):
11+
PATH_OPEN_CALL_STEP = 4
12+
else:
13+
PATH_OPEN_CALL_STEP = 3
14+
915
current_dir = Path(__file__).parent.absolute()
1016

1117

@@ -60,7 +66,7 @@ def test_mult(input_names, relative, inplace, jupyterapp, client, reader, writer
6066
# add suffix if needed
6167
paths = [p.with_suffix(".ipynb") for p in paths]
6268

63-
assert path_open.mock_calls[::3] == [call(p) for p in paths]
69+
assert path_open.mock_calls[::PATH_OPEN_CALL_STEP] == [call(p) for p in paths]
6470
assert reader.call_count == len(paths)
6571
# assert reader.mock_calls == [call(p, as_version=4) for p in paths]
6672

@@ -114,7 +120,7 @@ def test_output(input_names, relative, output_base, jupyterapp, client, reader,
114120
# add suffix if needed
115121
paths = [p.with_suffix(".ipynb") for p in paths]
116122

117-
assert path_open.mock_calls[::3] == [call(p) for p in paths]
123+
assert path_open.mock_calls[::PATH_OPEN_CALL_STEP] == [call(p) for p in paths]
118124
assert reader.call_count == len(paths)
119125

120126
expected = []

tests/test_client.py

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,7 @@
1111
import threading
1212
import warnings
1313
from base64 import b64decode, b64encode
14+
from platform import python_implementation
1415
from queue import Empty
1516
from typing import Any
1617
from unittest.mock import MagicMock, Mock
@@ -325,14 +326,15 @@ def filter_messages_on_error_output(err_output):
325326
("Factorials.ipynb", {"kernel_name": "python"}),
326327
("HelloWorld.ipynb", {"kernel_name": "python"}),
327328
("Inline Image.ipynb", {"kernel_name": "python"}),
328-
(
329+
pytest.param(
329330
"Interrupt.ipynb",
330331
{
331332
"kernel_name": "python",
332333
"timeout": 3,
333334
"interrupt_on_timeout": True,
334335
"allow_errors": True,
335336
},
337+
marks=pytest.mark.skipif(python_implementation() == "PyPy", reason="PyPy hangs"),
336338
),
337339
("JupyterWidgets.ipynb", {"kernel_name": "python"}),
338340
("Skip Exceptions with Cell Tags.ipynb", {"kernel_name": "python"}),

0 commit comments

Comments
 (0)