From 923d4e5e1a971ea64ce56c5b016a620be33d51eb Mon Sep 17 00:00:00 2001 From: Andrew Murray Date: Wed, 5 Jun 2024 22:27:23 +1000 Subject: [PATCH] Added type hints --- Tests/bench_cffi_access.py | 1 + Tests/test_features.py | 2 +- Tests/test_file_bmp.py | 2 +- Tests/test_file_bufrstub.py | 11 ++++++----- Tests/test_file_gribstub.py | 4 ++-- Tests/test_file_hdf5stub.py | 7 ++++--- Tests/test_file_jpeg.py | 2 +- Tests/test_file_webp.py | 4 +++- Tests/test_file_webp_animated.py | 2 +- Tests/test_file_wmf.py | 12 ++++++++---- Tests/test_image_access.py | 6 ++++++ Tests/test_image_rotate.py | 4 ++-- Tests/test_image_thumbnail.py | 4 +++- Tests/test_imageops_usm.py | 1 - Tests/test_qt_image_qapplication.py | 2 +- src/PIL/BufrStubImagePlugin.py | 2 +- src/PIL/GribStubImagePlugin.py | 2 +- src/PIL/Hdf5StubImagePlugin.py | 2 +- src/PIL/WmfImagePlugin.py | 2 +- 19 files changed, 44 insertions(+), 28 deletions(-) diff --git a/Tests/bench_cffi_access.py b/Tests/bench_cffi_access.py index d2a08c07bc4..c7d105836aa 100644 --- a/Tests/bench_cffi_access.py +++ b/Tests/bench_cffi_access.py @@ -44,6 +44,7 @@ def test_direct() -> None: caccess = im.im.pixel_access(False) access = PyAccess.new(im, False) + assert access is not None assert caccess[(0, 0)] == access[(0, 0)] print(f"Size: {im.width}x{im.height}") diff --git a/Tests/test_features.py b/Tests/test_features.py index 59fb4980923..de418115ee0 100644 --- a/Tests/test_features.py +++ b/Tests/test_features.py @@ -124,7 +124,7 @@ def test_unsupported_module() -> None: @pytest.mark.parametrize("supported_formats", (True, False)) -def test_pilinfo(supported_formats) -> None: +def test_pilinfo(supported_formats: bool) -> None: buf = io.StringIO() features.pilinfo(buf, supported_formats=supported_formats) out = buf.getvalue() diff --git a/Tests/test_file_bmp.py b/Tests/test_file_bmp.py index c7c9b24e763..2ff4160bd71 100644 --- a/Tests/test_file_bmp.py +++ b/Tests/test_file_bmp.py @@ -140,7 +140,7 @@ def test_load_dib() -> None: (124, "g/pal8v5.bmp"), ), ) -def test_dib_header_size(header_size, path): +def test_dib_header_size(header_size: int, path: str) -> None: image_path = "Tests/images/bmp/" + path with open(image_path, "rb") as fp: data = fp.read()[14:] diff --git a/Tests/test_file_bufrstub.py b/Tests/test_file_bufrstub.py index 3dd24533aae..939e82e7717 100644 --- a/Tests/test_file_bufrstub.py +++ b/Tests/test_file_bufrstub.py @@ -1,10 +1,11 @@ from __future__ import annotations from pathlib import Path +from typing import IO import pytest -from PIL import BufrStubImagePlugin, Image +from PIL import BufrStubImagePlugin, Image, ImageFile from .helper import hopper @@ -50,20 +51,20 @@ def test_save(tmp_path: Path) -> None: def test_handler(tmp_path: Path) -> None: - class TestHandler: + class TestHandler(ImageFile.StubHandler): opened = False loaded = False saved = False - def open(self, im) -> None: + def open(self, im: ImageFile.StubImageFile) -> None: self.opened = True - def load(self, im): + def load(self, im: ImageFile.StubImageFile) -> Image.Image: self.loaded = True im.fp.close() return Image.new("RGB", (1, 1)) - def save(self, im, fp, filename) -> None: + def save(self, im: Image.Image, fp: IO[bytes], filename: str) -> None: self.saved = True handler = TestHandler() diff --git a/Tests/test_file_gribstub.py b/Tests/test_file_gribstub.py index 096a5b88b21..86a9064fc46 100644 --- a/Tests/test_file_gribstub.py +++ b/Tests/test_file_gribstub.py @@ -5,7 +5,7 @@ import pytest -from PIL import GribStubImagePlugin, Image +from PIL import GribStubImagePlugin, Image, ImageFile from .helper import hopper @@ -51,7 +51,7 @@ def test_save(tmp_path: Path) -> None: def test_handler(tmp_path: Path) -> None: - class TestHandler: + class TestHandler(ImageFile.StubHandler): opened = False loaded = False saved = False diff --git a/Tests/test_file_hdf5stub.py b/Tests/test_file_hdf5stub.py index f871e2eff16..ee1544c51fa 100644 --- a/Tests/test_file_hdf5stub.py +++ b/Tests/test_file_hdf5stub.py @@ -1,11 +1,12 @@ from __future__ import annotations +from io import BytesIO from pathlib import Path from typing import IO import pytest -from PIL import Hdf5StubImagePlugin, Image +from PIL import Hdf5StubImagePlugin, Image, ImageFile TEST_FILE = "Tests/images/hdf5.h5" @@ -41,7 +42,7 @@ def test_load() -> None: def test_save() -> None: # Arrange with Image.open(TEST_FILE) as im: - dummy_fp = None + dummy_fp = BytesIO() dummy_filename = "dummy.filename" # Act / Assert: stub cannot save without an implemented handler @@ -52,7 +53,7 @@ def test_save() -> None: def test_handler(tmp_path: Path) -> None: - class TestHandler: + class TestHandler(ImageFile.StubHandler): opened = False loaded = False saved = False diff --git a/Tests/test_file_jpeg.py b/Tests/test_file_jpeg.py index 33f9ce00edc..18dc752d8bd 100644 --- a/Tests/test_file_jpeg.py +++ b/Tests/test_file_jpeg.py @@ -171,7 +171,7 @@ def getchannels(im: JpegImagePlugin.JpegImageFile) -> tuple[int, int, int]: [TEST_FILE, "Tests/images/pil_sample_cmyk.jpg"], ) def test_dpi(self, test_image_path: str) -> None: - def test(xdpi: int, ydpi: int | None = None): + def test(xdpi: int, ydpi: int | None = None) -> tuple[int, int] | None: with Image.open(test_image_path) as im: im = self.roundtrip(im, dpi=(xdpi, ydpi or xdpi)) return im.info.get("dpi") diff --git a/Tests/test_file_webp.py b/Tests/test_file_webp.py index e2de84c71a1..1caf032f6e1 100644 --- a/Tests/test_file_webp.py +++ b/Tests/test_file_webp.py @@ -198,7 +198,9 @@ def test_file_pointer_could_be_reused(self) -> None: (0, (0,), (-1, 0, 1, 2), (253, 254, 255, 256)), ) @skip_unless_feature("webp_anim") - def test_invalid_background(self, background, tmp_path: Path) -> None: + def test_invalid_background( + self, background: int | tuple[int, ...], tmp_path: Path + ) -> None: temp_file = str(tmp_path / "temp.webp") im = hopper() with pytest.raises(OSError): diff --git a/Tests/test_file_webp_animated.py b/Tests/test_file_webp_animated.py index ba931f8643c..882dccb32f9 100644 --- a/Tests/test_file_webp_animated.py +++ b/Tests/test_file_webp_animated.py @@ -69,7 +69,7 @@ def test_write_animation_RGB(tmp_path: Path) -> None: are visually similar to the originals. """ - def check(temp_file) -> None: + def check(temp_file: str) -> None: with Image.open(temp_file) as im: assert im.n_frames == 2 diff --git a/Tests/test_file_wmf.py b/Tests/test_file_wmf.py index b43e3f2965f..79e707263d6 100644 --- a/Tests/test_file_wmf.py +++ b/Tests/test_file_wmf.py @@ -1,10 +1,11 @@ from __future__ import annotations from pathlib import Path +from typing import IO import pytest -from PIL import Image, WmfImagePlugin +from PIL import Image, ImageFile, WmfImagePlugin from .helper import assert_image_similar_tofile, hopper @@ -34,10 +35,13 @@ def test_load() -> None: def test_register_handler(tmp_path: Path) -> None: - class TestHandler: + class TestHandler(ImageFile.StubHandler): methodCalled = False - def save(self, im, fp, filename) -> None: + def load(self, im: ImageFile.StubImageFile) -> Image.Image: + return Image.new("RGB", (1, 1)) + + def save(self, im: Image.Image, fp: IO[bytes], filename: str) -> None: self.methodCalled = True handler = TestHandler() @@ -70,7 +74,7 @@ def test_load_set_dpi() -> None: @pytest.mark.parametrize("ext", (".wmf", ".emf")) -def test_save(ext, tmp_path: Path) -> None: +def test_save(ext: str, tmp_path: Path) -> None: im = hopper() tmpfile = str(tmp_path / ("temp" + ext)) diff --git a/Tests/test_image_access.py b/Tests/test_image_access.py index 9d600667937..8abb1f69fc1 100644 --- a/Tests/test_image_access.py +++ b/Tests/test_image_access.py @@ -259,6 +259,7 @@ def _test_get_access(self, im: Image.Image) -> None: caccess = im.im.pixel_access(False) with pytest.warns(DeprecationWarning): access = PyAccess.new(im, False) + assert access is not None w, h = im.size for x in range(0, w, 10): @@ -289,6 +290,7 @@ def _test_set_access(self, im: Image.Image, color: tuple[int, ...] | float) -> N caccess = im.im.pixel_access(False) with pytest.warns(DeprecationWarning): access = PyAccess.new(im, False) + assert access is not None w, h = im.size for x in range(0, w, 10): @@ -299,6 +301,8 @@ def _test_set_access(self, im: Image.Image, color: tuple[int, ...] | float) -> N # Attempt to set the value on a read-only image with pytest.warns(DeprecationWarning): access = PyAccess.new(im, True) + assert access is not None + with pytest.raises(ValueError): access[(0, 0)] = color @@ -341,6 +345,8 @@ def test_p_putpixel_rgb_rgba(self, mode: str) -> None: im = Image.new(mode, (1, 1)) with pytest.warns(DeprecationWarning): access = PyAccess.new(im, False) + assert access is not None + access.putpixel((0, 0), color) if len(color) == 3: diff --git a/Tests/test_image_rotate.py b/Tests/test_image_rotate.py index c10c96da6f9..252a15db742 100644 --- a/Tests/test_image_rotate.py +++ b/Tests/test_image_rotate.py @@ -124,8 +124,8 @@ def test_fastpath_translate() -> None: def test_center() -> None: im = hopper() rotate(im, im.mode, 45, center=(0, 0)) - rotate(im, im.mode, 45, translate=(im.size[0] / 2, 0)) - rotate(im, im.mode, 45, center=(0, 0), translate=(im.size[0] / 2, 0)) + rotate(im, im.mode, 45, translate=(im.size[0] // 2, 0)) + rotate(im, im.mode, 45, center=(0, 0), translate=(im.size[0] // 2, 0)) def test_rotate_no_fill() -> None: diff --git a/Tests/test_image_thumbnail.py b/Tests/test_image_thumbnail.py index 2ca1d2cfc03..1593eaaf7fa 100644 --- a/Tests/test_image_thumbnail.py +++ b/Tests/test_image_thumbnail.py @@ -111,7 +111,9 @@ def test_load_first_unless_jpeg() -> None: with Image.open("Tests/images/hopper.jpg") as im: draft = im.draft - def im_draft(mode: str, size: tuple[int, int]): + def im_draft( + mode: str, size: tuple[int, int] + ) -> tuple[str, tuple[int, int, float, float]] | None: result = draft(mode, size) assert result is not None diff --git a/Tests/test_imageops_usm.py b/Tests/test_imageops_usm.py index 104c620de01..dbdd5b317d5 100644 --- a/Tests/test_imageops_usm.py +++ b/Tests/test_imageops_usm.py @@ -58,7 +58,6 @@ def test_blur_formats(test_images: dict[str, ImageFile.ImageFile]) -> None: blur = ImageFilter.GaussianBlur with pytest.raises(ValueError): im.convert("1").filter(blur) - blur(im.convert("L")) with pytest.raises(ValueError): im.convert("I").filter(blur) with pytest.raises(ValueError): diff --git a/Tests/test_qt_image_qapplication.py b/Tests/test_qt_image_qapplication.py index 3cd323553fa..28f66891c0d 100644 --- a/Tests/test_qt_image_qapplication.py +++ b/Tests/test_qt_image_qapplication.py @@ -46,7 +46,7 @@ def roundtrip(expected: Image.Image) -> None: @pytest.mark.skipif(not ImageQt.qt_is_installed, reason="Qt bindings are not installed") def test_sanity(tmp_path: Path) -> None: # Segfault test - app = QApplication([]) + app: QApplication | None = QApplication([]) ex = Example() assert app # Silence warning assert ex # Silence warning diff --git a/src/PIL/BufrStubImagePlugin.py b/src/PIL/BufrStubImagePlugin.py index 6f52204b829..7388a2b8a3a 100644 --- a/src/PIL/BufrStubImagePlugin.py +++ b/src/PIL/BufrStubImagePlugin.py @@ -17,7 +17,7 @@ _handler = None -def register_handler(handler: ImageFile.StubHandler) -> None: +def register_handler(handler: ImageFile.StubHandler | None) -> None: """ Install application-specific BUFR image handler. diff --git a/src/PIL/GribStubImagePlugin.py b/src/PIL/GribStubImagePlugin.py index b24dcded2f9..d3655f4ddc0 100644 --- a/src/PIL/GribStubImagePlugin.py +++ b/src/PIL/GribStubImagePlugin.py @@ -17,7 +17,7 @@ _handler = None -def register_handler(handler: ImageFile.StubHandler) -> None: +def register_handler(handler: ImageFile.StubHandler | None) -> None: """ Install application-specific GRIB image handler. diff --git a/src/PIL/Hdf5StubImagePlugin.py b/src/PIL/Hdf5StubImagePlugin.py index c8d7866a312..b789c215fee 100644 --- a/src/PIL/Hdf5StubImagePlugin.py +++ b/src/PIL/Hdf5StubImagePlugin.py @@ -17,7 +17,7 @@ _handler = None -def register_handler(handler: ImageFile.StubHandler) -> None: +def register_handler(handler: ImageFile.StubHandler | None) -> None: """ Install application-specific HDF5 image handler. diff --git a/src/PIL/WmfImagePlugin.py b/src/PIL/WmfImagePlugin.py index 25a4545db52..a68f705a03c 100644 --- a/src/PIL/WmfImagePlugin.py +++ b/src/PIL/WmfImagePlugin.py @@ -30,7 +30,7 @@ _handler = None -def register_handler(handler: ImageFile.StubHandler) -> None: +def register_handler(handler: ImageFile.StubHandler | None) -> None: """ Install application-specific WMF image handler.