diff --git a/.github/workflows/python.yml b/.github/workflows/python.yml index c7602893..c0efd0c4 100644 --- a/.github/workflows/python.yml +++ b/.github/workflows/python.yml @@ -50,7 +50,7 @@ jobs: strategy: matrix: os: [ubuntu-latest, ubuntu-24.04-arm, macos-latest] - python-version: ["3.10", "3.11", "3.12", "3.13", "3.13t", "3.14", "3.14t", "3.15", "3.15t"] + python-version: ["3.11", "3.12", "3.13", "3.13t", "3.14", "3.14t", "3.15", "3.15t"] openslide: [system, wheel] include: - os: ubuntu-latest @@ -170,7 +170,7 @@ jobs: shell: bash strategy: matrix: - python-version: ["3.10", "3.11", "3.12", "3.13", "3.13t", "3.14", "3.14t", "3.15", "3.15t"] + python-version: ["3.11", "3.12", "3.13", "3.13t", "3.14", "3.14t", "3.15", "3.15t"] openslide: [zip, wheel] steps: - name: Check out repo @@ -238,27 +238,6 @@ jobs: path: artifacts/whl compression-level: 0 - setuptools: - name: Setuptools install - needs: pre-commit - runs-on: ubuntu-latest - container: ubuntu:22.04 - steps: - - name: Install dependencies - run: | - apt-get update - DEBIAN_FRONTEND=noninteractive apt-get install -y \ - git libopenslide0 python3-jinja2 python3-pil python3-pip - pip install pytest - - name: Check out repo - uses: actions/checkout@v7 - - name: Install OpenSlide Python - run: python3 setup.py install - - name: Run tests - run: pytest -v - - name: Tile slide - run: python3 examples/deepzoom/deepzoom_tile.py --viewer -o tiled tests/fixtures/small.svs - docs: name: Docs needs: pre-commit diff --git a/.pre-commit-config.yaml b/.pre-commit-config.yaml index d2c0fc91..f0cc91b2 100644 --- a/.pre-commit-config.yaml +++ b/.pre-commit-config.yaml @@ -40,7 +40,7 @@ repos: name: Check Python types priority: 0 # Pillow is ignored in dependabot.yml - additional_dependencies: [flask, openslide-bin, pillow >= 13.0.0, types-PyYAML, types-setuptools] + additional_dependencies: [flask, openslide-bin, pillow >= 12.1.0, types-PyYAML, types-setuptools] - repo: https://github.com/rstcheck/rstcheck rev: v6.3.0 @@ -56,8 +56,6 @@ repos: - id: codespell name: Check spelling with codespell priority: 0 - additional_dependencies: - - tomli # Python < 3.11 - repo: meta hooks: diff --git a/README.md b/README.md index e9e21352..a6652ee7 100644 --- a/README.md +++ b/README.md @@ -45,7 +45,7 @@ OpenSlide can read virtual slides in several formats: ## Requirements -* Python ≥ 3.10 +* Python ≥ 3.11 * OpenSlide ≥ 3.4.0 * Pillow diff --git a/openslide/__init__.py b/openslide/__init__.py index f8c6e367..b4dd5deb 100644 --- a/openslide/__init__.py +++ b/openslide/__init__.py @@ -28,7 +28,7 @@ from collections.abc import Iterator, Mapping from io import BytesIO from types import TracebackType -from typing import Literal, TypeVar +from typing import Literal, Self, TypeVar from PIL import Image, ImageCms @@ -66,7 +66,7 @@ class AbstractSlide(metaclass=ABCMeta): def __init__(self) -> None: self._profile: bytes | None = None - def __enter__(self: _T) -> _T: + def __enter__(self) -> Self: return self def __exit__( @@ -178,9 +178,7 @@ def get_thumbnail(self, size: tuple[int, int]) -> Image.Image: bg_color = '#' + self.properties.get(PROPERTY_NAME_BACKGROUND_COLOR, 'ffffff') thumb = Image.new('RGB', tile.size, bg_color) thumb.paste(tile, None, tile) - # Image.Resampling added in Pillow 9.1.0 - # Image.LANCZOS removed in Pillow 10 - thumb.thumbnail(size, getattr(Image, 'Resampling', Image).LANCZOS) + thumb.thumbnail(size, Image.Resampling.LANCZOS) if self._profile is not None: thumb.info['icc_profile'] = self._profile return thumb @@ -392,8 +390,7 @@ def detect_format(cls, filename: lowlevel.Filename) -> str | None: If the file format is not recognized, return None.""" try: with Image.open(filename) as img: - # mypy will think img is Any until we drop Python 3.10 - return img.format # type: ignore[no-any-return] + return img.format except OSError: return None diff --git a/openslide/deepzoom.py b/openslide/deepzoom.py index 9eb89dea..afa5bf6d 100644 --- a/openslide/deepzoom.py +++ b/openslide/deepzoom.py @@ -185,9 +185,7 @@ def get_tile(self, level: int, address: tuple[int, int]) -> Image.Image: # Scale to the correct size if tile.size != z_size: - # Image.Resampling added in Pillow 9.1.0 - # Image.LANCZOS removed in Pillow 10 - tile.thumbnail(z_size, getattr(Image, 'Resampling', Image).LANCZOS) + tile.thumbnail(z_size, Image.Resampling.LANCZOS) # Reference ICC profile if profile is not None: diff --git a/pyproject.toml b/pyproject.toml index 532231ff..01891899 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -18,7 +18,6 @@ classifiers = [ "Operating System :: POSIX :: Linux", "Programming Language :: Python", "Programming Language :: Python :: 3", - "Programming Language :: Python :: 3.10", "Programming Language :: Python :: 3.11", "Programming Language :: Python :: 3.12", "Programming Language :: Python :: 3.13", @@ -28,7 +27,7 @@ classifiers = [ "Topic :: Scientific/Engineering :: Bio-Informatics", "Typing :: Typed", ] -requires-python = ">= 3.10" +requires-python = ">= 3.11" dependencies = ["Pillow"] dynamic = ["version"] @@ -58,7 +57,7 @@ check-hidden = true # ignore-words-list = "" [tool.mypy] -python_version = "3.10" +python_version = "3.11" strict = true [tool.pytest.ini_options] diff --git a/setup.py b/setup.py index dbdca38d..21c75f6f 100644 --- a/setup.py +++ b/setup.py @@ -1,18 +1,13 @@ -from pathlib import Path import sys import sysconfig from setuptools import Extension, setup from setuptools import __version__ as _setuptools_ver -# Load version string -with open(Path(__file__).parent / 'openslide/_version.py') as _fh: - exec(_fh.read()) # instantiates __version__ # noqa: S102 - # Use the free-threaded Stable ABI (abi3t) only on free-threaded Python # 3.15+ with setuptools 84.2+; Python supports building abi3t from # GIL-enabled interpreters but setuptools doesn't yet. Use the -# non-free-threaded Stable API (abi3) on Python 3.11+ with GIL enabled, and +# non-free-threaded Stable API (abi3) with GIL enabled, and # release-specific wheels in all other cases. _freethread = sysconfig.get_config_var('Py_GIL_DISABLED') _abi3t = ( @@ -20,7 +15,7 @@ and _freethread and tuple(int(c) for c in _setuptools_ver.split('.')) >= (84, 2) ) -_abi3 = sys.version_info >= (3, 11) and not _freethread +_abi3 = not _freethread setup( ext_modules=[ @@ -45,18 +40,4 @@ if _abi3 else {}, }, - # - # setuptools < 61 compatibility for distro packages building from source - name='openslide-python', - version=__version__, # type: ignore[name-defined] # noqa: F821 - install_requires=[ - 'Pillow', - ], - packages=[ - 'openslide', - ], - package_data={ - 'openslide': ['py.typed', '*.pyi'], - }, - zip_safe=False, )