From 4d511d86edf5b78ec3778061c41c5b7ed8653339 Mon Sep 17 00:00:00 2001 From: Andrew Murray Date: Mon, 1 Dec 2025 19:31:40 +1100 Subject: [PATCH 1/6] Changed argument type to match use --- Tests/test_file_libtiff.py | 12 ++++++++++-- 1 file changed, 10 insertions(+), 2 deletions(-) diff --git a/Tests/test_file_libtiff.py b/Tests/test_file_libtiff.py index 7cb3ea8e4..cf7676ab1 100644 --- a/Tests/test_file_libtiff.py +++ b/Tests/test_file_libtiff.py @@ -11,7 +11,15 @@ from typing import Any, NamedTuple import pytest -from PIL import Image, ImageFilter, ImageOps, TiffImagePlugin, TiffTags, features +from PIL import ( + Image, + ImageFile, + ImageFilter, + ImageOps, + TiffImagePlugin, + TiffTags, + features, +) from PIL.TiffImagePlugin import OSUBFILETYPE, SAMPLEFORMAT, STRIPOFFSETS, SUBIFD from .helper import ( @@ -27,7 +35,7 @@ from .helper import ( @skip_unless_feature("libtiff") class LibTiffTestCase: - def _assert_noerr(self, tmp_path: Path, im: TiffImagePlugin.TiffImageFile) -> None: + def _assert_noerr(self, tmp_path: Path, im: ImageFile.ImageFile) -> None: """Helper tests that assert basic sanity about the g4 tiff reading""" # 1 bit assert im.mode == "1" From 4024f0287d4e8a1467da8ce4ac86ea087e53af1c Mon Sep 17 00:00:00 2001 From: Andrew Murray Date: Mon, 1 Dec 2025 19:25:47 +1100 Subject: [PATCH 2/6] Assert image type --- Tests/test_file_iptc.py | 1 + Tests/test_file_libtiff.py | 1 + Tests/test_file_png.py | 2 ++ src/PIL/Image.py | 3 +++ 4 files changed, 7 insertions(+) diff --git a/Tests/test_file_iptc.py b/Tests/test_file_iptc.py index 0376b9997..9e2d8c06d 100644 --- a/Tests/test_file_iptc.py +++ b/Tests/test_file_iptc.py @@ -143,6 +143,7 @@ def test_getiptcinfo_tiff() -> None: # Test with LONG tag type with Image.open("Tests/images/hopper.Lab.tif") as im: + assert isinstance(im, TiffImagePlugin.TiffImageFile) im.tag_v2.tagtype[TiffImagePlugin.IPTC_NAA_CHUNK] = TiffTags.LONG iptc = IptcImagePlugin.getiptcinfo(im) diff --git a/Tests/test_file_libtiff.py b/Tests/test_file_libtiff.py index cf7676ab1..77e0b4bc9 100644 --- a/Tests/test_file_libtiff.py +++ b/Tests/test_file_libtiff.py @@ -378,6 +378,7 @@ class TestFileLibTiff(LibTiffTestCase): im.save(out, tiffinfo=ifd) with Image.open(out) as reloaded: + assert isinstance(reloaded, TiffImagePlugin.TiffImageFile) assert reloaded.tag_v2[37000] == 100 def test_inknames_tag( diff --git a/Tests/test_file_png.py b/Tests/test_file_png.py index 9875fe096..7f163a4d6 100644 --- a/Tests/test_file_png.py +++ b/Tests/test_file_png.py @@ -787,7 +787,9 @@ class TestFilePng: im.save(test_file, exif=im.getexif()) with Image.open(test_file) as reloaded: + assert isinstance(reloaded, PngImagePlugin.PngImageFile) exif = reloaded._getexif() + assert exif is not None assert exif[305] == "Adobe Photoshop CS Macintosh" def test_exif_argument(self, tmp_path: Path) -> None: diff --git a/src/PIL/Image.py b/src/PIL/Image.py index 9d50812eb..b71395c62 100644 --- a/src/PIL/Image.py +++ b/src/PIL/Image.py @@ -1519,6 +1519,9 @@ class Image: "".join(self.info["Raw profile type exif"].split("\n")[3:]) ) elif hasattr(self, "tag_v2"): + from . import TiffImagePlugin + + assert isinstance(self, TiffImagePlugin.TiffImageFile) self._exif.bigtiff = self.tag_v2._bigtiff self._exif.endian = self.tag_v2._endian self._exif.load_from_fp(self.fp, self.tag_v2._offset) From 46ac30aa80e592fb3f58e8094c03547c57e04cd5 Mon Sep 17 00:00:00 2001 From: Andrew Murray Date: Mon, 1 Dec 2025 18:42:58 +1100 Subject: [PATCH 3/6] Use different variables for Image and ImageFile instances --- Tests/test_file_libtiff.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/Tests/test_file_libtiff.py b/Tests/test_file_libtiff.py index 77e0b4bc9..e36b5f39e 100644 --- a/Tests/test_file_libtiff.py +++ b/Tests/test_file_libtiff.py @@ -1155,9 +1155,9 @@ class TestFileLibTiff(LibTiffTestCase): with Image.open("Tests/images/g4_orientation_1.tif") as base_im: for i in range(2, 9): with Image.open("Tests/images/g4_orientation_" + str(i) + ".tif") as im: - im = ImageOps.exif_transpose(im) + im_transposed = ImageOps.exif_transpose(im) - assert_image_similar(base_im, im, 0.7) + assert_image_similar(base_im, im_transposed, 0.7) @pytest.mark.parametrize( "test_file", From 61b1c3c841341cc6f22ab2caa321b7303f61bd35 Mon Sep 17 00:00:00 2001 From: Andrew Murray Date: Mon, 1 Dec 2025 23:51:00 +1100 Subject: [PATCH 4/6] Do not change variable type --- src/PIL/GifImagePlugin.py | 4 ++-- src/PIL/XVThumbImagePlugin.py | 4 ++-- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/src/PIL/GifImagePlugin.py b/src/PIL/GifImagePlugin.py index 58c460ef3..b00953a9d 100644 --- a/src/PIL/GifImagePlugin.py +++ b/src/PIL/GifImagePlugin.py @@ -116,8 +116,8 @@ class GifImageFile(ImageFile.ImageFile): # check if palette contains colour indices p = self.fp.read(3 << bits) if self._is_palette_needed(p): - p = ImagePalette.raw("RGB", p) - self.global_palette = self.palette = p + palette = ImagePalette.raw("RGB", p) + self.global_palette = self.palette = palette self._fp = self.fp # FIXME: hack self.__rewind = self.fp.tell() diff --git a/src/PIL/XVThumbImagePlugin.py b/src/PIL/XVThumbImagePlugin.py index cde28388f..192c041d9 100644 --- a/src/PIL/XVThumbImagePlugin.py +++ b/src/PIL/XVThumbImagePlugin.py @@ -66,10 +66,10 @@ class XVThumbImageFile(ImageFile.ImageFile): break # parse header line (already read) - s = s.strip().split() + w, h = s.strip().split(maxsplit=2)[:2] self._mode = "P" - self._size = int(s[0]), int(s[1]) + self._size = int(w), int(h) self.palette = ImagePalette.raw("RGB", PALETTE) From 7c3ece07c9871ca992bd497961e023228a8ebd14 Mon Sep 17 00:00:00 2001 From: Andrew Murray Date: Mon, 1 Dec 2025 19:06:02 +1100 Subject: [PATCH 5/6] Changed type so that im has fp attribute --- Tests/test_file_gribstub.py | 2 +- Tests/test_file_hdf5stub.py | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/Tests/test_file_gribstub.py b/Tests/test_file_gribstub.py index 960e5f4be..4dbed6b31 100644 --- a/Tests/test_file_gribstub.py +++ b/Tests/test_file_gribstub.py @@ -59,7 +59,7 @@ def test_handler(tmp_path: Path) -> None: def open(self, im: Image.Image) -> None: self.opened = True - def load(self, im: Image.Image) -> Image.Image: + def load(self, im: ImageFile.ImageFile) -> Image.Image: self.loaded = True im.fp.close() return Image.new("RGB", (1, 1)) diff --git a/Tests/test_file_hdf5stub.py b/Tests/test_file_hdf5stub.py index e4f09a09c..1e48597d3 100644 --- a/Tests/test_file_hdf5stub.py +++ b/Tests/test_file_hdf5stub.py @@ -61,7 +61,7 @@ def test_handler(tmp_path: Path) -> None: def open(self, im: Image.Image) -> None: self.opened = True - def load(self, im: Image.Image) -> Image.Image: + def load(self, im: ImageFile.ImageFile) -> Image.Image: self.loaded = True im.fp.close() return Image.new("RGB", (1, 1)) From fd1ddd6d56457c2611b5b947af9a2c1d5a9479b2 Mon Sep 17 00:00:00 2001 From: Andrew Murray Date: Mon, 1 Dec 2025 19:12:58 +1100 Subject: [PATCH 6/6] Use consistent type --- src/PIL/GifImagePlugin.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/PIL/GifImagePlugin.py b/src/PIL/GifImagePlugin.py index b00953a9d..0560a5a7d 100644 --- a/src/PIL/GifImagePlugin.py +++ b/src/PIL/GifImagePlugin.py @@ -256,7 +256,7 @@ class GifImageFile(ImageFile.ImageFile): info["comment"] += b"\n" + comment else: info["comment"] = comment - s = None + s = b"" continue elif s[0] == 255 and frame == 0 and block is not None: # @@ -299,7 +299,7 @@ class GifImageFile(ImageFile.ImageFile): bits = self.fp.read(1)[0] self.__offset = self.fp.tell() break - s = None + s = b"" if interlace is None: msg = "image not found in GIF frame"