diff --git a/.github/workflows/docker-publish.yml b/.github/workflows/docker-publish.yml index 7aba703bd..a804a6eea 100644 --- a/.github/workflows/docker-publish.yml +++ b/.github/workflows/docker-publish.yml @@ -15,10 +15,6 @@ jobs: fail-fast: true matrix: include: - - dockerfile: ./docker/3.10/Debian/Dockerfile - mtag: py3.10-debian - - dockerfile: ./docker/3.10/Ubuntu/Dockerfile - mtag: py3.10-ubuntu - dockerfile: ./docker/3.11/Debian/Dockerfile mtag: py3.11-debian - dockerfile: ./docker/3.11/Ubuntu/Dockerfile diff --git a/.github/workflows/mypy-type-check.yml b/.github/workflows/mypy-type-check.yml index 26b997c6c..51d80c8dc 100644 --- a/.github/workflows/mypy-type-check.yml +++ b/.github/workflows/mypy-type-check.yml @@ -18,7 +18,7 @@ jobs: strategy: matrix: - python-version: ["3.10", "3.11", "3.12", "3.13"] + python-version: ["3.11", "3.12", "3.13"] steps: diff --git a/.github/workflows/pip-install.yml b/.github/workflows/pip-install.yml index 03ab1b823..efaf7cdad 100644 --- a/.github/workflows/pip-install.yml +++ b/.github/workflows/pip-install.yml @@ -31,7 +31,7 @@ jobs: strategy: fail-fast: false matrix: - python-version: ["3.10", "3.11", "3.12", "3.13"] + python-version: ["3.11", "3.12", "3.13"] os: [ubuntu-24.04, windows-latest, macos-latest] # Force UTF-8 everywhere (Windows is the one that really needs it) diff --git a/.github/workflows/python-package.yml b/.github/workflows/python-package.yml index 6146e333f..57ed77a00 100644 --- a/.github/workflows/python-package.yml +++ b/.github/workflows/python-package.yml @@ -20,7 +20,7 @@ jobs: strategy: fail-fast: true matrix: - python-version: ["3.10", "3.11", "3.12", "3.13"] + python-version: ["3.11", "3.12", "3.13"] steps: - uses: actions/checkout@v4 @@ -101,10 +101,10 @@ jobs: steps: - uses: actions/checkout@v4 - - name: Set up Python 3.10 + - name: Set up Python 3.11 uses: actions/setup-python@v4 with: - python-version: '3.10' + python-version: '3.11' cache: 'pip' - name: Install dependencies diff --git a/CONTRIBUTING.rst b/CONTRIBUTING.rst index eaaf6f3d7..53479d46e 100644 --- a/CONTRIBUTING.rst +++ b/CONTRIBUTING.rst @@ -98,7 +98,7 @@ Before you submit a pull request, check that it meets these guidelines: 1. The pull request should include tests. 2. If the pull request adds functionality, the docs should be updated. Put your new functionality into a function with a docstring, and add the feature to the pull request description. -3. The pull request should work for Python 3.10, 3.11, 3.12 and 3.13, and for PyPy. Check https://github.com/TissueImageAnalytics/tiatoolbox/actions/workflows/python-package.yml and make sure that the tests pass for all supported Python versions. +3. The pull request should work for Python 3.11, 3.12, and 3.13 and for PyPy. Check https://github.com/TissueImageAnalytics/tiatoolbox/actions/workflows/python-package.yml and make sure that the tests pass for all supported Python versions. Tips ---- diff --git a/README.md b/README.md index 117c486ea..711ef4e75 100644 --- a/README.md +++ b/README.md @@ -106,7 +106,7 @@ Prepare a computer as a convenient platform for further development of the Pytho 5. Create virtual environment for TIAToolbox using ```sh - $ conda create -n tiatoolbox-dev python=3.10 # select version of your choice + $ conda create -n tiatoolbox-dev python=3.11 # select version of your choice $ conda activate tiatoolbox-dev $ pip install -r requirements/requirements_dev.txt ``` diff --git a/docker/3.10/Debian/Dockerfile b/docker/3.10/Debian/Dockerfile deleted file mode 100644 index 8b5158760..000000000 --- a/docker/3.10/Debian/Dockerfile +++ /dev/null @@ -1,15 +0,0 @@ -FROM python:3.10-slim-bullseye - -#get linux packages -RUN apt-get -y update && apt-get -y install --no-install-recommends \ - libopenjp2-7-dev libopenjp2-tools \ - sqlite3 libsqlite3-0 \ - libgl1 \ - libglib2.0-0 \ - build-essential \ - && pip3 --no-cache-dir install tiatoolbox \ - && apt-get clean \ - && rm -rf /var/lib/apt/lists/* - -# set the entry point to bash -ENTRYPOINT ["/bin/bash"] diff --git a/docker/3.10/Ubuntu/Dockerfile b/docker/3.10/Ubuntu/Dockerfile deleted file mode 100644 index 8b1721b9d..000000000 --- a/docker/3.10/Ubuntu/Dockerfile +++ /dev/null @@ -1,29 +0,0 @@ -FROM ubuntu:24.04 AS builder-image - -# To avoid tzdata blocking the build with frontend questions -ENV DEBIAN_FRONTEND=noninteractive - -# Install python3.10 -RUN apt-get update && \ - apt install software-properties-common -y &&\ - add-apt-repository ppa:deadsnakes/ppa -y && apt update &&\ - apt-get install -y --no-install-recommends python3.10-venv &&\ - apt-get install libpython3.10-dev -y &&\ - apt-get install python3.10-dev -y &&\ - apt-get install build-essential -y &&\ - apt-get clean && rm -rf /var/lib/apt/lists/* - -# Add env to PATH -RUN python3.10 -m venv /venv -ENV PATH=/venv/bin:$PATH - -# install TIAToolbox and its requirements -RUN apt-get update && apt-get install --no-install-recommends -y \ - libopenjp2-7-dev libopenjp2-tools \ - sqlite3 libsqlite3-0 \ - libgl1 \ - && apt-get clean && rm -rf /var/lib/apt/lists/* -RUN pip install --no-cache-dir tiatoolbox - -# activate virtual environment -ENV VIRTUAL_ENV=/venv diff --git a/docs/installation.rst b/docs/installation.rst index 6e79fea3f..77cce4c3f 100644 --- a/docs/installation.rst +++ b/docs/installation.rst @@ -59,7 +59,7 @@ MacPorts Installing Stable Release ========================= -Please note that TIAToolbox is tested for Python versions 3.10, 3.11, 3.12 and 3.13. +Please note that TIAToolbox is tested for Python versions 3.11, 3.12, and 3.13. Recommended ----------- diff --git a/pyproject.toml b/pyproject.toml index 28d32522d..a7da0c3c9 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -136,8 +136,8 @@ line-length = 88 # Allow unused variables when underscore-prefixed. lint.dummy-variable-rgx = "^(_+|(_+[a-zA-Z0-9_]*[a-zA-Z0-9]+?))$" -# Minimum Python version 3.10. -target-version = "py310" +# Minimum Python version 3.11. +target-version = "py311" [tool.ruff.lint.mccabe] # Unlike Flake8, default to a complexity level of 10. @@ -174,4 +174,4 @@ skip-magic-trailing-comma = false [tool.mypy] ignore_missing_imports = true -python_version = "3.10" +python_version = "3.11" diff --git a/requirements/requirements.conda.yml b/requirements/requirements.conda.yml index 7f41f83d7..e1160bf51 100644 --- a/requirements/requirements.conda.yml +++ b/requirements/requirements.conda.yml @@ -6,9 +6,8 @@ channels: - defaults dependencies: - cython - - openslide - pip>=20.0.2 - pixman>=0.39.0 - - python>=3.10, <=3.13 + - python>=3.11, <=3.13 - pip: - -r requirements.txt diff --git a/requirements/requirements.dev.conda.yml b/requirements/requirements.dev.conda.yml index 9787f66f2..fd8162d5b 100644 --- a/requirements/requirements.dev.conda.yml +++ b/requirements/requirements.dev.conda.yml @@ -6,9 +6,8 @@ channels: - defaults dependencies: - cython - - openslide - pip>=20.0.2 - pixman>=0.39.0 - - python>=3.10, <=3.13 + - python>=3.11, <=3.13 - pip: - -r requirements_dev.txt diff --git a/requirements/requirements.txt b/requirements/requirements.txt index edfa12f9c..754821393 100644 --- a/requirements/requirements.txt +++ b/requirements/requirements.txt @@ -29,7 +29,7 @@ scikit-learn>=1.2.0 scipy>=1.8 shapely>=2.0.0 SimpleITK>=2.2.1 -sphinx>=5.3.0 +sphinx>=5.3.0, <9.0.0 tifffile>=2022.10.10, <=2025.5.10 timm>=1.0.3 torch>=2.5.0 diff --git a/requirements/requirements.win64.conda.yml b/requirements/requirements.win64.conda.yml index d5e01a13b..3bf2d9484 100644 --- a/requirements/requirements.win64.conda.yml +++ b/requirements/requirements.win64.conda.yml @@ -9,6 +9,6 @@ dependencies: - openjpeg>=2.4.0 - pip>=20.0.2 - pixman>=0.39.0 - - python>=3.10, <=3.13 + - python>=3.11, <=3.13 - pip: - -r requirements.txt diff --git a/requirements/requirements.win64.dev.conda.yml b/requirements/requirements.win64.dev.conda.yml index 95404f4f5..48999206a 100644 --- a/requirements/requirements.win64.dev.conda.yml +++ b/requirements/requirements.win64.dev.conda.yml @@ -9,6 +9,6 @@ dependencies: - openjpeg>=2.4.0 - pip>=20.0.2 - pixman>=0.39.0 - - python>=3.10, <=3.13 + - python>=3.11, <=3.13 - pip: - -r requirements_dev.txt diff --git a/setup.py b/setup.py index 772e7c78a..8f2302e3f 100644 --- a/setup.py +++ b/setup.py @@ -34,13 +34,12 @@ setup( author="TIA Centre", author_email="TIA@warwick.ac.uk", - python_requires=">=3.10, <3.14", + python_requires=">=3.11, <3.14", classifiers=[ "Development Status :: 2 - Pre-Alpha", "Intended Audience :: Developers", "Natural Language :: English", "Programming Language :: Python :: 3", - "Programming Language :: Python :: 3.10", "Programming Language :: Python :: 3.11", "Programming Language :: Python :: 3.12", "Programming Language :: Python :: 3.13", diff --git a/tests/test_annotation_stores.py b/tests/test_annotation_stores.py index 636e3b7b4..a48463dc7 100644 --- a/tests/test_annotation_stores.py +++ b/tests/test_annotation_stores.py @@ -1827,13 +1827,13 @@ def test_load_cases_error( store._load_cases(["foo"], lambda: None, lambda: None) @staticmethod - def test_py310_init( + def test_py311_init( fill_store: Callable, # noqa: ARG004 store_cls: type[AnnotationStore], monkeypatch: object, ) -> None: - """Test that __init__ is compatible with Python 3.10.""" - py310_version = (3, 10, 0) + """Test that __init__ is compatible with Python 3.11.""" + py311_version = (3, 11, 0) class Connection(sqlite3.Connection): """Mock SQLite connection.""" @@ -1847,7 +1847,7 @@ def create_function( """Mock create_function without `deterministic` kwarg.""" return self.create_function(self, name, num_params) - monkeypatch.setattr(sys, "version_info", py310_version) + monkeypatch.setattr(sys, "version_info", py311_version) monkeypatch.setattr(sqlite3, "Connection", Connection) _ = store_cls() diff --git a/tiatoolbox/annotation/storage.py b/tiatoolbox/annotation/storage.py index 3b6bca565..3fc207639 100644 --- a/tiatoolbox/annotation/storage.py +++ b/tiatoolbox/annotation/storage.py @@ -58,6 +58,7 @@ TYPE_CHECKING, Any, ClassVar, + Self, TypeVar, cast, overload, @@ -72,7 +73,6 @@ from shapely.geometry import LineString, Point, Polygon from shapely.geometry import mapping as geometry2feature from shapely.geometry import shape as feature2geometry -from typing_extensions import Self import tiatoolbox from tiatoolbox import DuplicateFilter, logger diff --git a/tiatoolbox/wsicore/wsireader.py b/tiatoolbox/wsicore/wsireader.py index c971b7655..b6cd4374f 100644 --- a/tiatoolbox/wsicore/wsireader.py +++ b/tiatoolbox/wsicore/wsireader.py @@ -9,7 +9,7 @@ import os import re from collections import defaultdict -from datetime import datetime, timezone +from datetime import UTC, datetime from numbers import Number from pathlib import Path from typing import TYPE_CHECKING @@ -4681,14 +4681,14 @@ def us_date(string: str) -> datetime: """Return datetime parsed according to US date format (UTC-aware).""" # and we immediately attach UTC. dt = datetime.strptime(string, r"%m/%d/%y") # noqa: DTZ007 - return dt.replace(tzinfo=timezone.utc) + return dt.replace(tzinfo=UTC) def time(string: str) -> datetime: """Return datetime parsed according to HMS format (UTC-aware).""" # parse to time first; although .time() is tz-agnostic # DTZ007 is triggered by strptime t = datetime.strptime(string, r"%H:%M:%S").time() # noqa: DTZ007 - today_utc = datetime.now(timezone.utc) + today_utc = datetime.now(UTC) return today_utc.replace( hour=t.hour, minute=t.minute, second=t.second, microsecond=0 ) @@ -4698,7 +4698,7 @@ def time(string: str) -> datetime: for cast in casting_precedence: try: value = cast(value_string) - except ValueError: # noqa: PERF203 + except ValueError: continue else: return key, value