From affa8c80a3cc6ab02f6c8729510e2a5173a2ed28 Mon Sep 17 00:00:00 2001 From: jorenham Date: Tue, 27 Jan 2026 14:15:56 +0100 Subject: [PATCH 1/5] enable the mypy's strict mode --- pyproject.toml | 11 +++++------ 1 file changed, 5 insertions(+), 6 deletions(-) diff --git a/pyproject.toml b/pyproject.toml index e7adc432c86..c8f3de66664 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -195,17 +195,16 @@ exclude = [ "^Tests/images/picins/", "^Tests/images/sunraster/", ] -follow_imports = "silent" python_version = "3.11" -disallow_any_generics = true -disallow_untyped_defs = true -warn_redundant_casts = true -warn_unused_ignores = true +disallow_subclassing_any = false +disallow_untyped_calls = false +warn_return_any = false warn_unreachable = true enable_error_code = "ignore-without-code" -extra_checks = true +strict = true pretty = true num_workers = 4 +no_implicit_reexport = false [tool.pytest] addopts = [ "-ra", "--color=auto" ] From 02c5393ea9c9e30e9f795b644903302fed8394a1 Mon Sep 17 00:00:00 2001 From: jorenham Date: Tue, 27 Jan 2026 14:16:33 +0100 Subject: [PATCH 2/5] Fix mypy errors Co-authored-by: Andrew Murray <3112309+radarhere@users.noreply.github.com> Co-authored-by: Aarni Koskela --- src/PIL/EpsImagePlugin.py | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/src/PIL/EpsImagePlugin.py b/src/PIL/EpsImagePlugin.py index 5eaefe339a5..2973ae18838 100644 --- a/src/PIL/EpsImagePlugin.py +++ b/src/PIL/EpsImagePlugin.py @@ -209,7 +209,9 @@ def _open(self) -> None: imagedata_size: tuple[int, int] | None = None byte_arr = bytearray(255) - bytes_mv = memoryview(byte_arr) + # the extra `bytes` annotation here works around several false positive + # `comparison-overlap` mypy errors + bytes_mv: bytes | memoryview = memoryview(byte_arr) bytes_read = 0 reading_header_comments = True reading_trailer_comments = False From 4af4424b2db5ca11aa2e137cf4e5be528215e4f2 Mon Sep 17 00:00:00 2001 From: Aarni Koskela Date: Tue, 21 Jul 2026 08:23:50 +0300 Subject: [PATCH 3/5] Remove python_version mypy configuration; fix issues arising on 3.11-3.14 --- Tests/conftest.py | 4 ++-- pyproject.toml | 3 +-- src/PIL/GifImagePlugin.py | 5 +++-- 3 files changed, 6 insertions(+), 6 deletions(-) diff --git a/Tests/conftest.py b/Tests/conftest.py index 1f32bbedff3..9795375d9f8 100644 --- a/Tests/conftest.py +++ b/Tests/conftest.py @@ -10,7 +10,7 @@ gil_enabled_at_start = True if FREE_THREADED_BUILD: - gil_enabled_at_start = sys._is_gil_enabled() # type: ignore[attr-defined] + gil_enabled_at_start = sys._is_gil_enabled() # type: ignore[attr-defined,unused-ignore] def pytest_report_header(config: pytest.Config) -> str: @@ -28,7 +28,7 @@ def pytest_terminal_summary(terminalreporter: pytest.TerminalReporter) -> None: if ( FREE_THREADED_BUILD and not gil_enabled_at_start - and sys._is_gil_enabled() # type: ignore[attr-defined] + and sys._is_gil_enabled() # type: ignore[attr-defined,unused-ignore] ): tr = terminalreporter tr.ensure_newline() diff --git a/pyproject.toml b/pyproject.toml index c8f3de66664..add60dd94cb 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -195,7 +195,6 @@ exclude = [ "^Tests/images/picins/", "^Tests/images/sunraster/", ] -python_version = "3.11" disallow_subclassing_any = false disallow_untyped_calls = false warn_return_any = false @@ -203,8 +202,8 @@ warn_unreachable = true enable_error_code = "ignore-without-code" strict = true pretty = true -num_workers = 4 no_implicit_reexport = false +num_workers = 4 [tool.pytest] addopts = [ "-ra", "--color=auto" ] diff --git a/src/PIL/GifImagePlugin.py b/src/PIL/GifImagePlugin.py index 11fb180fc63..97e20c0495e 100644 --- a/src/PIL/GifImagePlugin.py +++ b/src/PIL/GifImagePlugin.py @@ -1203,8 +1203,9 @@ class Collector(BytesIO): data = [] def write(self, data: Buffer) -> int: - self.data.append(data) - return len(data) + data_bytes = bytes(data) + self.data.append(data_bytes) + return len(data_bytes) im.load() # make sure raster data is available From 7d39af34967fc65cdb921b3d4c5eb91440db2bce Mon Sep 17 00:00:00 2001 From: Andrew Murray Date: Mon, 17 Aug 2026 11:23:19 +1000 Subject: [PATCH 4/5] Test latest NumPy version on Python > 3.11 --- .ci/requirements-mypy.txt | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/.ci/requirements-mypy.txt b/.ci/requirements-mypy.txt index e2c99e5c602..ec1529fd4e5 100644 --- a/.ci/requirements-mypy.txt +++ b/.ci/requirements-mypy.txt @@ -4,7 +4,8 @@ arro3-core IceSpringPySideStubs-PyQt6 IceSpringPySideStubs-PySide6 ipython -numpy==2.4.6 +numpy==2.4.6;python_version=="3.11" +numpy;python_version>="3.12" packaging pyarrow-stubs pybind11 From d11ad9b5c6d2dbae286539409940081be7f3960d Mon Sep 17 00:00:00 2001 From: Aarni Koskela Date: Wed, 22 Jul 2026 08:35:48 +0300 Subject: [PATCH 5/5] CI: separate lint + mypy step; run mypy with all supported Python versions Co-authored-by: Andrew Murray <3112309+radarhere@users.noreply.github.com> --- .github/workflows/lint.yml | 20 +++++++++++++++++++- 1 file changed, 19 insertions(+), 1 deletion(-) diff --git a/.github/workflows/lint.yml b/.github/workflows/lint.yml index 0ef4abfacf6..37f3fa42d54 100644 --- a/.github/workflows/lint.yml +++ b/.github/workflows/lint.yml @@ -28,5 +28,23 @@ jobs: uses: astral-sh/setup-uv@20cfd1bf945f4377ade1205e4dbc17946fc9a30d # v10.0.1 - name: Lint run: uvx --with tox-uv tox -e lint + mypy: + runs-on: ubuntu-latest + strategy: + fail-fast: false + matrix: + python-version: [ + "3.14", + "3.13", + "3.12", + "3.11", + ] + name: Mypy + steps: + - uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1 + with: + persist-credentials: false + - name: Install uv + uses: astral-sh/setup-uv@20cfd1bf945f4377ade1205e4dbc17946fc9a30d # v10.0.1 - name: Mypy - run: uvx --with tox-uv tox -e mypy + run: uvx --python=${{ matrix.python-version }} --with tox-uv tox -e mypy