diff --git a/.github/actions/create-dev-env/action.yml b/.github/actions/create-dev-env/action.yml index c7b008b8..1a0e6221 100644 --- a/.github/actions/create-dev-env/action.yml +++ b/.github/actions/create-dev-env/action.yml @@ -7,7 +7,7 @@ runs: - name: Set Up Python 🐍 uses: actions/setup-python@v5 with: - python-version: "3.12" + python-version: 3.12 - name: Install Dev Dependencies 📦 run: | diff --git a/.github/workflows/pre-commit.yml b/.github/workflows/pre-commit.yml index 42c9b837..76f38132 100644 --- a/.github/workflows/pre-commit.yml +++ b/.github/workflows/pre-commit.yml @@ -21,7 +21,7 @@ jobs: - name: Set Up Python 🐍 uses: actions/setup-python@v5 with: - python-version: 3.x + python-version: 3.12 - name: Install pre-commit 📦 run: | diff --git a/.github/workflows/sphinx.yml b/.github/workflows/sphinx.yml index e6211d16..63f44369 100644 --- a/.github/workflows/sphinx.yml +++ b/.github/workflows/sphinx.yml @@ -38,7 +38,7 @@ jobs: - name: Set Up Python 🐍 uses: actions/setup-python@v5 with: - python-version: 3.9 + python-version: 3.12 - name: Install Doc Dependencies 📦 run: | diff --git a/.pre-commit-config.yaml b/.pre-commit-config.yaml index 57802ee1..43c3d17f 100644 --- a/.pre-commit-config.yaml +++ b/.pre-commit-config.yaml @@ -17,7 +17,7 @@ repos: rev: v3.19.1 hooks: - id: pyupgrade - args: [--py39-plus] + args: [--py312-plus] # Automatically sort python imports - repo: https://github.com/PyCQA/isort @@ -31,7 +31,7 @@ repos: rev: 25.1.0 hooks: - id: black - args: [--target-version=py39] + args: [--target-version=py312] # Check python code static typing - repo: https://github.com/pre-commit/mirrors-mypy @@ -141,10 +141,10 @@ repos: rev: 1.9.1 hooks: - id: nbqa-pyupgrade - args: [--py39-plus] + args: [--py312-plus] - id: nbqa-isort - id: nbqa-black - args: [--target-version=py39] + args: [--target-version=py312] - id: nbqa-flake8 # Run black on python code blocks in documentation files. @@ -156,7 +156,7 @@ repos: # the python code blocks include jupyter-specific additions such as % or ! # See https://github.com/adamchainz/blacken-docs/issues/127 for an upstream # feature request about this. - args: [--target-version=py39, --skip-errors] + args: [--target-version=py312, --skip-errors] # pre-commit.ci config reference: https://pre-commit.ci/#configuration ci: diff --git a/CHANGELOG.md b/CHANGELOG.md index 80082eeb..8a1d239e 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -11,6 +11,7 @@ Affected: all images. - **Non-breaking:** don't create extra free space in runners for cuda images ([#2218](https://github.com/jupyter/docker-stacks/pull/2218)). - **Non-breaking:** revert "Pin some packages to fix `r-notebook` and `datascience-notebook` under aarch64" ([#2220](https://github.com/jupyter/docker-stacks/pull/2220)). - **Non-breaking:** Simplify and improve `test_packages.py` ([#2219](https://github.com/jupyter/docker-stacks/pull/2219)). +- **Non-breaking:** Use Python 3.12 for internal code ([#2222](https://github.com/jupyter/docker-stacks/pull/2222)). ## 2025-02-17 diff --git a/mypy.ini b/mypy.ini index 3e20bf5b..c2ea66fa 100644 --- a/mypy.ini +++ b/mypy.ini @@ -8,7 +8,7 @@ # We use mypy as part of pre-commit checks [mypy] -python_version = 3.9 +python_version = 3.12 follow_imports = error strict = True no_incremental = True diff --git a/tagging/docker_runner.py b/tagging/docker_runner.py index 9d71f27b..c2020109 100644 --- a/tagging/docker_runner.py +++ b/tagging/docker_runner.py @@ -2,7 +2,6 @@ # Distributed under the terms of the Modified BSD License. import logging from types import TracebackType -from typing import Optional import docker from docker.models.containers import Container @@ -17,7 +16,7 @@ class DockerRunner: docker_client: docker.DockerClient = docker.from_env(), command: str = "sleep infinity", ): - self.container: Optional[Container] = None + self.container: Container | None = None self.image_name: str = image_name self.command: str = command self.docker_client: docker.DockerClient = docker_client @@ -34,9 +33,9 @@ class DockerRunner: def __exit__( self, - exc_type: Optional[type[BaseException]], - exc_val: Optional[BaseException], - exc_tb: Optional[TracebackType], + exc_type: type[BaseException] | None, + exc_val: BaseException | None, + exc_tb: TracebackType | None, ) -> None: assert self.container is not None LOGGER.info(f"Removing container {self.container.name} ...") diff --git a/tagging/get_taggers_and_manifests.py b/tagging/get_taggers_and_manifests.py index d41d7a86..3c39b532 100644 --- a/tagging/get_taggers_and_manifests.py +++ b/tagging/get_taggers_and_manifests.py @@ -1,6 +1,5 @@ # Copyright (c) Jupyter Development Team. # Distributed under the terms of the Modified BSD License. -from typing import Optional from tagging.images_hierarchy import ALL_IMAGES from tagging.manifests import ManifestInterface @@ -8,7 +7,7 @@ from tagging.taggers import TaggerInterface def get_taggers_and_manifests( - short_image_name: Optional[str], + short_image_name: str | None, ) -> tuple[list[TaggerInterface], list[ManifestInterface]]: if short_image_name is None: return [[], []] # type: ignore diff --git a/tagging/images_hierarchy.py b/tagging/images_hierarchy.py index 8c3e3fd3..3a15faa0 100644 --- a/tagging/images_hierarchy.py +++ b/tagging/images_hierarchy.py @@ -1,7 +1,6 @@ # Copyright (c) Jupyter Development Team. # Distributed under the terms of the Modified BSD License. from dataclasses import dataclass, field -from typing import Optional from tagging.manifests import ( AptPackagesManifest, @@ -32,7 +31,7 @@ from tagging.taggers import ( @dataclass class ImageDescription: - parent_image: Optional[str] + parent_image: str | None taggers: list[TaggerInterface] = field(default_factory=list) manifests: list[ManifestInterface] = field(default_factory=list) diff --git a/tests/base-notebook/test_healthcheck.py b/tests/base-notebook/test_healthcheck.py index 36a8a4dc..c3684b18 100644 --- a/tests/base-notebook/test_healthcheck.py +++ b/tests/base-notebook/test_healthcheck.py @@ -2,7 +2,6 @@ # Distributed under the terms of the Modified BSD License. import logging import time -from typing import Optional import pytest # type: ignore @@ -56,9 +55,9 @@ LOGGER = logging.getLogger(__name__) ) def test_healthy( container: TrackedContainer, - env: Optional[list[str]], - cmd: Optional[list[str]], - user: Optional[str], + env: list[str] | None, + cmd: list[str] | None, + user: str | None, ) -> None: running_container = container.run_detached( tty=True, @@ -104,9 +103,9 @@ def test_healthy( ) def test_healthy_with_proxy( container: TrackedContainer, - env: Optional[list[str]], - cmd: Optional[list[str]], - user: Optional[str], + env: list[str] | None, + cmd: list[str] | None, + user: str | None, ) -> None: running_container = container.run_detached( tty=True, @@ -142,8 +141,8 @@ def test_healthy_with_proxy( ) def test_not_healthy( container: TrackedContainer, - env: Optional[list[str]], - cmd: Optional[list[str]], + env: list[str] | None, + cmd: list[str] | None, ) -> None: running_container = container.run_detached( tty=True, diff --git a/tests/base-notebook/test_start_container.py b/tests/base-notebook/test_start_container.py index 729e7cac..e938f78a 100644 --- a/tests/base-notebook/test_start_container.py +++ b/tests/base-notebook/test_start_container.py @@ -2,7 +2,6 @@ # Distributed under the terms of the Modified BSD License. import logging import time -from typing import Optional import pytest # type: ignore import requests @@ -32,7 +31,7 @@ LOGGER = logging.getLogger(__name__) def test_start_notebook( container: TrackedContainer, http_client: requests.Session, - env: Optional[list[str]], + env: list[str] | None, expected_command: str, expected_start: bool, expected_warnings: list[str], diff --git a/tests/conftest.py b/tests/conftest.py index 1df04b60..6df248a5 100644 --- a/tests/conftest.py +++ b/tests/conftest.py @@ -4,7 +4,7 @@ import logging import os import socket from contextlib import closing -from typing import Any, Optional +from typing import Any import docker import pytest # type: ignore @@ -72,7 +72,7 @@ class TrackedContainer: image_name: str, **kwargs: Any, ): - self.container: Optional[Container] = None + self.container: Container | None = None self.docker_client: docker.DockerClient = docker_client self.image_name: str = image_name self.kwargs: Any = kwargs diff --git a/tests/docker-stacks-foundation/test_packages.py b/tests/docker-stacks-foundation/test_packages.py index f68d6ec9..d2d2f193 100644 --- a/tests/docker-stacks-foundation/test_packages.py +++ b/tests/docker-stacks-foundation/test_packages.py @@ -40,8 +40,7 @@ Example: """ import logging -from collections.abc import Iterable -from typing import Callable +from collections.abc import Callable, Iterable import pytest # type: ignore diff --git a/tests/images_hierarchy.py b/tests/images_hierarchy.py index 193ec270..df583bd9 100644 --- a/tests/images_hierarchy.py +++ b/tests/images_hierarchy.py @@ -1,7 +1,6 @@ # Copyright (c) Jupyter Development Team. # Distributed under the terms of the Modified BSD License. from pathlib import Path -from typing import Optional THIS_DIR = Path(__file__).parent.resolve() @@ -23,7 +22,7 @@ ALL_IMAGES = { def get_test_dirs( - short_image_name: Optional[str], + short_image_name: str | None, ) -> list[Path]: if short_image_name is None: return [] diff --git a/tests/package_helper.py b/tests/package_helper.py index 6c5930b7..b5e0e415 100644 --- a/tests/package_helper.py +++ b/tests/package_helper.py @@ -27,7 +27,7 @@ import logging import re from collections import defaultdict from itertools import chain -from typing import Any, Optional +from typing import Any from docker.models.containers import Container from tabulate import tabulate @@ -44,9 +44,9 @@ class CondaPackageHelper: self.running_container: Container = CondaPackageHelper.start_container( container ) - self.requested: Optional[dict[str, set[str]]] = None - self.installed: Optional[dict[str, set[str]]] = None - self.available: Optional[dict[str, set[str]]] = None + self.requested: dict[str, set[str]] | None = None + self.installed: dict[str, set[str]] | None = None + self.available: dict[str, set[str]] | None = None self.comparison: list[dict[str, str]] = [] @staticmethod