diff --git a/.github/workflows/main.yml b/.github/workflows/main.yml index 4f846b5..d214686 100644 --- a/.github/workflows/main.yml +++ b/.github/workflows/main.yml @@ -20,7 +20,7 @@ jobs: fail-fast: false matrix: os: [ubuntu-latest, macos-latest, windows-latest] - python-version: [ '3.10', '3.11', '3.12', '3.13', '3.14' ] + python-version: [ '3.11', '3.12', '3.13', '3.14', '3.15' ] steps: - name: Checkout @@ -30,6 +30,7 @@ jobs: uses: actions/setup-python@v5 with: python-version: ${{ matrix.python-version }} + allow-prereleases: true - name: Install akernel run: | diff --git a/plugins/akernel_task/pyproject.toml b/plugins/akernel_task/pyproject.toml index 60b37c6..4187af1 100644 --- a/plugins/akernel_task/pyproject.toml +++ b/plugins/akernel_task/pyproject.toml @@ -7,7 +7,7 @@ name = "fps_akernel_task" version = "0.2.1" description = "An FPS plugin for the kernel task API" keywords = ["jupyter", "server", "fastapi", "plugins"] -requires-python = ">=3.10" +requires-python = ">=3.11" dependencies = [ "jupyverse-api >=0.15.0,<0.16.0", "anyio", @@ -31,3 +31,7 @@ Homepage = "https://github.com/davidbrochart/akernel" [project.entry-points] "fps.modules" = {akernel_task = "fps_akernel_task.main:AKernelTaskModule", akernelthread_task = "fps_akernel_task.main:AKernelThreadTaskModule"} "jupyverse.modules" = {akernel_task = "fps_akernel_task.main:AKernelTaskModule", akernelthread_task = "fps_akernel_task.main:AKernelThreadTaskModule"} + +[tool.hatch.build.targets.wheel.shared-data] +"share/jupyter/kernels/akernel-task/kernel.json" = "share/jupyter/kernels/akernel-task/kernel.json" +"share/jupyter/kernels/akernel-thread/kernel.json" = "share/jupyter/kernels/akernel-thread/kernel.json" diff --git a/share/jupyter/kernels/akernel-task/kernel.json b/plugins/akernel_task/share/jupyter/kernels/akernel-task/kernel.json similarity index 100% rename from share/jupyter/kernels/akernel-task/kernel.json rename to plugins/akernel_task/share/jupyter/kernels/akernel-task/kernel.json diff --git a/share/jupyter/kernels/akernel-thread/kernel.json b/plugins/akernel_task/share/jupyter/kernels/akernel-thread/kernel.json similarity index 100% rename from share/jupyter/kernels/akernel-thread/kernel.json rename to plugins/akernel_task/share/jupyter/kernels/akernel-thread/kernel.json diff --git a/pyproject.toml b/pyproject.toml index c8fe245..6f07115 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -8,16 +8,16 @@ version = "0.4.1" description = "An asynchronous Python Jupyter kernel" readme = "README.md" license = {text = "MIT"} -requires-python = ">=3.10" +requires-python = ">=3.11" authors = [{name = "David Brochart", email = "david.brochart@gmail.com"}] classifiers = [ "Development Status :: 4 - Beta", "Programming Language :: Python", - "Programming Language :: Python :: 3.10", "Programming Language :: Python :: 3.11", "Programming Language :: Python :: 3.12", "Programming Language :: Python :: 3.13", "Programming Language :: Python :: 3.14", + "Programming Language :: Python :: 3.15", "Programming Language :: Python :: Implementation :: CPython", "Programming Language :: Python :: Implementation :: PyPy", ] @@ -57,8 +57,6 @@ packages = ["src/akernel"] [tool.hatch.build.targets.wheel.shared-data] "share/jupyter/kernels/akernel/kernel.json" = "share/jupyter/kernels/akernel/kernel.json" -"share/jupyter/kernels/akernel-task/kernel.json" = "share/jupyter/kernels/akernel-task/kernel.json" -"share/jupyter/kernels/akernel-thread/kernel.json" = "share/jupyter/kernels/akernel-thread/kernel.json" [project.urls] Homepage = "https://github.com/davidbrochart/akernel" diff --git a/src/akernel/message.py b/src/akernel/message.py index b30a78a..0a5d49d 100644 --- a/src/akernel/message.py +++ b/src/akernel/message.py @@ -4,7 +4,7 @@ import hmac import json import uuid -from datetime import datetime, timezone +from datetime import UTC, datetime from typing import Any, cast from dateutil.parser import parse as dateutil_parse # type: ignore @@ -22,7 +22,7 @@ def date_to_str(obj: dict[str, Any]): def utcnow() -> datetime: - return datetime.now(timezone.utc) + return datetime.now(UTC) def feed_identities(msg_list: list[bytes]) -> tuple[list[bytes], list[bytes]]: diff --git a/tests/test_jupyter_interrupt.py b/tests/test_jupyter_interrupt.py index f23f3b4..1a81550 100644 --- a/tests/test_jupyter_interrupt.py +++ b/tests/test_jupyter_interrupt.py @@ -121,6 +121,8 @@ async def test_jupyter_interrupt_preserves_kernel( root = tmp_path else: root = Path(__file__).resolve().parents[1] + if execute_in_thread: + root /= "plugins/akernel_task" spec_path = root / "share" / "jupyter" / "kernels" / name / "kernel.json" spec = json.loads(spec_path.read_text()) # Use this interpreter and checkout while retaining the shipped launch options. diff --git a/tests/test_kernelspec.py b/tests/test_kernelspec.py index c750370..1c1ac63 100644 --- a/tests/test_kernelspec.py +++ b/tests/test_kernelspec.py @@ -22,7 +22,10 @@ def test_install_matches_packaged_kernelspec(tmp_path, monkeypatch, options, nam app(["install", *options], result_action="return_value") relative_path = Path("share/jupyter/kernels") / name / "kernel.json" installed = json.loads((tmp_path / relative_path).read_text()) - packaged = json.loads((Path(__file__).resolve().parents[1] / relative_path).read_text()) + package_root = Path(__file__).resolve().parents[1] + if name != "akernel": + package_root /= "plugins/akernel_task" + packaged = json.loads((package_root / relative_path).read_text()) assert installed == packaged assert installed["display_name"] == f"Python 3 ({name})" assert installed["interrupt_mode"] == interrupt_mode