From 5056850a2f0a54f27e4117cbe26abe468e4405bc Mon Sep 17 00:00:00 2001 From: Andrew Murray Date: Fri, 20 Oct 2023 16:09:13 +1100 Subject: [PATCH 01/21] Seek past the data when skipping a layer --- Tests/images/five_channels.psd | Bin 0 -> 1120 bytes Tests/test_file_psd.py | 5 +++++ src/PIL/PsdImagePlugin.py | 3 +++ 3 files changed, 8 insertions(+) create mode 100644 Tests/images/five_channels.psd diff --git a/Tests/images/five_channels.psd b/Tests/images/five_channels.psd new file mode 100644 index 0000000000000000000000000000000000000000..021a5fa633bf9989b728018e58f6c950a604370a GIT binary patch literal 1120 zcmaJFeA*5AW_0auEwxQWg*v%pZkAl~N z2Y)VBJ$Uh~R}WqVL8uDi)r(#fy+~cZdE2-lG!DEs-V0CT+pGZ)2tlz16f_$3$r!A^9Mn5#VBuXT`Nz0K>;OX zv4Em!hyCS7qb`h-<=0_S+q)&nb#lx^Ytdf~^s3?*txWE-V<>5F!}j@e%B0O0K<;xK|5yN~?gB^qas2yn93MRaGM|7~e#-A10M(zg@29rP zBVhJ6@Zxo9v+e;e?*Q{3`(|LOdt|osb{qKq3@B~^r``gE>q+0}6F;852R7KN`WxWE zL*T5-+&3n?dzyrQefw|BasT+wSGk&;+f+0{4Y@d`&MR|X&0k(c<>NnMmnrvqfhR$f zZ7!LHp(HtuPX)uYcio^DaR`Lhjr^IQcO{1Y3ya1ro_BL1$UV(e}}zr1K%lHA!z y^^H|l8`5)ibFammBNfcimqVQu?4iZ`6W{pF8s8nW1Ja}MJ+Y7OqcOT-lJ*zu@1>;x literal 0 HcmV?d00001 diff --git a/Tests/test_file_psd.py b/Tests/test_file_psd.py index e405834b5..708212fa6 100644 --- a/Tests/test_file_psd.py +++ b/Tests/test_file_psd.py @@ -111,6 +111,11 @@ def test_rgba(): assert_image_equal_tofile(im, "Tests/images/imagedraw_square.png") +def test_layer_skip(): + with Image.open("Tests/images/five_channels.psd") as im: + assert im.n_frames == 1 + + def test_icc_profile(): with Image.open(test_file) as im: assert "icc_profile" in im.info diff --git a/src/PIL/PsdImagePlugin.py b/src/PIL/PsdImagePlugin.py index 2f019bb8c..46970da04 100644 --- a/src/PIL/PsdImagePlugin.py +++ b/src/PIL/PsdImagePlugin.py @@ -186,6 +186,9 @@ def _layerinfo(fp, ct_bytes): ct_types = i16(read(2)) types = list(range(ct_types)) if len(types) > 4: + fp.seek(len(types) * 6 + 12, io.SEEK_CUR) + size = i32(read(4)) + fp.seek(size, io.SEEK_CUR) continue for _ in types: From 7c2b6811834ec36846d9bf9dc97675eecc777dd8 Mon Sep 17 00:00:00 2001 From: Andrew Murray Date: Thu, 2 Nov 2023 16:05:13 +1100 Subject: [PATCH 02/21] Handle disposing background from outside palette --- Tests/images/background_outside_palette.gif | Bin 0 -> 82 bytes Tests/test_file_gif.py | 6 ++++++ src/PIL/GifImagePlugin.py | 2 ++ 3 files changed, 8 insertions(+) create mode 100644 Tests/images/background_outside_palette.gif diff --git a/Tests/images/background_outside_palette.gif b/Tests/images/background_outside_palette.gif new file mode 100644 index 0000000000000000000000000000000000000000..63e767463c498b85ab40023298e1434e76db4598 GIT binary patch literal 82 ycmZ?wbh9u|WMp7uX!y?n0g69aI6y2N5CM{5;9y~3WMN^zkZ6Qy0jY#4vIYQ>R|mBK literal 0 HcmV?d00001 diff --git a/Tests/test_file_gif.py b/Tests/test_file_gif.py index fa5d54feb..d18ce2055 100644 --- a/Tests/test_file_gif.py +++ b/Tests/test_file_gif.py @@ -1142,6 +1142,12 @@ def test_rgba_transparency(tmp_path): assert_image_equal(hopper("P").convert("RGB"), reloaded) +def test_background_outside_palettte(tmp_path): + with Image.open("Tests/images/background_outside_palette.gif") as im: + im.seek(1) + assert im.info["background"] == 255 + + def test_bbox(tmp_path): out = str(tmp_path / "temp.gif") diff --git a/src/PIL/GifImagePlugin.py b/src/PIL/GifImagePlugin.py index 4ce295f7f..d30dfbb3d 100644 --- a/src/PIL/GifImagePlugin.py +++ b/src/PIL/GifImagePlugin.py @@ -335,6 +335,8 @@ class GifImageFile(ImageFile.ImageFile): def _rgb(color): if self._frame_palette: + if color * 3 + 3 > len(self._frame_palette.palette): + color = 0 color = tuple(self._frame_palette.palette[color * 3 : color * 3 + 3]) else: color = (color, color, color) From dc0379fea5315831b9d99a8d6328710ec201d78a Mon Sep 17 00:00:00 2001 From: Andrew Murray Date: Fri, 3 Nov 2023 21:09:16 +1100 Subject: [PATCH 03/21] Corrected combining durations from multiple frames into single frame --- Tests/test_file_gif.py | 11 ++++++++-- src/PIL/GifImagePlugin.py | 42 +++++++++++++++++++-------------------- 2 files changed, 30 insertions(+), 23 deletions(-) diff --git a/Tests/test_file_gif.py b/Tests/test_file_gif.py index fa5d54feb..a03079ecd 100644 --- a/Tests/test_file_gif.py +++ b/Tests/test_file_gif.py @@ -856,7 +856,14 @@ def test_identical_frames(tmp_path): @pytest.mark.parametrize( - "duration", ([1000, 1500, 2000, 4000], (1000, 1500, 2000, 4000), 8500) + "duration", + ( + [1000, 1500, 2000], + (1000, 1500, 2000), + # One more duration than the number of frames + [1000, 1500, 2000, 4000], + 1500, + ), ) def test_identical_frames_to_single_frame(duration, tmp_path): out = str(tmp_path / "temp.gif") @@ -872,7 +879,7 @@ def test_identical_frames_to_single_frame(duration, tmp_path): assert reread.n_frames == 1 # Assert that the new duration is the total of the identical frames - assert reread.info["duration"] == 8500 + assert reread.info["duration"] == 4500 def test_loop_none(tmp_path): diff --git a/src/PIL/GifImagePlugin.py b/src/PIL/GifImagePlugin.py index 4ce295f7f..799198598 100644 --- a/src/PIL/GifImagePlugin.py +++ b/src/PIL/GifImagePlugin.py @@ -627,28 +627,28 @@ def _write_multiple_frames(im, fp, palette): bbox = None im_frames.append({"im": im_frame, "bbox": bbox, "encoderinfo": encoderinfo}) - if len(im_frames) > 1: - for frame_data in im_frames: - im_frame = frame_data["im"] - if not frame_data["bbox"]: - # global header - for s in _get_global_header(im_frame, frame_data["encoderinfo"]): - fp.write(s) - offset = (0, 0) - else: - # compress difference - if not palette: - frame_data["encoderinfo"]["include_color_table"] = True + if len(im_frames) == 1: + if "duration" in im.encoderinfo: + # Since multiple frames will not be written, use the combined duration + im.encoderinfo["duration"] = im_frames[0]["encoderinfo"]["duration"] + return - im_frame = im_frame.crop(frame_data["bbox"]) - offset = frame_data["bbox"][:2] - _write_frame_data(fp, im_frame, offset, frame_data["encoderinfo"]) - return True - elif "duration" in im.encoderinfo and isinstance( - im.encoderinfo["duration"], (list, tuple) - ): - # Since multiple frames will not be written, add together the frame durations - im.encoderinfo["duration"] = sum(im.encoderinfo["duration"]) + for frame_data in im_frames: + im_frame = frame_data["im"] + if not frame_data["bbox"]: + # global header + for s in _get_global_header(im_frame, frame_data["encoderinfo"]): + fp.write(s) + offset = (0, 0) + else: + # compress difference + if not palette: + frame_data["encoderinfo"]["include_color_table"] = True + + im_frame = im_frame.crop(frame_data["bbox"]) + offset = frame_data["bbox"][:2] + _write_frame_data(fp, im_frame, offset, frame_data["encoderinfo"]) + return True def _save_all(im, fp, filename): From f016d3079baac6349da937ea31229f1edfcef64c Mon Sep 17 00:00:00 2001 From: Andrew Murray Date: Mon, 13 Nov 2023 14:31:22 +1100 Subject: [PATCH 04/21] Determine mask mode in Python instead of C --- src/PIL/ImageFont.py | 8 ++++---- src/_imagingft.c | 2 +- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/src/PIL/ImageFont.py b/src/PIL/ImageFont.py index c29562135..1593c5d54 100644 --- a/src/PIL/ImageFont.py +++ b/src/PIL/ImageFont.py @@ -565,16 +565,16 @@ class FreeTypeFont: im = None size = None - def fill(mode, im_size): + def fill(width, height): nonlocal im, size - size = im_size + size = (width, height) if Image.MAX_IMAGE_PIXELS is not None: - pixels = max(1, size[0]) * max(1, size[1]) + pixels = max(1, width) * max(1, height) if pixels > 2 * Image.MAX_IMAGE_PIXELS: return - im = Image.core.fill(mode, size) + im = Image.core.fill("RGBA" if mode == "RGBA" else "L", size) return im offset = self.font.render( diff --git a/src/_imagingft.c b/src/_imagingft.c index 64175de8b..f0b849035 100644 --- a/src/_imagingft.c +++ b/src/_imagingft.c @@ -877,7 +877,7 @@ font_render(FontObject *self, PyObject *args) { width += stroke_width * 2 + ceil(x_start); height += stroke_width * 2 + ceil(y_start); - image = PyObject_CallFunction(fill, "s(ii)", strcmp(mode, "RGBA") == 0 ? "RGBA" : "L", width, height); + image = PyObject_CallFunction(fill, "ii", width, height); if (image == Py_None) { PyMem_Del(glyph_info); return Py_BuildValue("ii", 0, 0); From 524b823c1bcc7b3255cacd988fb8bb2c25981095 Mon Sep 17 00:00:00 2001 From: Andrew Murray Date: Fri, 17 Nov 2023 17:41:47 +1100 Subject: [PATCH 05/21] Removed unnecessary string length check --- src/PIL/ImageFont.py | 1 - 1 file changed, 1 deletion(-) diff --git a/src/PIL/ImageFont.py b/src/PIL/ImageFont.py index c29562135..f5cf73a96 100644 --- a/src/PIL/ImageFont.py +++ b/src/PIL/ImageFont.py @@ -712,7 +712,6 @@ class TransposedFont: if self.orientation in (Image.Transpose.ROTATE_90, Image.Transpose.ROTATE_270): msg = "text length is undefined for text rotated by 90 or 270 degrees" raise ValueError(msg) - _string_length_check(text) return self.font.getlength(text, *args, **kwargs) From a07bac3a56518e40559e3b14619ccd0c89a01e50 Mon Sep 17 00:00:00 2001 From: Andrew Murray Date: Tue, 21 Nov 2023 21:45:14 +1100 Subject: [PATCH 06/21] Attempt memory mapping when tile args is a string --- src/PIL/ImageFile.py | 2 ++ src/PIL/WebPImagePlugin.py | 3 +++ 2 files changed, 5 insertions(+) diff --git a/src/PIL/ImageFile.py b/src/PIL/ImageFile.py index 902e8ce5f..998a68e1c 100644 --- a/src/PIL/ImageFile.py +++ b/src/PIL/ImageFile.py @@ -187,6 +187,8 @@ class ImageFile(Image.Image): if use_mmap: # try memory mapping decoder_name, extents, offset, args = self.tile[0] + if isinstance(args, str): + args = (args, 0, 1) if ( decoder_name == "raw" and len(args) >= 3 diff --git a/src/PIL/WebPImagePlugin.py b/src/PIL/WebPImagePlugin.py index 612fc0946..eed58a13b 100644 --- a/src/PIL/WebPImagePlugin.py +++ b/src/PIL/WebPImagePlugin.py @@ -168,6 +168,9 @@ class WebPImageFile(ImageFile.ImageFile): return super().load() + def load_seek(self, pos): + pass + def tell(self): if not _webp.HAVE_WEBPANIM: return super().tell() From 55c5587437669389bd7b0044753b47ca43afe59e Mon Sep 17 00:00:00 2001 From: Andrew Murray Date: Sat, 25 Nov 2023 19:16:32 +1100 Subject: [PATCH 07/21] Fill identical pixels with transparency in subsequent frames --- Tests/test_file_gif.py | 21 ++++++ docs/handbook/image-file-formats.rst | 9 ++- src/PIL/GifImagePlugin.py | 109 ++++++++++++++++++--------- src/PIL/ImagePalette.py | 46 +++++------ 4 files changed, 124 insertions(+), 61 deletions(-) diff --git a/Tests/test_file_gif.py b/Tests/test_file_gif.py index fa5d54feb..5bfb120f3 100644 --- a/Tests/test_file_gif.py +++ b/Tests/test_file_gif.py @@ -217,6 +217,27 @@ def test_optimize_if_palette_can_be_reduced_by_half(): assert len(reloaded.palette.palette) // 3 == colors +def test_full_palette_second_frame(tmp_path): + out = str(tmp_path / "temp.gif") + im = Image.new("P", (1, 256)) + + full_palette_im = Image.new("P", (1, 256)) + for i in range(256): + full_palette_im.putpixel((0, i), i) + full_palette_im.palette = ImagePalette.ImagePalette( + "RGB", bytearray(i // 3 for i in range(768)) + ) + full_palette_im.palette.dirty = 1 + + im.save(out, save_all=True, append_images=[full_palette_im]) + + with Image.open(out) as reloaded: + reloaded.seek(1) + + for i in range(256): + reloaded.getpixel((0, i)) == i + + def test_roundtrip(tmp_path): out = str(tmp_path / "temp.gif") im = hopper() diff --git a/docs/handbook/image-file-formats.rst b/docs/handbook/image-file-formats.rst index 38c00f870..bded1149b 100644 --- a/docs/handbook/image-file-formats.rst +++ b/docs/handbook/image-file-formats.rst @@ -266,13 +266,14 @@ following options are available:: :py:class:`PIL.ImagePalette.ImagePalette` object. **optimize** - Whether to attempt to compress the palette by eliminating unused colors. + Whether to attempt to compress the palette by eliminating unused colors + (this is only useful if the palette can be compressed to the next smaller + power of 2 elements) and whether to mark all pixels that are not new in the + next frame as transparent. + This is attempted by default, unless a palette is specified as an option or as part of the first image's :py:attr:`~PIL.Image.Image.info` dictionary. - This is only useful if the palette can be compressed to the next smaller - power of 2 elements. - Note that if the image you are saving comes from an existing GIF, it may have the following properties in its :py:attr:`~PIL.Image.Image.info` dictionary. For these options, if you do not pass them in, they will default to diff --git a/src/PIL/GifImagePlugin.py b/src/PIL/GifImagePlugin.py index 0793d4b42..f73be9221 100644 --- a/src/PIL/GifImagePlugin.py +++ b/src/PIL/GifImagePlugin.py @@ -30,7 +30,15 @@ import os import subprocess from enum import IntEnum -from . import Image, ImageChops, ImageFile, ImagePalette, ImageSequence +from . import ( + Image, + ImageChops, + ImageFile, + ImageMath, + ImageOps, + ImagePalette, + ImageSequence, +) from ._binary import i16le as i16 from ._binary import o8 from ._binary import o16le as o16 @@ -534,7 +542,15 @@ def _normalize_palette(im, palette, info): else: used_palette_colors = _get_optimize(im, info) if used_palette_colors is not None: - return im.remap_palette(used_palette_colors, source_palette) + im = im.remap_palette(used_palette_colors, source_palette) + if "transparency" in info: + try: + info["transparency"] = used_palette_colors.index( + info["transparency"] + ) + except ValueError: + del info["transparency"] + return im im.palette.palette = source_palette return im @@ -562,13 +578,11 @@ def _write_single_frame(im, fp, palette): def _getbbox(base_im, im_frame): - if _get_palette_bytes(im_frame) == _get_palette_bytes(base_im): - delta = ImageChops.subtract_modulo(im_frame, base_im) - else: - delta = ImageChops.subtract_modulo( - im_frame.convert("RGBA"), base_im.convert("RGBA") - ) - return delta.getbbox(alpha_only=False) + if _get_palette_bytes(im_frame) != _get_palette_bytes(base_im): + im_frame = im_frame.convert("RGBA") + base_im = base_im.convert("RGBA") + delta = ImageChops.subtract_modulo(im_frame, base_im) + return delta, delta.getbbox(alpha_only=False) def _write_multiple_frames(im, fp, palette): @@ -576,6 +590,7 @@ def _write_multiple_frames(im, fp, palette): disposal = im.encoderinfo.get("disposal", im.info.get("disposal")) im_frames = [] + previous_im = None frame_count = 0 background_im = None for imSequence in itertools.chain([im], im.encoderinfo.get("append_images", [])): @@ -589,9 +604,9 @@ def _write_multiple_frames(im, fp, palette): im.encoderinfo.setdefault(k, v) encoderinfo = im.encoderinfo.copy() - im_frame = _normalize_palette(im_frame, palette, encoderinfo) if "transparency" in im_frame.info: encoderinfo.setdefault("transparency", im_frame.info["transparency"]) + im_frame = _normalize_palette(im_frame, palette, encoderinfo) if isinstance(duration, (list, tuple)): encoderinfo["duration"] = duration[frame_count] elif duration is None and "duration" in im_frame.info: @@ -600,14 +615,16 @@ def _write_multiple_frames(im, fp, palette): encoderinfo["disposal"] = disposal[frame_count] frame_count += 1 + diff_frame = None if im_frames: # delta frame - previous = im_frames[-1] - bbox = _getbbox(previous["im"], im_frame) + delta, bbox = _getbbox(previous_im, im_frame) if not bbox: # This frame is identical to the previous frame if encoderinfo.get("duration"): - previous["encoderinfo"]["duration"] += encoderinfo["duration"] + im_frames[-1]["encoderinfo"]["duration"] += encoderinfo[ + "duration" + ] continue if encoderinfo.get("disposal") == 2: if background_im is None: @@ -617,10 +634,44 @@ def _write_multiple_frames(im, fp, palette): background = _get_background(im_frame, color) background_im = Image.new("P", im_frame.size, background) background_im.putpalette(im_frames[0]["im"].palette) - bbox = _getbbox(background_im, im_frame) + delta, bbox = _getbbox(background_im, im_frame) + if encoderinfo.get("optimize") and im_frame.mode != "1": + if "transparency" not in encoderinfo: + try: + encoderinfo[ + "transparency" + ] = im_frame.palette._new_color_index(im_frame) + except ValueError: + pass + if "transparency" in encoderinfo: + # When the delta is zero, fill the image with transparency + diff_frame = im_frame.copy() + fill = Image.new( + "P", diff_frame.size, encoderinfo["transparency"] + ) + if delta.mode == "RGBA": + r, g, b, a = delta.split() + mask = ImageMath.eval( + "convert(max(max(max(r, g), b), a) * 255, '1')", + r=r, + g=g, + b=b, + a=a, + ) + else: + if delta.mode == "P": + # Convert to L without considering palette + delta_l = Image.new("L", delta.size) + delta_l.putdata(delta.getdata()) + delta = delta_l + mask = ImageMath.eval("convert(im * 255, '1')", im=delta) + diff_frame.paste(fill, mask=ImageOps.invert(mask)) else: bbox = None - im_frames.append({"im": im_frame, "bbox": bbox, "encoderinfo": encoderinfo}) + previous_im = im_frame + im_frames.append( + {"im": diff_frame or im_frame, "bbox": bbox, "encoderinfo": encoderinfo} + ) if len(im_frames) > 1: for frame_data in im_frames: @@ -678,22 +729,10 @@ def get_interlace(im): def _write_local_header(fp, im, offset, flags): - transparent_color_exists = False try: - transparency = int(im.encoderinfo["transparency"]) - except (KeyError, ValueError): - pass - else: - # optimize the block away if transparent color is not used - transparent_color_exists = True - - used_palette_colors = _get_optimize(im, im.encoderinfo) - if used_palette_colors is not None: - # adjust the transparency index after optimize - try: - transparency = used_palette_colors.index(transparency) - except ValueError: - transparent_color_exists = False + transparency = im.encoderinfo["transparency"] + except KeyError: + transparency = None if "duration" in im.encoderinfo: duration = int(im.encoderinfo["duration"] / 10) @@ -702,11 +741,9 @@ def _write_local_header(fp, im, offset, flags): disposal = int(im.encoderinfo.get("disposal", 0)) - if transparent_color_exists or duration != 0 or disposal: - packed_flag = 1 if transparent_color_exists else 0 + if transparency is not None or duration != 0 or disposal: + packed_flag = 1 if transparency is not None else 0 packed_flag |= disposal << 2 - if not transparent_color_exists: - transparency = 0 fp.write( b"!" @@ -714,7 +751,7 @@ def _write_local_header(fp, im, offset, flags): + o8(4) # length + o8(packed_flag) # packed fields + o16(duration) # duration - + o8(transparency) # transparency index + + o8(transparency or 0) # transparency index + o8(0) ) @@ -802,7 +839,7 @@ def _get_optimize(im, info): :param info: encoderinfo :returns: list of indexes of palette entries in use, or None """ - if im.mode in ("P", "L") and info and info.get("optimize", 0): + if im.mode in ("P", "L") and info and info.get("optimize"): # Potentially expensive operation. # The palette saves 3 bytes per color not used, but palette diff --git a/src/PIL/ImagePalette.py b/src/PIL/ImagePalette.py index cb4f1dba1..b7c8d03ab 100644 --- a/src/PIL/ImagePalette.py +++ b/src/PIL/ImagePalette.py @@ -102,6 +102,30 @@ class ImagePalette: # Declare tostring as an alias for tobytes tostring = tobytes + def _new_color_index(self, image=None, e=None): + if not isinstance(self.palette, bytearray): + self._palette = bytearray(self.palette) + index = len(self.palette) // 3 + special_colors = () + if image: + special_colors = ( + image.info.get("background"), + image.info.get("transparency"), + ) + while index in special_colors: + index += 1 + if index >= 256: + if image: + # Search for an unused index + for i, count in reversed(list(enumerate(image.histogram()))): + if count == 0 and i not in special_colors: + index = i + break + if index >= 256: + msg = "cannot allocate more than 256 colors" + raise ValueError(msg) from e + return index + def getcolor(self, color, image=None): """Given an rgb tuple, allocate palette entry. @@ -124,27 +148,7 @@ class ImagePalette: return self.colors[color] except KeyError as e: # allocate new color slot - if not isinstance(self.palette, bytearray): - self._palette = bytearray(self.palette) - index = len(self.palette) // 3 - special_colors = () - if image: - special_colors = ( - image.info.get("background"), - image.info.get("transparency"), - ) - while index in special_colors: - index += 1 - if index >= 256: - if image: - # Search for an unused index - for i, count in reversed(list(enumerate(image.histogram()))): - if count == 0 and i not in special_colors: - index = i - break - if index >= 256: - msg = "cannot allocate more than 256 colors" - raise ValueError(msg) from e + index = self._new_color_index(image, e) self.colors[color] = index if index * 3 < len(self.palette): self._palette = ( From ac38a91816975774fbec6ea738b0d85557f311cb Mon Sep 17 00:00:00 2001 From: Andrew Murray Date: Thu, 14 Dec 2023 23:10:30 +1100 Subject: [PATCH 08/21] Added type hints --- src/PIL/ImageChops.py | 48 ++++++++++++++++++++++++------------------- 1 file changed, 27 insertions(+), 21 deletions(-) diff --git a/src/PIL/ImageChops.py b/src/PIL/ImageChops.py index 0255f41b6..89b4f2d88 100644 --- a/src/PIL/ImageChops.py +++ b/src/PIL/ImageChops.py @@ -18,7 +18,7 @@ from . import Image -def constant(image, value): +def constant(image: Image.Image, value: int) -> Image.Image: """Fill a channel with a given gray level. :rtype: :py:class:`~PIL.Image.Image` @@ -27,7 +27,7 @@ def constant(image, value): return Image.new("L", image.size, value) -def duplicate(image): +def duplicate(image: Image.Image) -> Image.Image: """Copy a channel. Alias for :py:meth:`PIL.Image.Image.copy`. :rtype: :py:class:`~PIL.Image.Image` @@ -36,7 +36,7 @@ def duplicate(image): return image.copy() -def invert(image): +def invert(image: Image.Image) -> Image.Image: """ Invert an image (channel). :: @@ -49,7 +49,7 @@ def invert(image): return image._new(image.im.chop_invert()) -def lighter(image1, image2): +def lighter(image1: Image.Image, image2: Image.Image) -> Image.Image: """ Compares the two images, pixel by pixel, and returns a new image containing the lighter values. :: @@ -64,7 +64,7 @@ def lighter(image1, image2): return image1._new(image1.im.chop_lighter(image2.im)) -def darker(image1, image2): +def darker(image1: Image.Image, image2: Image.Image) -> Image.Image: """ Compares the two images, pixel by pixel, and returns a new image containing the darker values. :: @@ -79,7 +79,7 @@ def darker(image1, image2): return image1._new(image1.im.chop_darker(image2.im)) -def difference(image1, image2): +def difference(image1: Image.Image, image2: Image.Image) -> Image.Image: """ Returns the absolute value of the pixel-by-pixel difference between the two images. :: @@ -94,7 +94,7 @@ def difference(image1, image2): return image1._new(image1.im.chop_difference(image2.im)) -def multiply(image1, image2): +def multiply(image1: Image.Image, image2: Image.Image) -> Image.Image: """ Superimposes two images on top of each other. @@ -111,7 +111,7 @@ def multiply(image1, image2): return image1._new(image1.im.chop_multiply(image2.im)) -def screen(image1, image2): +def screen(image1: Image.Image, image2: Image.Image) -> Image.Image: """ Superimposes two inverted images on top of each other. :: @@ -125,7 +125,7 @@ def screen(image1, image2): return image1._new(image1.im.chop_screen(image2.im)) -def soft_light(image1, image2): +def soft_light(image1: Image.Image, image2: Image.Image) -> Image.Image: """ Superimposes two images on top of each other using the Soft Light algorithm @@ -137,7 +137,7 @@ def soft_light(image1, image2): return image1._new(image1.im.chop_soft_light(image2.im)) -def hard_light(image1, image2): +def hard_light(image1: Image.Image, image2: Image.Image) -> Image.Image: """ Superimposes two images on top of each other using the Hard Light algorithm @@ -149,7 +149,7 @@ def hard_light(image1, image2): return image1._new(image1.im.chop_hard_light(image2.im)) -def overlay(image1, image2): +def overlay(image1: Image.Image, image2: Image.Image) -> Image.Image: """ Superimposes two images on top of each other using the Overlay algorithm @@ -161,7 +161,9 @@ def overlay(image1, image2): return image1._new(image1.im.chop_overlay(image2.im)) -def add(image1, image2, scale=1.0, offset=0): +def add( + image1: Image.Image, image2: Image.Image, scale: float = 1.0, offset: float = 0 +) -> Image.Image: """ Adds two images, dividing the result by scale and adding the offset. If omitted, scale defaults to 1.0, and offset to 0.0. :: @@ -176,7 +178,9 @@ def add(image1, image2, scale=1.0, offset=0): return image1._new(image1.im.chop_add(image2.im, scale, offset)) -def subtract(image1, image2, scale=1.0, offset=0): +def subtract( + image1: Image.Image, image2: Image.Image, scale: float = 1.0, offset: float = 0 +) -> Image.Image: """ Subtracts two images, dividing the result by scale and adding the offset. If omitted, scale defaults to 1.0, and offset to 0.0. :: @@ -191,7 +195,7 @@ def subtract(image1, image2, scale=1.0, offset=0): return image1._new(image1.im.chop_subtract(image2.im, scale, offset)) -def add_modulo(image1, image2): +def add_modulo(image1: Image.Image, image2: Image.Image) -> Image.Image: """Add two images, without clipping the result. :: out = ((image1 + image2) % MAX) @@ -204,7 +208,7 @@ def add_modulo(image1, image2): return image1._new(image1.im.chop_add_modulo(image2.im)) -def subtract_modulo(image1, image2): +def subtract_modulo(image1: Image.Image, image2: Image.Image) -> Image.Image: """Subtract two images, without clipping the result. :: out = ((image1 - image2) % MAX) @@ -217,7 +221,7 @@ def subtract_modulo(image1, image2): return image1._new(image1.im.chop_subtract_modulo(image2.im)) -def logical_and(image1, image2): +def logical_and(image1: Image.Image, image2: Image.Image) -> Image.Image: """Logical AND between two images. Both of the images must have mode "1". If you would like to perform a @@ -235,7 +239,7 @@ def logical_and(image1, image2): return image1._new(image1.im.chop_and(image2.im)) -def logical_or(image1, image2): +def logical_or(image1: Image.Image, image2: Image.Image) -> Image.Image: """Logical OR between two images. Both of the images must have mode "1". :: @@ -250,7 +254,7 @@ def logical_or(image1, image2): return image1._new(image1.im.chop_or(image2.im)) -def logical_xor(image1, image2): +def logical_xor(image1: Image.Image, image2: Image.Image) -> Image.Image: """Logical XOR between two images. Both of the images must have mode "1". :: @@ -265,7 +269,7 @@ def logical_xor(image1, image2): return image1._new(image1.im.chop_xor(image2.im)) -def blend(image1, image2, alpha): +def blend(image1: Image.Image, image2: Image.Image, alpha: float) -> Image.Image: """Blend images using constant transparency weight. Alias for :py:func:`PIL.Image.blend`. @@ -275,7 +279,9 @@ def blend(image1, image2, alpha): return Image.blend(image1, image2, alpha) -def composite(image1, image2, mask): +def composite( + image1: Image.Image, image2: Image.Image, mask: Image.Image +) -> Image.Image: """Create composite using transparency mask. Alias for :py:func:`PIL.Image.composite`. @@ -285,7 +291,7 @@ def composite(image1, image2, mask): return Image.composite(image1, image2, mask) -def offset(image, xoffset, yoffset=None): +def offset(image: Image.Image, xoffset: int, yoffset: int = None) -> Image.Image: """Returns a copy of the image where data has been offset by the given distances. Data wraps around the edges. If ``yoffset`` is omitted, it is assumed to be equal to ``xoffset``. From e482ea9305fd45bbe7cc55394f599fe3d55731c3 Mon Sep 17 00:00:00 2001 From: Andrew Murray <3112309+radarhere@users.noreply.github.com> Date: Fri, 15 Dec 2023 07:57:14 +1100 Subject: [PATCH 09/21] Corrected type hint MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-authored-by: Ondrej Baranovič --- src/PIL/ImageChops.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/PIL/ImageChops.py b/src/PIL/ImageChops.py index 89b4f2d88..81c7f0d0b 100644 --- a/src/PIL/ImageChops.py +++ b/src/PIL/ImageChops.py @@ -291,7 +291,7 @@ def composite( return Image.composite(image1, image2, mask) -def offset(image: Image.Image, xoffset: int, yoffset: int = None) -> Image.Image: +def offset(image: Image.Image, xoffset: int, yoffset: int | None = None) -> Image.Image: """Returns a copy of the image where data has been offset by the given distances. Data wraps around the edges. If ``yoffset`` is omitted, it is assumed to be equal to ``xoffset``. From b60a5827e8266a72b24a12a87898b6e55d328d1a Mon Sep 17 00:00:00 2001 From: Andrew Murray Date: Fri, 15 Dec 2023 07:59:38 +1100 Subject: [PATCH 10/21] Import annotations to allow for pipe as union type --- src/PIL/ImageChops.py | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/PIL/ImageChops.py b/src/PIL/ImageChops.py index 81c7f0d0b..29a5c995f 100644 --- a/src/PIL/ImageChops.py +++ b/src/PIL/ImageChops.py @@ -15,6 +15,8 @@ # See the README file for information on usage and redistribution. # +from __future__ import annotations + from . import Image From 368c05c9dc6f12528df2bbe254f2b6677c61b47f Mon Sep 17 00:00:00 2001 From: Hugo van Kemenade Date: Mon, 18 Dec 2023 18:11:29 +0200 Subject: [PATCH 11/21] Inline isinstance check --- src/PIL/ImageMath.py | 6 +----- 1 file changed, 1 insertion(+), 5 deletions(-) diff --git a/src/PIL/ImageMath.py b/src/PIL/ImageMath.py index 2c73acb97..047187195 100644 --- a/src/PIL/ImageMath.py +++ b/src/PIL/ImageMath.py @@ -20,10 +20,6 @@ import builtins from . import Image, _imagingmath -def _isconstant(v): - return isinstance(v, (int, float)) - - class _Operand: """Wraps an image operand, providing standard operators""" @@ -43,7 +39,7 @@ class _Operand: raise ValueError(msg) else: # argument was a constant - if _isconstant(im1) and self.im.mode in ("1", "L", "I"): + if isinstance(im1, (int, float)) and self.im.mode in ("1", "L", "I"): return Image.new("I", self.im.size, im1) else: return Image.new("F", self.im.size, im1) From 1f9dafec80cd19fdb94f7110fe53d29581ee9b6b Mon Sep 17 00:00:00 2001 From: Andrew Murray Date: Tue, 19 Dec 2023 14:11:00 +1100 Subject: [PATCH 12/21] Added type hints for format and format_description --- src/PIL/Image.py | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/src/PIL/Image.py b/src/PIL/Image.py index ad9df0244..1cb484b85 100644 --- a/src/PIL/Image.py +++ b/src/PIL/Image.py @@ -24,6 +24,8 @@ # See the README file for information on usage and redistribution. # +from __future__ import annotations + import atexit import builtins import io @@ -477,8 +479,8 @@ class Image: * :py:func:`~PIL.Image.frombytes` """ - format = None - format_description = None + format: str | None = None + format_description: str | None = None _close_exclusive_fp_after_loading = True def __init__(self): From b8605eaa84f88e9cde4fe944f073eff9e7feaf89 Mon Sep 17 00:00:00 2001 From: Hugo van Kemenade Date: Fri, 30 Jun 2023 18:50:18 +0300 Subject: [PATCH 13/21] Check types with mypy --- .github/workflows/lint.yml | 6 ++++++ pyproject.toml | 31 +++++++++++++++++++++++++++++++ tox.ini | 7 +++++++ 3 files changed, 44 insertions(+) diff --git a/.github/workflows/lint.yml b/.github/workflows/lint.yml index c8fda7e7f..9069fc615 100644 --- a/.github/workflows/lint.yml +++ b/.github/workflows/lint.yml @@ -2,6 +2,9 @@ name: Lint on: [push, pull_request, workflow_dispatch] +env: + FORCE_COLOR: 1 + permissions: contents: read @@ -46,3 +49,6 @@ jobs: run: tox -e lint env: PRE_COMMIT_COLOR: always + + - name: Mypy + run: tox -e mypy diff --git a/pyproject.toml b/pyproject.toml index f9cea0612..63ee7d42d 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -125,3 +125,34 @@ known-first-party = ["PIL"] [tool.pytest.ini_options] addopts = "-ra --color=yes" testpaths = ["Tests"] + +[tool.mypy] +python_version = "3.8" +pretty = true +disallow_any_generics = true +enable_error_code = "ignore-without-code" +extra_checks = true +follow_imports = "silent" +warn_redundant_casts = true +warn_unreachable = true +warn_unused_ignores = true +exclude = [ + '^src/PIL/_tkinter_finder.py$', + '^src/PIL/DdsImagePlugin.py$', + '^src/PIL/FpxImagePlugin.py$', + '^src/PIL/Image.py$', + '^src/PIL/ImageCms.py$', + '^src/PIL/ImageFile.py$', + '^src/PIL/ImageFont.py$', + '^src/PIL/ImageMath.py$', + '^src/PIL/ImageMorph.py$', + '^src/PIL/ImageQt.py$', + '^src/PIL/ImageShow.py$', + '^src/PIL/ImImagePlugin.py$', + '^src/PIL/MicImagePlugin.py$', + '^src/PIL/PdfParser.py$', + '^src/PIL/PyAccess.py$', + '^src/PIL/TiffImagePlugin.py$', + '^src/PIL/TiffTags.py$', + '^src/PIL/WebPImagePlugin.py$', +] diff --git a/tox.ini b/tox.ini index 5388ed243..7121df049 100644 --- a/tox.ini +++ b/tox.ini @@ -29,3 +29,10 @@ pass_env = commands = pre-commit run --all-files --show-diff-on-failure check-manifest + +[testenv:mypy] +skip_install = true +deps = + mypy==1.7.1 +commands = + mypy src {posargs} From 5db5d6617985747088d3a7bf385446675d20b90b Mon Sep 17 00:00:00 2001 From: Hugo van Kemenade Date: Mon, 18 Dec 2023 15:42:22 +0200 Subject: [PATCH 14/21] Remove default 'line-length = 88' --- pyproject.toml | 1 - 1 file changed, 1 deletion(-) diff --git a/pyproject.toml b/pyproject.toml index 63ee7d42d..a48a4fcc6 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -94,7 +94,6 @@ test-command = "cd {project} && .github/workflows/wheels-test.sh" test-extras = "tests" [tool.ruff] -line-length = 88 select = [ "C4", # flake8-comprehensions "E", # pycodestyle errors From acc8f95f9b232b2b857de660dd6d9637b5617e1f Mon Sep 17 00:00:00 2001 From: Hugo van Kemenade Date: Tue, 19 Dec 2023 11:25:42 +0200 Subject: [PATCH 15/21] Add NumPy to tox for mypy Co-authored-by: Andrew Murray <3112309+radarhere@users.noreply.github.com> --- tox.ini | 1 + 1 file changed, 1 insertion(+) diff --git a/tox.ini b/tox.ini index 7121df049..034d89372 100644 --- a/tox.ini +++ b/tox.ini @@ -34,5 +34,6 @@ commands = skip_install = true deps = mypy==1.7.1 + numpy commands = mypy src {posargs} From bfbfff0b785125a76f74e6571c2af8c0f900a098 Mon Sep 17 00:00:00 2001 From: Andrew Murray Date: Thu, 21 Dec 2023 22:08:38 +1100 Subject: [PATCH 16/21] Update CHANGES.rst [ci skip] --- CHANGES.rst | 15 +++++++++++++++ 1 file changed, 15 insertions(+) diff --git a/CHANGES.rst b/CHANGES.rst index fd25b6f37..f69c3ffa7 100644 --- a/CHANGES.rst +++ b/CHANGES.rst @@ -5,6 +5,21 @@ Changelog (Pillow) 10.2.0 (unreleased) ------------------- +- Attempt memory mapping when tile args is a string #7565 + [radarhere] + +- Fill identical pixels with transparency in subsequent frames when saving GIF #7568 + [radarhere] + +- Corrected duration when combining multiple GIF frames into single frame #7521 + [radarhere] + +- Handle disposing GIF background from outside palette #7515 + [radarhere] + +- Seek past the data when skipping a PSD layer #7483 + [radarhere] + - Import plugins relative to the module #7576 [deliangyang, jaxx0n] From 905ae8b5d1fce478d64b7fbf2c656691d6804a38 Mon Sep 17 00:00:00 2001 From: Hugo van Kemenade Date: Thu, 21 Dec 2023 13:13:07 +0200 Subject: [PATCH 17/21] Add 'from __future__ import annotations' using Ruff/isort --- pyproject.toml | 1 + 1 file changed, 1 insertion(+) diff --git a/pyproject.toml b/pyproject.toml index a48a4fcc6..193e8c9b2 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -120,6 +120,7 @@ extend-ignore = [ [tool.ruff.isort] known-first-party = ["PIL"] +required-imports = ["from __future__ import annotations"] [tool.pytest.ini_options] addopts = "-ra --color=yes" From 43b2f61e7953a4d2586aa0d6ba84426698fc9179 Mon Sep 17 00:00:00 2001 From: Hugo van Kemenade Date: Thu, 21 Dec 2023 13:13:31 +0200 Subject: [PATCH 18/21] Add 'from __future__ import annotations' using Ruff/isort --- .github/workflows/system-info.py | 2 ++ Tests/32bit_segfault_check.py | 1 + Tests/bench_cffi_access.py | 1 + Tests/check_fli_oob.py | 1 + Tests/check_fli_overflow.py | 1 + Tests/check_icns_dos.py | 1 + Tests/check_imaging_leaks.py | 1 + Tests/check_j2k_dos.py | 1 + Tests/check_j2k_leaks.py | 1 + Tests/check_j2k_overflow.py | 1 + Tests/check_jp2_overflow.py | 1 + Tests/check_jpeg_leaks.py | 1 + Tests/check_large_memory.py | 1 + Tests/check_large_memory_numpy.py | 1 + Tests/check_libtiff_segfault.py | 1 + Tests/check_png_dos.py | 1 + Tests/check_release_notes.py | 1 + Tests/check_wheel.py | 1 + Tests/conftest.py | 1 + Tests/createfontdatachunk.py | 1 + Tests/helper.py | 1 + Tests/oss-fuzz/fuzz_font.py | 1 + Tests/oss-fuzz/fuzz_pillow.py | 1 + Tests/oss-fuzz/fuzzers.py | 1 + Tests/oss-fuzz/test_fuzzers.py | 1 + Tests/test_000_sanity.py | 1 + Tests/test_binary.py | 1 + Tests/test_bmp_reference.py | 1 + Tests/test_box_blur.py | 1 + Tests/test_color_lut.py | 1 + Tests/test_core_resources.py | 1 + Tests/test_decompression_bomb.py | 1 + Tests/test_deprecate.py | 1 + Tests/test_features.py | 1 + Tests/test_file_apng.py | 1 + Tests/test_file_blp.py | 1 + Tests/test_file_bmp.py | 1 + Tests/test_file_bufrstub.py | 1 + Tests/test_file_container.py | 1 + Tests/test_file_cur.py | 1 + Tests/test_file_dcx.py | 1 + Tests/test_file_dds.py | 1 + Tests/test_file_eps.py | 1 + Tests/test_file_fits.py | 1 + Tests/test_file_fli.py | 1 + Tests/test_file_fpx.py | 1 + Tests/test_file_ftex.py | 1 + Tests/test_file_gbr.py | 1 + Tests/test_file_gd.py | 1 + Tests/test_file_gif.py | 1 + Tests/test_file_gimpgradient.py | 1 + Tests/test_file_gimppalette.py | 1 + Tests/test_file_gribstub.py | 1 + Tests/test_file_hdf5stub.py | 1 + Tests/test_file_icns.py | 1 + Tests/test_file_ico.py | 1 + Tests/test_file_im.py | 1 + Tests/test_file_imt.py | 1 + Tests/test_file_iptc.py | 1 + Tests/test_file_jpeg.py | 1 + Tests/test_file_jpeg2k.py | 1 + Tests/test_file_libtiff.py | 1 + Tests/test_file_libtiff_small.py | 1 + Tests/test_file_mcidas.py | 1 + Tests/test_file_mic.py | 1 + Tests/test_file_mpo.py | 1 + Tests/test_file_msp.py | 1 + Tests/test_file_palm.py | 1 + Tests/test_file_pcd.py | 1 + Tests/test_file_pcx.py | 1 + Tests/test_file_pdf.py | 1 + Tests/test_file_pixar.py | 1 + Tests/test_file_png.py | 1 + Tests/test_file_ppm.py | 1 + Tests/test_file_psd.py | 1 + Tests/test_file_qoi.py | 1 + Tests/test_file_sgi.py | 1 + Tests/test_file_spider.py | 1 + Tests/test_file_sun.py | 1 + Tests/test_file_tar.py | 1 + Tests/test_file_tga.py | 1 + Tests/test_file_tiff.py | 1 + Tests/test_file_tiff_metadata.py | 1 + Tests/test_file_wal.py | 1 + Tests/test_file_webp.py | 1 + Tests/test_file_webp_alpha.py | 1 + Tests/test_file_webp_animated.py | 1 + Tests/test_file_webp_lossless.py | 1 + Tests/test_file_webp_metadata.py | 1 + Tests/test_file_wmf.py | 1 + Tests/test_file_xbm.py | 1 + Tests/test_file_xpm.py | 1 + Tests/test_file_xvthumb.py | 1 + Tests/test_font_bdf.py | 1 + Tests/test_font_crash.py | 1 + Tests/test_font_leaks.py | 1 + Tests/test_font_pcf.py | 1 + Tests/test_font_pcf_charsets.py | 1 + Tests/test_format_hsv.py | 1 + Tests/test_format_lab.py | 1 + Tests/test_image.py | 1 + Tests/test_image_access.py | 1 + Tests/test_image_array.py | 1 + Tests/test_image_convert.py | 1 + Tests/test_image_copy.py | 1 + Tests/test_image_crop.py | 1 + Tests/test_image_draft.py | 1 + Tests/test_image_entropy.py | 1 + Tests/test_image_filter.py | 1 + Tests/test_image_frombytes.py | 1 + Tests/test_image_fromqimage.py | 1 + Tests/test_image_getbands.py | 1 + Tests/test_image_getbbox.py | 1 + Tests/test_image_getcolors.py | 1 + Tests/test_image_getdata.py | 1 + Tests/test_image_getextrema.py | 1 + Tests/test_image_getim.py | 1 + Tests/test_image_getpalette.py | 1 + Tests/test_image_getprojection.py | 1 + Tests/test_image_histogram.py | 1 + Tests/test_image_load.py | 1 + Tests/test_image_mode.py | 1 + Tests/test_image_paste.py | 1 + Tests/test_image_point.py | 1 + Tests/test_image_putalpha.py | 1 + Tests/test_image_putdata.py | 1 + Tests/test_image_putpalette.py | 1 + Tests/test_image_quantize.py | 1 + Tests/test_image_reduce.py | 1 + Tests/test_image_resample.py | 1 + Tests/test_image_resize.py | 1 + Tests/test_image_rotate.py | 1 + Tests/test_image_split.py | 1 + Tests/test_image_thumbnail.py | 1 + Tests/test_image_tobitmap.py | 1 + Tests/test_image_tobytes.py | 1 + Tests/test_image_transform.py | 1 + Tests/test_image_transpose.py | 1 + Tests/test_imagechops.py | 1 + Tests/test_imagecms.py | 1 + Tests/test_imagecolor.py | 1 + Tests/test_imagedraw.py | 1 + Tests/test_imagedraw2.py | 1 + Tests/test_imageenhance.py | 1 + Tests/test_imagefile.py | 1 + Tests/test_imagefont.py | 1 + Tests/test_imagefontctl.py | 1 + Tests/test_imagefontpil.py | 1 + Tests/test_imagegrab.py | 1 + Tests/test_imagemath.py | 1 + Tests/test_imagemorph.py | 1 + Tests/test_imageops.py | 1 + Tests/test_imageops_usm.py | 1 + Tests/test_imagepalette.py | 1 + Tests/test_imagepath.py | 1 + Tests/test_imageqt.py | 1 + Tests/test_imagesequence.py | 1 + Tests/test_imageshow.py | 1 + Tests/test_imagestat.py | 1 + Tests/test_imagetk.py | 1 + Tests/test_imagewin.py | 1 + Tests/test_imagewin_pointers.py | 1 + Tests/test_lib_image.py | 1 + Tests/test_lib_pack.py | 1 + Tests/test_locale.py | 1 + Tests/test_main.py | 1 + Tests/test_map.py | 1 + Tests/test_mode_i16.py | 1 + Tests/test_numpy.py | 1 + Tests/test_pdfparser.py | 1 + Tests/test_pickle.py | 1 + Tests/test_psdraw.py | 1 + Tests/test_pyroma.py | 1 + Tests/test_qt_image_qapplication.py | 1 + Tests/test_qt_image_toqimage.py | 1 + Tests/test_sgi_crash.py | 1 + Tests/test_shell_injection.py | 1 + Tests/test_tiff_crashes.py | 1 + Tests/test_tiff_ifdrational.py | 1 + Tests/test_uploader.py | 1 + Tests/test_util.py | 1 + Tests/test_webp_leaks.py | 1 + _custom_build/backend.py | 2 ++ conftest.py | 2 ++ docs/Guardfile | 2 ++ docs/conf.py | 1 + docs/example/DdsImagePlugin.py | 1 + docs/example/anchors.py | 2 ++ selftest.py | 1 + setup.py | 1 + src/PIL/BdfFontFile.py | 2 +- src/PIL/BlpImagePlugin.py | 1 + src/PIL/BmpImagePlugin.py | 2 +- src/PIL/BufrStubImagePlugin.py | 1 + src/PIL/ContainerIO.py | 2 +- src/PIL/CurImagePlugin.py | 2 ++ src/PIL/DcxImagePlugin.py | 1 + src/PIL/DdsImagePlugin.py | 1 + src/PIL/EpsImagePlugin.py | 1 + src/PIL/ExifTags.py | 1 + src/PIL/FitsImagePlugin.py | 1 + src/PIL/FliImagePlugin.py | 1 + src/PIL/FontFile.py | 2 +- src/PIL/FpxImagePlugin.py | 2 ++ src/PIL/FtexImagePlugin.py | 1 + src/PIL/GbrImagePlugin.py | 1 + src/PIL/GdImageFile.py | 2 +- src/PIL/GifImagePlugin.py | 1 + src/PIL/GimpGradientFile.py | 2 +- src/PIL/GimpPaletteFile.py | 1 + src/PIL/GribStubImagePlugin.py | 1 + src/PIL/Hdf5StubImagePlugin.py | 1 + src/PIL/IcnsImagePlugin.py | 1 + src/PIL/IcoImagePlugin.py | 2 +- src/PIL/ImImagePlugin.py | 2 +- src/PIL/ImageCms.py | 1 + src/PIL/ImageColor.py | 1 + src/PIL/ImageDraw.py | 1 + src/PIL/ImageDraw2.py | 2 +- src/PIL/ImageEnhance.py | 1 + src/PIL/ImageFilter.py | 2 ++ src/PIL/ImageGrab.py | 1 + src/PIL/ImageMath.py | 1 + src/PIL/ImageMode.py | 1 + src/PIL/ImageMorph.py | 1 + src/PIL/ImageOps.py | 1 + src/PIL/ImagePalette.py | 1 + src/PIL/ImagePath.py | 1 + src/PIL/ImageQt.py | 1 + src/PIL/ImageSequence.py | 1 + src/PIL/ImageShow.py | 2 ++ src/PIL/ImageStat.py | 1 + src/PIL/ImageTk.py | 1 + src/PIL/ImageTransform.py | 1 + src/PIL/ImageWin.py | 1 + src/PIL/ImtImagePlugin.py | 2 +- src/PIL/IptcImagePlugin.py | 2 ++ src/PIL/Jpeg2KImagePlugin.py | 2 ++ src/PIL/JpegImagePlugin.py | 2 ++ src/PIL/JpegPresets.py | 2 ++ src/PIL/McIdasImagePlugin.py | 1 + src/PIL/MicImagePlugin.py | 2 +- src/PIL/MpegImagePlugin.py | 2 +- src/PIL/MpoImagePlugin.py | 1 + src/PIL/MspImagePlugin.py | 1 + src/PIL/PSDraw.py | 1 + src/PIL/PaletteFile.py | 1 + src/PIL/PalmImagePlugin.py | 1 + src/PIL/PcdImagePlugin.py | 2 +- src/PIL/PcfFontFile.py | 1 + src/PIL/PcxImagePlugin.py | 1 + src/PIL/PdfImagePlugin.py | 1 + src/PIL/PdfParser.py | 2 ++ src/PIL/PixarImagePlugin.py | 1 + src/PIL/PngImagePlugin.py | 1 + src/PIL/PpmImagePlugin.py | 2 +- src/PIL/PsdImagePlugin.py | 1 + src/PIL/PyAccess.py | 1 + src/PIL/QoiImagePlugin.py | 1 + src/PIL/SgiImagePlugin.py | 2 +- src/PIL/SpiderImagePlugin.py | 2 ++ src/PIL/SunImagePlugin.py | 2 +- src/PIL/TarIO.py | 1 + src/PIL/TgaImagePlugin.py | 2 +- src/PIL/TiffImagePlugin.py | 2 ++ src/PIL/TiffTags.py | 1 + src/PIL/WalImageFile.py | 1 + src/PIL/WebPImagePlugin.py | 2 ++ src/PIL/WmfImagePlugin.py | 1 + src/PIL/XVThumbImagePlugin.py | 1 + src/PIL/XbmImagePlugin.py | 1 + src/PIL/XpmImagePlugin.py | 2 +- src/PIL/__init__.py | 1 + src/PIL/__main__.py | 2 ++ src/PIL/_binary.py | 2 +- src/PIL/_tkinter_finder.py | 2 ++ src/PIL/_util.py | 2 ++ src/PIL/_version.py | 2 ++ src/PIL/features.py | 2 ++ 279 files changed, 301 insertions(+), 19 deletions(-) diff --git a/.github/workflows/system-info.py b/.github/workflows/system-info.py index 8e840319a..57f28c620 100644 --- a/.github/workflows/system-info.py +++ b/.github/workflows/system-info.py @@ -6,6 +6,8 @@ This sort of info is missing from GitHub Actions. Requested here: https://github.com/actions/virtual-environments/issues/79 """ +from __future__ import annotations + import os import platform import sys diff --git a/Tests/32bit_segfault_check.py b/Tests/32bit_segfault_check.py index 2ff7f908f..06ed2ed2f 100755 --- a/Tests/32bit_segfault_check.py +++ b/Tests/32bit_segfault_check.py @@ -1,4 +1,5 @@ #!/usr/bin/env python3 +from __future__ import annotations import sys diff --git a/Tests/bench_cffi_access.py b/Tests/bench_cffi_access.py index 36ce63296..8a37c7d51 100644 --- a/Tests/bench_cffi_access.py +++ b/Tests/bench_cffi_access.py @@ -1,3 +1,4 @@ +from __future__ import annotations import time from PIL import PyAccess diff --git a/Tests/check_fli_oob.py b/Tests/check_fli_oob.py index 7b3d4d7ee..ac46ff1eb 100644 --- a/Tests/check_fli_oob.py +++ b/Tests/check_fli_oob.py @@ -1,4 +1,5 @@ #!/usr/bin/env python3 +from __future__ import annotations from PIL import Image diff --git a/Tests/check_fli_overflow.py b/Tests/check_fli_overflow.py index c600c45ed..0fabcb5d3 100644 --- a/Tests/check_fli_overflow.py +++ b/Tests/check_fli_overflow.py @@ -1,3 +1,4 @@ +from __future__ import annotations from PIL import Image TEST_FILE = "Tests/images/fli_overflow.fli" diff --git a/Tests/check_icns_dos.py b/Tests/check_icns_dos.py index a34bee45c..ac6be4869 100644 --- a/Tests/check_icns_dos.py +++ b/Tests/check_icns_dos.py @@ -1,5 +1,6 @@ # Tests potential DOS of IcnsImagePlugin with 0 length block. # Run from anywhere that PIL is importable. +from __future__ import annotations from io import BytesIO diff --git a/Tests/check_imaging_leaks.py b/Tests/check_imaging_leaks.py index d07082aba..8c17c051d 100755 --- a/Tests/check_imaging_leaks.py +++ b/Tests/check_imaging_leaks.py @@ -1,4 +1,5 @@ #!/usr/bin/env python3 +from __future__ import annotations import pytest from PIL import Image diff --git a/Tests/check_j2k_dos.py b/Tests/check_j2k_dos.py index 71dcea4f3..2c63c3402 100644 --- a/Tests/check_j2k_dos.py +++ b/Tests/check_j2k_dos.py @@ -1,5 +1,6 @@ # Tests potential DOS of Jpeg2kImagePlugin with 0 length block. # Run from anywhere that PIL is importable. +from __future__ import annotations from io import BytesIO diff --git a/Tests/check_j2k_leaks.py b/Tests/check_j2k_leaks.py index afe5836f3..83a12e2c2 100644 --- a/Tests/check_j2k_leaks.py +++ b/Tests/check_j2k_leaks.py @@ -1,3 +1,4 @@ +from __future__ import annotations from io import BytesIO import pytest diff --git a/Tests/check_j2k_overflow.py b/Tests/check_j2k_overflow.py index b16412898..982f6ea74 100644 --- a/Tests/check_j2k_overflow.py +++ b/Tests/check_j2k_overflow.py @@ -1,3 +1,4 @@ +from __future__ import annotations import pytest from PIL import Image diff --git a/Tests/check_jp2_overflow.py b/Tests/check_jp2_overflow.py index 0210505f5..9afbff112 100755 --- a/Tests/check_jp2_overflow.py +++ b/Tests/check_jp2_overflow.py @@ -12,6 +12,7 @@ # the output should be empty. There may be python issues # in the valgrind especially if run in a debug python # version. +from __future__ import annotations from PIL import Image diff --git a/Tests/check_jpeg_leaks.py b/Tests/check_jpeg_leaks.py index 940c0b00d..3cd37c7af 100644 --- a/Tests/check_jpeg_leaks.py +++ b/Tests/check_jpeg_leaks.py @@ -1,3 +1,4 @@ +from __future__ import annotations from io import BytesIO import pytest diff --git a/Tests/check_large_memory.py b/Tests/check_large_memory.py index d98f4a694..9b83798d5 100644 --- a/Tests/check_large_memory.py +++ b/Tests/check_large_memory.py @@ -1,3 +1,4 @@ +from __future__ import annotations import sys import pytest diff --git a/Tests/check_large_memory_numpy.py b/Tests/check_large_memory_numpy.py index 24cb1f722..0ff3de8dc 100644 --- a/Tests/check_large_memory_numpy.py +++ b/Tests/check_large_memory_numpy.py @@ -1,3 +1,4 @@ +from __future__ import annotations import sys import pytest diff --git a/Tests/check_libtiff_segfault.py b/Tests/check_libtiff_segfault.py index bd7f407e4..ee1d7d11f 100644 --- a/Tests/check_libtiff_segfault.py +++ b/Tests/check_libtiff_segfault.py @@ -1,3 +1,4 @@ +from __future__ import annotations import pytest from PIL import Image diff --git a/Tests/check_png_dos.py b/Tests/check_png_dos.py index f4a129f50..292fe4b7f 100644 --- a/Tests/check_png_dos.py +++ b/Tests/check_png_dos.py @@ -1,3 +1,4 @@ +from __future__ import annotations import zlib from io import BytesIO diff --git a/Tests/check_release_notes.py b/Tests/check_release_notes.py index 0a9a898d7..ebfaffa47 100644 --- a/Tests/check_release_notes.py +++ b/Tests/check_release_notes.py @@ -1,3 +1,4 @@ +from __future__ import annotations import sys from pathlib import Path diff --git a/Tests/check_wheel.py b/Tests/check_wheel.py index cc52cb75e..afe4cc3ee 100644 --- a/Tests/check_wheel.py +++ b/Tests/check_wheel.py @@ -1,3 +1,4 @@ +from __future__ import annotations import sys from PIL import features diff --git a/Tests/conftest.py b/Tests/conftest.py index 66da7593c..cd64bd755 100644 --- a/Tests/conftest.py +++ b/Tests/conftest.py @@ -1,3 +1,4 @@ +from __future__ import annotations import io diff --git a/Tests/createfontdatachunk.py b/Tests/createfontdatachunk.py index e318eb732..2e990b709 100755 --- a/Tests/createfontdatachunk.py +++ b/Tests/createfontdatachunk.py @@ -1,4 +1,5 @@ #!/usr/bin/env python3 +from __future__ import annotations import base64 import os diff --git a/Tests/helper.py b/Tests/helper.py index cce7eca3a..b333c2fd4 100644 --- a/Tests/helper.py +++ b/Tests/helper.py @@ -1,6 +1,7 @@ """ Helper functions. """ +from __future__ import annotations import logging import os diff --git a/Tests/oss-fuzz/fuzz_font.py b/Tests/oss-fuzz/fuzz_font.py index bc2ba9a7e..4e7c7deec 100755 --- a/Tests/oss-fuzz/fuzz_font.py +++ b/Tests/oss-fuzz/fuzz_font.py @@ -13,6 +13,7 @@ # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. +from __future__ import annotations import atheris diff --git a/Tests/oss-fuzz/fuzz_pillow.py b/Tests/oss-fuzz/fuzz_pillow.py index 545daccb6..e7cd0474a 100644 --- a/Tests/oss-fuzz/fuzz_pillow.py +++ b/Tests/oss-fuzz/fuzz_pillow.py @@ -13,6 +13,7 @@ # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. +from __future__ import annotations import atheris diff --git a/Tests/oss-fuzz/fuzzers.py b/Tests/oss-fuzz/fuzzers.py index 10a172b46..3f3c1e388 100644 --- a/Tests/oss-fuzz/fuzzers.py +++ b/Tests/oss-fuzz/fuzzers.py @@ -1,3 +1,4 @@ +from __future__ import annotations import io import warnings diff --git a/Tests/oss-fuzz/test_fuzzers.py b/Tests/oss-fuzz/test_fuzzers.py index 0526f550e..68834045a 100644 --- a/Tests/oss-fuzz/test_fuzzers.py +++ b/Tests/oss-fuzz/test_fuzzers.py @@ -1,3 +1,4 @@ +from __future__ import annotations import subprocess import sys diff --git a/Tests/test_000_sanity.py b/Tests/test_000_sanity.py index 3fd982474..c582dfad3 100644 --- a/Tests/test_000_sanity.py +++ b/Tests/test_000_sanity.py @@ -1,3 +1,4 @@ +from __future__ import annotations from PIL import Image diff --git a/Tests/test_binary.py b/Tests/test_binary.py index 4882e65e6..62da26636 100644 --- a/Tests/test_binary.py +++ b/Tests/test_binary.py @@ -1,3 +1,4 @@ +from __future__ import annotations from PIL import _binary diff --git a/Tests/test_bmp_reference.py b/Tests/test_bmp_reference.py index 002a44a4f..bed8dc3a8 100644 --- a/Tests/test_bmp_reference.py +++ b/Tests/test_bmp_reference.py @@ -1,3 +1,4 @@ +from __future__ import annotations import os import warnings diff --git a/Tests/test_box_blur.py b/Tests/test_box_blur.py index 745364ddc..e798cba3d 100644 --- a/Tests/test_box_blur.py +++ b/Tests/test_box_blur.py @@ -1,3 +1,4 @@ +from __future__ import annotations import pytest from PIL import Image, ImageFilter diff --git a/Tests/test_color_lut.py b/Tests/test_color_lut.py index 6d9a60570..448ba2fac 100644 --- a/Tests/test_color_lut.py +++ b/Tests/test_color_lut.py @@ -1,3 +1,4 @@ +from __future__ import annotations from array import array import pytest diff --git a/Tests/test_core_resources.py b/Tests/test_core_resources.py index 9021a9fb3..5275652f6 100644 --- a/Tests/test_core_resources.py +++ b/Tests/test_core_resources.py @@ -1,3 +1,4 @@ +from __future__ import annotations import sys import pytest diff --git a/Tests/test_decompression_bomb.py b/Tests/test_decompression_bomb.py index 87681a0b5..391948d40 100644 --- a/Tests/test_decompression_bomb.py +++ b/Tests/test_decompression_bomb.py @@ -1,3 +1,4 @@ +from __future__ import annotations import pytest from PIL import Image diff --git a/Tests/test_deprecate.py b/Tests/test_deprecate.py index f175b90af..d45a6603c 100644 --- a/Tests/test_deprecate.py +++ b/Tests/test_deprecate.py @@ -1,3 +1,4 @@ +from __future__ import annotations import pytest from PIL import _deprecate diff --git a/Tests/test_features.py b/Tests/test_features.py index c4e9cd368..8f0e4b418 100644 --- a/Tests/test_features.py +++ b/Tests/test_features.py @@ -1,3 +1,4 @@ +from __future__ import annotations import io import re diff --git a/Tests/test_file_apng.py b/Tests/test_file_apng.py index 1fb97a789..60d951636 100644 --- a/Tests/test_file_apng.py +++ b/Tests/test_file_apng.py @@ -1,3 +1,4 @@ +from __future__ import annotations import pytest from PIL import Image, ImageSequence, PngImagePlugin diff --git a/Tests/test_file_blp.py b/Tests/test_file_blp.py index 8b1355b62..4c1e38d1d 100644 --- a/Tests/test_file_blp.py +++ b/Tests/test_file_blp.py @@ -1,3 +1,4 @@ +from __future__ import annotations import pytest from PIL import Image diff --git a/Tests/test_file_bmp.py b/Tests/test_file_bmp.py index 58a45aa0b..4cc92c5f6 100644 --- a/Tests/test_file_bmp.py +++ b/Tests/test_file_bmp.py @@ -1,3 +1,4 @@ +from __future__ import annotations import io import pytest diff --git a/Tests/test_file_bufrstub.py b/Tests/test_file_bufrstub.py index a7714c92c..5780232a2 100644 --- a/Tests/test_file_bufrstub.py +++ b/Tests/test_file_bufrstub.py @@ -1,3 +1,4 @@ +from __future__ import annotations import pytest from PIL import BufrStubImagePlugin, Image diff --git a/Tests/test_file_container.py b/Tests/test_file_container.py index 65cf6a75e..0da5d3824 100644 --- a/Tests/test_file_container.py +++ b/Tests/test_file_container.py @@ -1,3 +1,4 @@ +from __future__ import annotations import pytest from PIL import ContainerIO, Image diff --git a/Tests/test_file_cur.py b/Tests/test_file_cur.py index f04a20a22..08c3257f9 100644 --- a/Tests/test_file_cur.py +++ b/Tests/test_file_cur.py @@ -1,3 +1,4 @@ +from __future__ import annotations import pytest from PIL import CurImagePlugin, Image diff --git a/Tests/test_file_dcx.py b/Tests/test_file_dcx.py index 22686af34..25e4badbc 100644 --- a/Tests/test_file_dcx.py +++ b/Tests/test_file_dcx.py @@ -1,3 +1,4 @@ +from __future__ import annotations import warnings import pytest diff --git a/Tests/test_file_dds.py b/Tests/test_file_dds.py index 0dd3d5bb9..2d60fbb64 100644 --- a/Tests/test_file_dds.py +++ b/Tests/test_file_dds.py @@ -1,4 +1,5 @@ """Test DdsImagePlugin""" +from __future__ import annotations from io import BytesIO import pytest diff --git a/Tests/test_file_eps.py b/Tests/test_file_eps.py index 259cf75c3..c479c384a 100644 --- a/Tests/test_file_eps.py +++ b/Tests/test_file_eps.py @@ -1,3 +1,4 @@ +from __future__ import annotations import io import pytest diff --git a/Tests/test_file_fits.py b/Tests/test_file_fits.py index 68b3eb567..1383f9c5c 100644 --- a/Tests/test_file_fits.py +++ b/Tests/test_file_fits.py @@ -1,3 +1,4 @@ +from __future__ import annotations from io import BytesIO import pytest diff --git a/Tests/test_file_fli.py b/Tests/test_file_fli.py index f96afdc95..10bf36cc2 100644 --- a/Tests/test_file_fli.py +++ b/Tests/test_file_fli.py @@ -1,3 +1,4 @@ +from __future__ import annotations import warnings import pytest diff --git a/Tests/test_file_fpx.py b/Tests/test_file_fpx.py index 9a1784d31..af3b79815 100644 --- a/Tests/test_file_fpx.py +++ b/Tests/test_file_fpx.py @@ -1,3 +1,4 @@ +from __future__ import annotations import pytest from PIL import Image diff --git a/Tests/test_file_ftex.py b/Tests/test_file_ftex.py index ac6253db0..a494c8029 100644 --- a/Tests/test_file_ftex.py +++ b/Tests/test_file_ftex.py @@ -1,3 +1,4 @@ +from __future__ import annotations import pytest from PIL import FtexImagePlugin, Image diff --git a/Tests/test_file_gbr.py b/Tests/test_file_gbr.py index 1ea8af8ee..7dfe05396 100644 --- a/Tests/test_file_gbr.py +++ b/Tests/test_file_gbr.py @@ -1,3 +1,4 @@ +from __future__ import annotations import pytest from PIL import GbrImagePlugin, Image diff --git a/Tests/test_file_gd.py b/Tests/test_file_gd.py index 5594e5bbb..ec80c54a1 100644 --- a/Tests/test_file_gd.py +++ b/Tests/test_file_gd.py @@ -1,3 +1,4 @@ +from __future__ import annotations import pytest from PIL import GdImageFile, UnidentifiedImageError diff --git a/Tests/test_file_gif.py b/Tests/test_file_gif.py index 0c51a2014..78b77e974 100644 --- a/Tests/test_file_gif.py +++ b/Tests/test_file_gif.py @@ -1,3 +1,4 @@ +from __future__ import annotations import warnings from io import BytesIO diff --git a/Tests/test_file_gimpgradient.py b/Tests/test_file_gimpgradient.py index 3f056fdae..d5be46dc3 100644 --- a/Tests/test_file_gimpgradient.py +++ b/Tests/test_file_gimpgradient.py @@ -1,3 +1,4 @@ +from __future__ import annotations from PIL import GimpGradientFile, ImagePalette diff --git a/Tests/test_file_gimppalette.py b/Tests/test_file_gimppalette.py index caec9cf21..775d3b7cd 100644 --- a/Tests/test_file_gimppalette.py +++ b/Tests/test_file_gimppalette.py @@ -1,3 +1,4 @@ +from __future__ import annotations import pytest from PIL.GimpPaletteFile import GimpPaletteFile diff --git a/Tests/test_file_gribstub.py b/Tests/test_file_gribstub.py index dd1c5e7d2..d962e85a4 100644 --- a/Tests/test_file_gribstub.py +++ b/Tests/test_file_gribstub.py @@ -1,3 +1,4 @@ +from __future__ import annotations import pytest from PIL import GribStubImagePlugin, Image diff --git a/Tests/test_file_hdf5stub.py b/Tests/test_file_hdf5stub.py index 7ca10fac5..9c776b712 100644 --- a/Tests/test_file_hdf5stub.py +++ b/Tests/test_file_hdf5stub.py @@ -1,3 +1,4 @@ +from __future__ import annotations import pytest from PIL import Hdf5StubImagePlugin, Image diff --git a/Tests/test_file_icns.py b/Tests/test_file_icns.py index 42275424d..c62fffc5b 100644 --- a/Tests/test_file_icns.py +++ b/Tests/test_file_icns.py @@ -1,3 +1,4 @@ +from __future__ import annotations import io import os import warnings diff --git a/Tests/test_file_ico.py b/Tests/test_file_ico.py index 4e6dbe6ed..de9fa353a 100644 --- a/Tests/test_file_ico.py +++ b/Tests/test_file_ico.py @@ -1,3 +1,4 @@ +from __future__ import annotations import io import os diff --git a/Tests/test_file_im.py b/Tests/test_file_im.py index fd00f260e..0cb26d06a 100644 --- a/Tests/test_file_im.py +++ b/Tests/test_file_im.py @@ -1,3 +1,4 @@ +from __future__ import annotations import filecmp import warnings diff --git a/Tests/test_file_imt.py b/Tests/test_file_imt.py index f56acc429..3db488558 100644 --- a/Tests/test_file_imt.py +++ b/Tests/test_file_imt.py @@ -1,3 +1,4 @@ +from __future__ import annotations import io import pytest diff --git a/Tests/test_file_iptc.py b/Tests/test_file_iptc.py index dac35a8d0..d0ecde393 100644 --- a/Tests/test_file_iptc.py +++ b/Tests/test_file_iptc.py @@ -1,3 +1,4 @@ +from __future__ import annotations import sys from io import BytesIO, StringIO diff --git a/Tests/test_file_jpeg.py b/Tests/test_file_jpeg.py index ef070b6c5..ffaea6296 100644 --- a/Tests/test_file_jpeg.py +++ b/Tests/test_file_jpeg.py @@ -1,3 +1,4 @@ +from __future__ import annotations import os import re import warnings diff --git a/Tests/test_file_jpeg2k.py b/Tests/test_file_jpeg2k.py index 2016b3ccb..aaa4104e5 100644 --- a/Tests/test_file_jpeg2k.py +++ b/Tests/test_file_jpeg2k.py @@ -1,3 +1,4 @@ +from __future__ import annotations import os import re from io import BytesIO diff --git a/Tests/test_file_libtiff.py b/Tests/test_file_libtiff.py index a7394f1bf..65adf449d 100644 --- a/Tests/test_file_libtiff.py +++ b/Tests/test_file_libtiff.py @@ -1,3 +1,4 @@ +from __future__ import annotations import base64 import io import itertools diff --git a/Tests/test_file_libtiff_small.py b/Tests/test_file_libtiff_small.py index 03137c8b6..9501c55a6 100644 --- a/Tests/test_file_libtiff_small.py +++ b/Tests/test_file_libtiff_small.py @@ -1,3 +1,4 @@ +from __future__ import annotations from io import BytesIO from PIL import Image diff --git a/Tests/test_file_mcidas.py b/Tests/test_file_mcidas.py index 41f22cf0c..4b31aaa78 100644 --- a/Tests/test_file_mcidas.py +++ b/Tests/test_file_mcidas.py @@ -1,3 +1,4 @@ +from __future__ import annotations import pytest from PIL import Image, McIdasImagePlugin diff --git a/Tests/test_file_mic.py b/Tests/test_file_mic.py index 2588d3a05..e7ea39ea9 100644 --- a/Tests/test_file_mic.py +++ b/Tests/test_file_mic.py @@ -1,3 +1,4 @@ +from __future__ import annotations import pytest from PIL import Image, ImagePalette diff --git a/Tests/test_file_mpo.py b/Tests/test_file_mpo.py index 2e921e467..da62bc6d4 100644 --- a/Tests/test_file_mpo.py +++ b/Tests/test_file_mpo.py @@ -1,3 +1,4 @@ +from __future__ import annotations import warnings from io import BytesIO diff --git a/Tests/test_file_msp.py b/Tests/test_file_msp.py index 497052b05..f4e357ae0 100644 --- a/Tests/test_file_msp.py +++ b/Tests/test_file_msp.py @@ -1,3 +1,4 @@ +from __future__ import annotations import os import pytest diff --git a/Tests/test_file_palm.py b/Tests/test_file_palm.py index 926fdb26f..735840de4 100644 --- a/Tests/test_file_palm.py +++ b/Tests/test_file_palm.py @@ -1,3 +1,4 @@ +from __future__ import annotations import os.path import subprocess diff --git a/Tests/test_file_pcd.py b/Tests/test_file_pcd.py index dc45a48c1..596a3414f 100644 --- a/Tests/test_file_pcd.py +++ b/Tests/test_file_pcd.py @@ -1,3 +1,4 @@ +from __future__ import annotations from PIL import Image diff --git a/Tests/test_file_pcx.py b/Tests/test_file_pcx.py index 485adf785..f42ec4a68 100644 --- a/Tests/test_file_pcx.py +++ b/Tests/test_file_pcx.py @@ -1,3 +1,4 @@ +from __future__ import annotations import pytest from PIL import Image, ImageFile, PcxImagePlugin diff --git a/Tests/test_file_pdf.py b/Tests/test_file_pdf.py index ffc392d6b..9e07d9ed0 100644 --- a/Tests/test_file_pdf.py +++ b/Tests/test_file_pdf.py @@ -1,3 +1,4 @@ +from __future__ import annotations import io import os import os.path diff --git a/Tests/test_file_pixar.py b/Tests/test_file_pixar.py index 315ea4676..63779f202 100644 --- a/Tests/test_file_pixar.py +++ b/Tests/test_file_pixar.py @@ -1,3 +1,4 @@ +from __future__ import annotations import pytest from PIL import Image, PixarImagePlugin diff --git a/Tests/test_file_png.py b/Tests/test_file_png.py index b8f481408..ff3862110 100644 --- a/Tests/test_file_png.py +++ b/Tests/test_file_png.py @@ -1,3 +1,4 @@ +from __future__ import annotations import re import sys import warnings diff --git a/Tests/test_file_ppm.py b/Tests/test_file_ppm.py index 292642ca9..bb49a46d3 100644 --- a/Tests/test_file_ppm.py +++ b/Tests/test_file_ppm.py @@ -1,3 +1,4 @@ +from __future__ import annotations import sys from io import BytesIO diff --git a/Tests/test_file_psd.py b/Tests/test_file_psd.py index 708212fa6..8b06ce2b1 100644 --- a/Tests/test_file_psd.py +++ b/Tests/test_file_psd.py @@ -1,3 +1,4 @@ +from __future__ import annotations import warnings import pytest diff --git a/Tests/test_file_qoi.py b/Tests/test_file_qoi.py index 0a835dcf6..b7c945729 100644 --- a/Tests/test_file_qoi.py +++ b/Tests/test_file_qoi.py @@ -1,3 +1,4 @@ +from __future__ import annotations import pytest from PIL import Image, QoiImagePlugin diff --git a/Tests/test_file_sgi.py b/Tests/test_file_sgi.py index 6a5d8887d..13698276b 100644 --- a/Tests/test_file_sgi.py +++ b/Tests/test_file_sgi.py @@ -1,3 +1,4 @@ +from __future__ import annotations import pytest from PIL import Image, SgiImagePlugin diff --git a/Tests/test_file_spider.py b/Tests/test_file_spider.py index 09f1ef8e4..f21098754 100644 --- a/Tests/test_file_spider.py +++ b/Tests/test_file_spider.py @@ -1,3 +1,4 @@ +from __future__ import annotations import tempfile import warnings from io import BytesIO diff --git a/Tests/test_file_sun.py b/Tests/test_file_sun.py index edb320603..874b37b52 100644 --- a/Tests/test_file_sun.py +++ b/Tests/test_file_sun.py @@ -1,3 +1,4 @@ +from __future__ import annotations import os import pytest diff --git a/Tests/test_file_tar.py b/Tests/test_file_tar.py index b27fa25f3..4470823cd 100644 --- a/Tests/test_file_tar.py +++ b/Tests/test_file_tar.py @@ -1,3 +1,4 @@ +from __future__ import annotations import warnings import pytest diff --git a/Tests/test_file_tga.py b/Tests/test_file_tga.py index 1a5730f49..d0f228573 100644 --- a/Tests/test_file_tga.py +++ b/Tests/test_file_tga.py @@ -1,3 +1,4 @@ +from __future__ import annotations import os from glob import glob from itertools import product diff --git a/Tests/test_file_tiff.py b/Tests/test_file_tiff.py index 7362c93ca..0851796d0 100644 --- a/Tests/test_file_tiff.py +++ b/Tests/test_file_tiff.py @@ -1,3 +1,4 @@ +from __future__ import annotations import os import warnings from io import BytesIO diff --git a/Tests/test_file_tiff_metadata.py b/Tests/test_file_tiff_metadata.py index b7d100e7a..edd57e6b5 100644 --- a/Tests/test_file_tiff_metadata.py +++ b/Tests/test_file_tiff_metadata.py @@ -1,3 +1,4 @@ +from __future__ import annotations import io import struct diff --git a/Tests/test_file_wal.py b/Tests/test_file_wal.py index 4be46e9d6..0b84d0320 100644 --- a/Tests/test_file_wal.py +++ b/Tests/test_file_wal.py @@ -1,3 +1,4 @@ +from __future__ import annotations from PIL import WalImageFile from .helper import assert_image_equal_tofile diff --git a/Tests/test_file_webp.py b/Tests/test_file_webp.py index 30938e971..c91818ef6 100644 --- a/Tests/test_file_webp.py +++ b/Tests/test_file_webp.py @@ -1,3 +1,4 @@ +from __future__ import annotations import io import re import sys diff --git a/Tests/test_file_webp_alpha.py b/Tests/test_file_webp_alpha.py index 5970fd2a3..79d01a444 100644 --- a/Tests/test_file_webp_alpha.py +++ b/Tests/test_file_webp_alpha.py @@ -1,3 +1,4 @@ +from __future__ import annotations import pytest from PIL import Image diff --git a/Tests/test_file_webp_animated.py b/Tests/test_file_webp_animated.py index 2fd5e5484..22acb4be6 100644 --- a/Tests/test_file_webp_animated.py +++ b/Tests/test_file_webp_animated.py @@ -1,3 +1,4 @@ +from __future__ import annotations import pytest from packaging.version import parse as parse_version diff --git a/Tests/test_file_webp_lossless.py b/Tests/test_file_webp_lossless.py index 2da443628..6acf58ac3 100644 --- a/Tests/test_file_webp_lossless.py +++ b/Tests/test_file_webp_lossless.py @@ -1,3 +1,4 @@ +from __future__ import annotations import pytest from PIL import Image diff --git a/Tests/test_file_webp_metadata.py b/Tests/test_file_webp_metadata.py index dd47be8b2..a7b7bbcf6 100644 --- a/Tests/test_file_webp_metadata.py +++ b/Tests/test_file_webp_metadata.py @@ -1,3 +1,4 @@ +from __future__ import annotations from io import BytesIO import pytest diff --git a/Tests/test_file_wmf.py b/Tests/test_file_wmf.py index 7c8b54fd1..596dc8ba1 100644 --- a/Tests/test_file_wmf.py +++ b/Tests/test_file_wmf.py @@ -1,3 +1,4 @@ +from __future__ import annotations import pytest from PIL import Image, WmfImagePlugin diff --git a/Tests/test_file_xbm.py b/Tests/test_file_xbm.py index d2c05b78a..b086ffd68 100644 --- a/Tests/test_file_xbm.py +++ b/Tests/test_file_xbm.py @@ -1,3 +1,4 @@ +from __future__ import annotations from io import BytesIO import pytest diff --git a/Tests/test_file_xpm.py b/Tests/test_file_xpm.py index 8595b07eb..265feab42 100644 --- a/Tests/test_file_xpm.py +++ b/Tests/test_file_xpm.py @@ -1,3 +1,4 @@ +from __future__ import annotations import pytest from PIL import Image, XpmImagePlugin diff --git a/Tests/test_file_xvthumb.py b/Tests/test_file_xvthumb.py index 9efe7ec14..5848995c1 100644 --- a/Tests/test_file_xvthumb.py +++ b/Tests/test_file_xvthumb.py @@ -1,3 +1,4 @@ +from __future__ import annotations import pytest from PIL import Image, XVThumbImagePlugin diff --git a/Tests/test_font_bdf.py b/Tests/test_font_bdf.py index 1e7caee32..1e5eff2f1 100644 --- a/Tests/test_font_bdf.py +++ b/Tests/test_font_bdf.py @@ -1,3 +1,4 @@ +from __future__ import annotations import pytest from PIL import BdfFontFile, FontFile diff --git a/Tests/test_font_crash.py b/Tests/test_font_crash.py index 27663f396..388ee7118 100644 --- a/Tests/test_font_crash.py +++ b/Tests/test_font_crash.py @@ -1,3 +1,4 @@ +from __future__ import annotations import pytest from PIL import Image, ImageDraw, ImageFont diff --git a/Tests/test_font_leaks.py b/Tests/test_font_leaks.py index 38f7ddac5..6a038bb40 100644 --- a/Tests/test_font_leaks.py +++ b/Tests/test_font_leaks.py @@ -1,3 +1,4 @@ +from __future__ import annotations from PIL import Image, ImageDraw, ImageFont from .helper import PillowLeakTestCase, skip_unless_feature diff --git a/Tests/test_font_pcf.py b/Tests/test_font_pcf.py index 815ef1d92..4365b9310 100644 --- a/Tests/test_font_pcf.py +++ b/Tests/test_font_pcf.py @@ -1,3 +1,4 @@ +from __future__ import annotations import os import pytest diff --git a/Tests/test_font_pcf_charsets.py b/Tests/test_font_pcf_charsets.py index 664663fd6..950e5029f 100644 --- a/Tests/test_font_pcf_charsets.py +++ b/Tests/test_font_pcf_charsets.py @@ -1,3 +1,4 @@ +from __future__ import annotations import os import pytest diff --git a/Tests/test_format_hsv.py b/Tests/test_format_hsv.py index b485e854f..fd47fae39 100644 --- a/Tests/test_format_hsv.py +++ b/Tests/test_format_hsv.py @@ -1,3 +1,4 @@ +from __future__ import annotations import colorsys import itertools diff --git a/Tests/test_format_lab.py b/Tests/test_format_lab.py index 41c8efdf3..c7610ce8a 100644 --- a/Tests/test_format_lab.py +++ b/Tests/test_format_lab.py @@ -1,3 +1,4 @@ +from __future__ import annotations from PIL import Image diff --git a/Tests/test_image.py b/Tests/test_image.py index f0861bb4f..615e00e40 100644 --- a/Tests/test_image.py +++ b/Tests/test_image.py @@ -1,3 +1,4 @@ +from __future__ import annotations import io import logging import os diff --git a/Tests/test_image_access.py b/Tests/test_image_access.py index 2b4fb7733..4a794371d 100644 --- a/Tests/test_image_access.py +++ b/Tests/test_image_access.py @@ -1,3 +1,4 @@ +from __future__ import annotations import os import subprocess import sys diff --git a/Tests/test_image_array.py b/Tests/test_image_array.py index ae3518e44..b3e5d9e3e 100644 --- a/Tests/test_image_array.py +++ b/Tests/test_image_array.py @@ -1,3 +1,4 @@ +from __future__ import annotations import pytest from packaging.version import parse as parse_version diff --git a/Tests/test_image_convert.py b/Tests/test_image_convert.py index f5775f09c..7c17040d3 100644 --- a/Tests/test_image_convert.py +++ b/Tests/test_image_convert.py @@ -1,3 +1,4 @@ +from __future__ import annotations import pytest from PIL import Image diff --git a/Tests/test_image_copy.py b/Tests/test_image_copy.py index cd602fc76..abf5f846f 100644 --- a/Tests/test_image_copy.py +++ b/Tests/test_image_copy.py @@ -1,3 +1,4 @@ +from __future__ import annotations import copy import pytest diff --git a/Tests/test_image_crop.py b/Tests/test_image_crop.py index daf8c8da1..0bb54e5d8 100644 --- a/Tests/test_image_crop.py +++ b/Tests/test_image_crop.py @@ -1,3 +1,4 @@ +from __future__ import annotations import pytest from PIL import Image diff --git a/Tests/test_image_draft.py b/Tests/test_image_draft.py index 8b4b44768..774272dd1 100644 --- a/Tests/test_image_draft.py +++ b/Tests/test_image_draft.py @@ -1,3 +1,4 @@ +from __future__ import annotations from PIL import Image from .helper import fromstring, skip_unless_feature, tostring diff --git a/Tests/test_image_entropy.py b/Tests/test_image_entropy.py index ea5886e72..031fceda3 100644 --- a/Tests/test_image_entropy.py +++ b/Tests/test_image_entropy.py @@ -1,3 +1,4 @@ +from __future__ import annotations from .helper import hopper diff --git a/Tests/test_image_filter.py b/Tests/test_image_filter.py index a7932a351..5bd7ee0d2 100644 --- a/Tests/test_image_filter.py +++ b/Tests/test_image_filter.py @@ -1,3 +1,4 @@ +from __future__ import annotations import pytest from PIL import Image, ImageFilter diff --git a/Tests/test_image_frombytes.py b/Tests/test_image_frombytes.py index c299e4544..017da499d 100644 --- a/Tests/test_image_frombytes.py +++ b/Tests/test_image_frombytes.py @@ -1,3 +1,4 @@ +from __future__ import annotations import pytest from PIL import Image diff --git a/Tests/test_image_fromqimage.py b/Tests/test_image_fromqimage.py index 7fe992353..b3ca43bde 100644 --- a/Tests/test_image_fromqimage.py +++ b/Tests/test_image_fromqimage.py @@ -1,3 +1,4 @@ +from __future__ import annotations import warnings import pytest diff --git a/Tests/test_image_getbands.py b/Tests/test_image_getbands.py index 08fc12c1c..e7701dbc4 100644 --- a/Tests/test_image_getbands.py +++ b/Tests/test_image_getbands.py @@ -1,3 +1,4 @@ +from __future__ import annotations from PIL import Image diff --git a/Tests/test_image_getbbox.py b/Tests/test_image_getbbox.py index afca66703..9e792cfdf 100644 --- a/Tests/test_image_getbbox.py +++ b/Tests/test_image_getbbox.py @@ -1,3 +1,4 @@ +from __future__ import annotations import pytest from PIL import Image diff --git a/Tests/test_image_getcolors.py b/Tests/test_image_getcolors.py index 7fd0398f9..dea3a60a1 100644 --- a/Tests/test_image_getcolors.py +++ b/Tests/test_image_getcolors.py @@ -1,3 +1,4 @@ +from __future__ import annotations from .helper import hopper diff --git a/Tests/test_image_getdata.py b/Tests/test_image_getdata.py index 36c81b40f..873cc65bf 100644 --- a/Tests/test_image_getdata.py +++ b/Tests/test_image_getdata.py @@ -1,3 +1,4 @@ +from __future__ import annotations from PIL import Image from .helper import hopper diff --git a/Tests/test_image_getextrema.py b/Tests/test_image_getextrema.py index 710794da4..b17c8a786 100644 --- a/Tests/test_image_getextrema.py +++ b/Tests/test_image_getextrema.py @@ -1,3 +1,4 @@ +from __future__ import annotations from PIL import Image from .helper import hopper diff --git a/Tests/test_image_getim.py b/Tests/test_image_getim.py index 746e63b15..e969c8164 100644 --- a/Tests/test_image_getim.py +++ b/Tests/test_image_getim.py @@ -1,3 +1,4 @@ +from __future__ import annotations from .helper import hopper diff --git a/Tests/test_image_getpalette.py b/Tests/test_image_getpalette.py index 58a6dacbb..a5be972d3 100644 --- a/Tests/test_image_getpalette.py +++ b/Tests/test_image_getpalette.py @@ -1,3 +1,4 @@ +from __future__ import annotations from PIL import Image from .helper import hopper diff --git a/Tests/test_image_getprojection.py b/Tests/test_image_getprojection.py index f65d40708..aa47be3b2 100644 --- a/Tests/test_image_getprojection.py +++ b/Tests/test_image_getprojection.py @@ -1,3 +1,4 @@ +from __future__ import annotations from PIL import Image from .helper import hopper diff --git a/Tests/test_image_histogram.py b/Tests/test_image_histogram.py index 0ee52e724..7ba2f10b7 100644 --- a/Tests/test_image_histogram.py +++ b/Tests/test_image_histogram.py @@ -1,3 +1,4 @@ +from __future__ import annotations from .helper import hopper diff --git a/Tests/test_image_load.py b/Tests/test_image_load.py index f7fe99bb4..17847c4fd 100644 --- a/Tests/test_image_load.py +++ b/Tests/test_image_load.py @@ -1,3 +1,4 @@ +from __future__ import annotations import logging import os diff --git a/Tests/test_image_mode.py b/Tests/test_image_mode.py index e4c8bb9df..ad90d1250 100644 --- a/Tests/test_image_mode.py +++ b/Tests/test_image_mode.py @@ -1,3 +1,4 @@ +from __future__ import annotations import pytest from PIL import Image, ImageMode diff --git a/Tests/test_image_paste.py b/Tests/test_image_paste.py index 1ab02017d..0b87f6072 100644 --- a/Tests/test_image_paste.py +++ b/Tests/test_image_paste.py @@ -1,3 +1,4 @@ +from __future__ import annotations import pytest from PIL import Image diff --git a/Tests/test_image_point.py b/Tests/test_image_point.py index c406cb8ec..fce45ec4f 100644 --- a/Tests/test_image_point.py +++ b/Tests/test_image_point.py @@ -1,3 +1,4 @@ +from __future__ import annotations import pytest from .helper import assert_image_equal, hopper diff --git a/Tests/test_image_putalpha.py b/Tests/test_image_putalpha.py index e2dcead34..0ba7e5919 100644 --- a/Tests/test_image_putalpha.py +++ b/Tests/test_image_putalpha.py @@ -1,3 +1,4 @@ +from __future__ import annotations from PIL import Image diff --git a/Tests/test_image_putdata.py b/Tests/test_image_putdata.py index 4e40aec74..d3cb13e2e 100644 --- a/Tests/test_image_putdata.py +++ b/Tests/test_image_putdata.py @@ -1,3 +1,4 @@ +from __future__ import annotations import sys from array import array diff --git a/Tests/test_image_putpalette.py b/Tests/test_image_putpalette.py index 376553344..de2d90242 100644 --- a/Tests/test_image_putpalette.py +++ b/Tests/test_image_putpalette.py @@ -1,3 +1,4 @@ +from __future__ import annotations import pytest from PIL import Image, ImagePalette diff --git a/Tests/test_image_quantize.py b/Tests/test_image_quantize.py index 3bafc4c9c..54c567aae 100644 --- a/Tests/test_image_quantize.py +++ b/Tests/test_image_quantize.py @@ -1,3 +1,4 @@ +from __future__ import annotations import pytest from packaging.version import parse as parse_version diff --git a/Tests/test_image_reduce.py b/Tests/test_image_reduce.py index ae8d740a0..a4d0f5107 100644 --- a/Tests/test_image_reduce.py +++ b/Tests/test_image_reduce.py @@ -1,3 +1,4 @@ +from __future__ import annotations import pytest from PIL import Image, ImageMath, ImageMode diff --git a/Tests/test_image_resample.py b/Tests/test_image_resample.py index be49955dd..b4bf6c8df 100644 --- a/Tests/test_image_resample.py +++ b/Tests/test_image_resample.py @@ -1,3 +1,4 @@ +from __future__ import annotations from contextlib import contextmanager import pytest diff --git a/Tests/test_image_resize.py b/Tests/test_image_resize.py index b5bfa903f..0d3b43ee2 100644 --- a/Tests/test_image_resize.py +++ b/Tests/test_image_resize.py @@ -1,6 +1,7 @@ """ Tests for resize functionality. """ +from __future__ import annotations from itertools import permutations import pytest diff --git a/Tests/test_image_rotate.py b/Tests/test_image_rotate.py index 82fe46b7d..0931aa32d 100644 --- a/Tests/test_image_rotate.py +++ b/Tests/test_image_rotate.py @@ -1,3 +1,4 @@ +from __future__ import annotations import pytest from PIL import Image diff --git a/Tests/test_image_split.py b/Tests/test_image_split.py index 5cb7c9a8b..707508250 100644 --- a/Tests/test_image_split.py +++ b/Tests/test_image_split.py @@ -1,3 +1,4 @@ +from __future__ import annotations import pytest from PIL import Image, features diff --git a/Tests/test_image_thumbnail.py b/Tests/test_image_thumbnail.py index 96a2c2662..9e6796ca2 100644 --- a/Tests/test_image_thumbnail.py +++ b/Tests/test_image_thumbnail.py @@ -1,3 +1,4 @@ +from __future__ import annotations import pytest from PIL import Image diff --git a/Tests/test_image_tobitmap.py b/Tests/test_image_tobitmap.py index a12ce329f..156b9919d 100644 --- a/Tests/test_image_tobitmap.py +++ b/Tests/test_image_tobitmap.py @@ -1,3 +1,4 @@ +from __future__ import annotations import pytest from .helper import assert_image_equal, fromstring, hopper diff --git a/Tests/test_image_tobytes.py b/Tests/test_image_tobytes.py index 31e1c0080..f6042bca5 100644 --- a/Tests/test_image_tobytes.py +++ b/Tests/test_image_tobytes.py @@ -1,3 +1,4 @@ +from __future__ import annotations from .helper import hopper diff --git a/Tests/test_image_transform.py b/Tests/test_image_transform.py index 64a5c9459..15939ef64 100644 --- a/Tests/test_image_transform.py +++ b/Tests/test_image_transform.py @@ -1,3 +1,4 @@ +from __future__ import annotations import math import pytest diff --git a/Tests/test_image_transpose.py b/Tests/test_image_transpose.py index 877f439ca..66a2d9e29 100644 --- a/Tests/test_image_transpose.py +++ b/Tests/test_image_transpose.py @@ -1,3 +1,4 @@ +from __future__ import annotations import pytest from PIL.Image import Transpose diff --git a/Tests/test_imagechops.py b/Tests/test_imagechops.py index e7687cc1b..8e3a738d7 100644 --- a/Tests/test_imagechops.py +++ b/Tests/test_imagechops.py @@ -1,3 +1,4 @@ +from __future__ import annotations from PIL import Image, ImageChops from .helper import assert_image_equal, hopper diff --git a/Tests/test_imagecms.py b/Tests/test_imagecms.py index 8efe063c1..0dde82bd7 100644 --- a/Tests/test_imagecms.py +++ b/Tests/test_imagecms.py @@ -1,3 +1,4 @@ +from __future__ import annotations import datetime import os import re diff --git a/Tests/test_imagecolor.py b/Tests/test_imagecolor.py index 2fae6151c..c0ffd2ebf 100644 --- a/Tests/test_imagecolor.py +++ b/Tests/test_imagecolor.py @@ -1,3 +1,4 @@ +from __future__ import annotations import pytest from PIL import Image, ImageColor diff --git a/Tests/test_imagedraw.py b/Tests/test_imagedraw.py index 4052c41ff..379fe78cd 100644 --- a/Tests/test_imagedraw.py +++ b/Tests/test_imagedraw.py @@ -1,3 +1,4 @@ +from __future__ import annotations import contextlib import os.path diff --git a/Tests/test_imagedraw2.py b/Tests/test_imagedraw2.py index a2c2fa1f0..d729af14d 100644 --- a/Tests/test_imagedraw2.py +++ b/Tests/test_imagedraw2.py @@ -1,3 +1,4 @@ +from __future__ import annotations import os.path import pytest diff --git a/Tests/test_imageenhance.py b/Tests/test_imageenhance.py index 221ef8cdb..f4e4d59be 100644 --- a/Tests/test_imageenhance.py +++ b/Tests/test_imageenhance.py @@ -1,3 +1,4 @@ +from __future__ import annotations import pytest from PIL import Image, ImageEnhance diff --git a/Tests/test_imagefile.py b/Tests/test_imagefile.py index 2389c4717..4804a554f 100644 --- a/Tests/test_imagefile.py +++ b/Tests/test_imagefile.py @@ -1,3 +1,4 @@ +from __future__ import annotations from io import BytesIO import pytest diff --git a/Tests/test_imagefont.py b/Tests/test_imagefont.py index 0f1c52b66..6ad56e2b1 100644 --- a/Tests/test_imagefont.py +++ b/Tests/test_imagefont.py @@ -1,3 +1,4 @@ +from __future__ import annotations import copy import os import re diff --git a/Tests/test_imagefontctl.py b/Tests/test_imagefontctl.py index 6099b04e4..bea532b05 100644 --- a/Tests/test_imagefontctl.py +++ b/Tests/test_imagefontctl.py @@ -1,3 +1,4 @@ +from __future__ import annotations import pytest from PIL import Image, ImageDraw, ImageFont diff --git a/Tests/test_imagefontpil.py b/Tests/test_imagefontpil.py index c30463e81..21b4dee3c 100644 --- a/Tests/test_imagefontpil.py +++ b/Tests/test_imagefontpil.py @@ -1,3 +1,4 @@ +from __future__ import annotations import pytest from PIL import Image, ImageDraw, ImageFont, features diff --git a/Tests/test_imagegrab.py b/Tests/test_imagegrab.py index a75cbadc4..b7683ec18 100644 --- a/Tests/test_imagegrab.py +++ b/Tests/test_imagegrab.py @@ -1,3 +1,4 @@ +from __future__ import annotations import os import shutil import subprocess diff --git a/Tests/test_imagemath.py b/Tests/test_imagemath.py index fe7ac9a7a..22de86c7c 100644 --- a/Tests/test_imagemath.py +++ b/Tests/test_imagemath.py @@ -1,3 +1,4 @@ +from __future__ import annotations import pytest from PIL import Image, ImageMath diff --git a/Tests/test_imagemorph.py b/Tests/test_imagemorph.py index 29c71f917..ec55aadf9 100644 --- a/Tests/test_imagemorph.py +++ b/Tests/test_imagemorph.py @@ -1,4 +1,5 @@ # Test the ImageMorphology functionality +from __future__ import annotations import pytest from PIL import Image, ImageMorph, _imagingmorph diff --git a/Tests/test_imageops.py b/Tests/test_imageops.py index a3bb536ce..7980bead0 100644 --- a/Tests/test_imageops.py +++ b/Tests/test_imageops.py @@ -1,3 +1,4 @@ +from __future__ import annotations import pytest from PIL import Image, ImageDraw, ImageOps, ImageStat, features diff --git a/Tests/test_imageops_usm.py b/Tests/test_imageops_usm.py index 8837ed2a2..84d3a6950 100644 --- a/Tests/test_imageops_usm.py +++ b/Tests/test_imageops_usm.py @@ -1,3 +1,4 @@ +from __future__ import annotations import pytest from PIL import Image, ImageFilter diff --git a/Tests/test_imagepalette.py b/Tests/test_imagepalette.py index baa698bb4..e5b59b74a 100644 --- a/Tests/test_imagepalette.py +++ b/Tests/test_imagepalette.py @@ -1,3 +1,4 @@ +from __future__ import annotations import pytest from PIL import Image, ImagePalette diff --git a/Tests/test_imagepath.py b/Tests/test_imagepath.py index c112cfd87..ac3ea3281 100644 --- a/Tests/test_imagepath.py +++ b/Tests/test_imagepath.py @@ -1,3 +1,4 @@ +from __future__ import annotations import array import math import struct diff --git a/Tests/test_imageqt.py b/Tests/test_imageqt.py index 2c73a2094..41d247f42 100644 --- a/Tests/test_imageqt.py +++ b/Tests/test_imageqt.py @@ -1,3 +1,4 @@ +from __future__ import annotations import warnings import pytest diff --git a/Tests/test_imagesequence.py b/Tests/test_imagesequence.py index 62f528332..6d71e4d87 100644 --- a/Tests/test_imagesequence.py +++ b/Tests/test_imagesequence.py @@ -1,3 +1,4 @@ +from __future__ import annotations import pytest from PIL import Image, ImageSequence, TiffImagePlugin diff --git a/Tests/test_imageshow.py b/Tests/test_imageshow.py index 3e73339ed..761d28d30 100644 --- a/Tests/test_imageshow.py +++ b/Tests/test_imageshow.py @@ -1,3 +1,4 @@ +from __future__ import annotations import pytest from PIL import Image, ImageShow diff --git a/Tests/test_imagestat.py b/Tests/test_imagestat.py index b3b5db13f..7b56b89cc 100644 --- a/Tests/test_imagestat.py +++ b/Tests/test_imagestat.py @@ -1,3 +1,4 @@ +from __future__ import annotations import pytest from PIL import Image, ImageStat diff --git a/Tests/test_imagetk.py b/Tests/test_imagetk.py index a0c9574ba..bb20fbb6f 100644 --- a/Tests/test_imagetk.py +++ b/Tests/test_imagetk.py @@ -1,3 +1,4 @@ +from __future__ import annotations import pytest from PIL import Image diff --git a/Tests/test_imagewin.py b/Tests/test_imagewin.py index 5e489284f..6927eedcf 100644 --- a/Tests/test_imagewin.py +++ b/Tests/test_imagewin.py @@ -1,3 +1,4 @@ +from __future__ import annotations import pytest from PIL import ImageWin diff --git a/Tests/test_imagewin_pointers.py b/Tests/test_imagewin_pointers.py index df1305655..bd154335a 100644 --- a/Tests/test_imagewin_pointers.py +++ b/Tests/test_imagewin_pointers.py @@ -1,3 +1,4 @@ +from __future__ import annotations from io import BytesIO from PIL import Image, ImageWin diff --git a/Tests/test_lib_image.py b/Tests/test_lib_image.py index f6818be46..92cad4ac1 100644 --- a/Tests/test_lib_image.py +++ b/Tests/test_lib_image.py @@ -1,3 +1,4 @@ +from __future__ import annotations import pytest from PIL import Image diff --git a/Tests/test_lib_pack.py b/Tests/test_lib_pack.py index 2a4d9acf4..1293f7628 100644 --- a/Tests/test_lib_pack.py +++ b/Tests/test_lib_pack.py @@ -1,3 +1,4 @@ +from __future__ import annotations import sys import pytest diff --git a/Tests/test_locale.py b/Tests/test_locale.py index 7a07fbbe0..49b052fa4 100644 --- a/Tests/test_locale.py +++ b/Tests/test_locale.py @@ -1,3 +1,4 @@ +from __future__ import annotations import locale import pytest diff --git a/Tests/test_main.py b/Tests/test_main.py index 46ff63c4e..a84e61a7b 100644 --- a/Tests/test_main.py +++ b/Tests/test_main.py @@ -1,3 +1,4 @@ +from __future__ import annotations import os import subprocess import sys diff --git a/Tests/test_map.py b/Tests/test_map.py index d816bddaf..76444f33d 100644 --- a/Tests/test_map.py +++ b/Tests/test_map.py @@ -1,3 +1,4 @@ +from __future__ import annotations import sys import pytest diff --git a/Tests/test_mode_i16.py b/Tests/test_mode_i16.py index 1786dba38..3e17d8dcc 100644 --- a/Tests/test_mode_i16.py +++ b/Tests/test_mode_i16.py @@ -1,3 +1,4 @@ +from __future__ import annotations import pytest from PIL import Image diff --git a/Tests/test_numpy.py b/Tests/test_numpy.py index 147f94a71..6f0e99b3f 100644 --- a/Tests/test_numpy.py +++ b/Tests/test_numpy.py @@ -1,3 +1,4 @@ +from __future__ import annotations import warnings import pytest diff --git a/Tests/test_pdfparser.py b/Tests/test_pdfparser.py index 105a838d9..aeeafb6f1 100644 --- a/Tests/test_pdfparser.py +++ b/Tests/test_pdfparser.py @@ -1,3 +1,4 @@ +from __future__ import annotations import time import pytest diff --git a/Tests/test_pickle.py b/Tests/test_pickle.py index 1c5d482bd..eb687b57b 100644 --- a/Tests/test_pickle.py +++ b/Tests/test_pickle.py @@ -1,3 +1,4 @@ +from __future__ import annotations import pickle import pytest diff --git a/Tests/test_psdraw.py b/Tests/test_psdraw.py index e74d79828..77c7952e9 100644 --- a/Tests/test_psdraw.py +++ b/Tests/test_psdraw.py @@ -1,3 +1,4 @@ +from __future__ import annotations import os import sys from io import BytesIO diff --git a/Tests/test_pyroma.py b/Tests/test_pyroma.py index aa05c2cfd..08133b6c3 100644 --- a/Tests/test_pyroma.py +++ b/Tests/test_pyroma.py @@ -1,3 +1,4 @@ +from __future__ import annotations import pytest from PIL import __version__ diff --git a/Tests/test_qt_image_qapplication.py b/Tests/test_qt_image_qapplication.py index 5d2e41212..49ca01677 100644 --- a/Tests/test_qt_image_qapplication.py +++ b/Tests/test_qt_image_qapplication.py @@ -1,3 +1,4 @@ +from __future__ import annotations import pytest from PIL import ImageQt diff --git a/Tests/test_qt_image_toqimage.py b/Tests/test_qt_image_toqimage.py index 95c13ba75..396bd9080 100644 --- a/Tests/test_qt_image_toqimage.py +++ b/Tests/test_qt_image_toqimage.py @@ -1,3 +1,4 @@ +from __future__ import annotations import pytest from PIL import ImageQt diff --git a/Tests/test_sgi_crash.py b/Tests/test_sgi_crash.py index b5f9d4424..37d72d451 100644 --- a/Tests/test_sgi_crash.py +++ b/Tests/test_sgi_crash.py @@ -1,3 +1,4 @@ +from __future__ import annotations import pytest from PIL import Image diff --git a/Tests/test_shell_injection.py b/Tests/test_shell_injection.py index d25d42dfc..d93b03904 100644 --- a/Tests/test_shell_injection.py +++ b/Tests/test_shell_injection.py @@ -1,3 +1,4 @@ +from __future__ import annotations import shutil import pytest diff --git a/Tests/test_tiff_crashes.py b/Tests/test_tiff_crashes.py index 143765b8e..64e781cba 100644 --- a/Tests/test_tiff_crashes.py +++ b/Tests/test_tiff_crashes.py @@ -10,6 +10,7 @@ # the output should be empty. There may be Python issues # in the valgrind especially if run in a debug Python # version. +from __future__ import annotations import pytest diff --git a/Tests/test_tiff_ifdrational.py b/Tests/test_tiff_ifdrational.py index 6e3fcec90..e7b41fb47 100644 --- a/Tests/test_tiff_ifdrational.py +++ b/Tests/test_tiff_ifdrational.py @@ -1,3 +1,4 @@ +from __future__ import annotations from fractions import Fraction from PIL import Image, TiffImagePlugin, features diff --git a/Tests/test_uploader.py b/Tests/test_uploader.py index 720926e53..6b693f7cd 100644 --- a/Tests/test_uploader.py +++ b/Tests/test_uploader.py @@ -1,3 +1,4 @@ +from __future__ import annotations from .helper import assert_image_equal, assert_image_similar, hopper diff --git a/Tests/test_util.py b/Tests/test_util.py index 9efbdd1f3..1457d85f7 100644 --- a/Tests/test_util.py +++ b/Tests/test_util.py @@ -1,3 +1,4 @@ +from __future__ import annotations import pytest from PIL import _util diff --git a/Tests/test_webp_leaks.py b/Tests/test_webp_leaks.py index 5bd9bacdb..28ebc7d79 100644 --- a/Tests/test_webp_leaks.py +++ b/Tests/test_webp_leaks.py @@ -1,3 +1,4 @@ +from __future__ import annotations from io import BytesIO from PIL import Image diff --git a/_custom_build/backend.py b/_custom_build/backend.py index 23225d6b8..d1537b809 100644 --- a/_custom_build/backend.py +++ b/_custom_build/backend.py @@ -1,3 +1,5 @@ +from __future__ import annotations + import sys from setuptools.build_meta import * # noqa: F403 diff --git a/conftest.py b/conftest.py index e123cca80..4dcd5e053 100644 --- a/conftest.py +++ b/conftest.py @@ -1 +1,3 @@ +from __future__ import annotations + pytest_plugins = ["Tests.helper"] diff --git a/docs/Guardfile b/docs/Guardfile index 6cbf07b06..16a891a73 100755 --- a/docs/Guardfile +++ b/docs/Guardfile @@ -1,4 +1,6 @@ #!/usr/bin/env python3 +from __future__ import annotations + from livereload.compiler import shell from livereload.task import Task diff --git a/docs/conf.py b/docs/conf.py index 833dfa215..9974b0f2a 100644 --- a/docs/conf.py +++ b/docs/conf.py @@ -15,6 +15,7 @@ # add these directories to sys.path here. If the directory is relative to the # documentation root, use os.path.abspath to make it absolute, like shown here. # sys.path.insert(0, os.path.abspath('.')) +from __future__ import annotations import PIL diff --git a/docs/example/DdsImagePlugin.py b/docs/example/DdsImagePlugin.py index 61690410b..e98bb8680 100644 --- a/docs/example/DdsImagePlugin.py +++ b/docs/example/DdsImagePlugin.py @@ -9,6 +9,7 @@ The contents of this file are hereby released in the public domain (CC0) Full text of the CC0 license: https://creativecommons.org/publicdomain/zero/1.0/ """ +from __future__ import annotations import struct from io import BytesIO diff --git a/docs/example/anchors.py b/docs/example/anchors.py index 3447de4f7..3a0e40b84 100644 --- a/docs/example/anchors.py +++ b/docs/example/anchors.py @@ -1,3 +1,5 @@ +from __future__ import annotations + from PIL import Image, ImageDraw, ImageFont font = ImageFont.truetype("Tests/fonts/NotoSans-Regular.ttf", 16) diff --git a/selftest.py b/selftest.py index 6eeadd1db..600fd6496 100755 --- a/selftest.py +++ b/selftest.py @@ -1,5 +1,6 @@ #!/usr/bin/env python3 # minimal sanity check +from __future__ import annotations import sys diff --git a/setup.py b/setup.py index 2a364ba97..1bf0bcff5 100755 --- a/setup.py +++ b/setup.py @@ -7,6 +7,7 @@ # Final rating: 10/10 # Your cheese is so fresh most people think it's a cream: Mascarpone # ------------------------------ +from __future__ import annotations import os import re diff --git a/src/PIL/BdfFontFile.py b/src/PIL/BdfFontFile.py index 161954831..b12ddc2d4 100644 --- a/src/PIL/BdfFontFile.py +++ b/src/PIL/BdfFontFile.py @@ -20,7 +20,7 @@ """ Parse X Bitmap Distribution Format (BDF) """ - +from __future__ import annotations from . import FontFile, Image diff --git a/src/PIL/BlpImagePlugin.py b/src/PIL/BlpImagePlugin.py index 398696d5c..b8f38b78a 100644 --- a/src/PIL/BlpImagePlugin.py +++ b/src/PIL/BlpImagePlugin.py @@ -28,6 +28,7 @@ BLP files come in many different flavours: - DXT3 compression is used if alpha_encoding == 1. - DXT5 compression is used if alpha_encoding == 7. """ +from __future__ import annotations import os import struct diff --git a/src/PIL/BmpImagePlugin.py b/src/PIL/BmpImagePlugin.py index b51019c66..6f730cfef 100644 --- a/src/PIL/BmpImagePlugin.py +++ b/src/PIL/BmpImagePlugin.py @@ -22,7 +22,7 @@ # # See the README file for information on usage and redistribution. # - +from __future__ import annotations import os diff --git a/src/PIL/BufrStubImagePlugin.py b/src/PIL/BufrStubImagePlugin.py index eef25aa14..60f3ec25b 100644 --- a/src/PIL/BufrStubImagePlugin.py +++ b/src/PIL/BufrStubImagePlugin.py @@ -8,6 +8,7 @@ # # See the README file for information on usage and redistribution. # +from __future__ import annotations from . import Image, ImageFile diff --git a/src/PIL/ContainerIO.py b/src/PIL/ContainerIO.py index 45e80b39a..387a4c182 100644 --- a/src/PIL/ContainerIO.py +++ b/src/PIL/ContainerIO.py @@ -13,7 +13,7 @@ # # See the README file for information on usage and redistribution. # - +from __future__ import annotations import io diff --git a/src/PIL/CurImagePlugin.py b/src/PIL/CurImagePlugin.py index fc0dae44b..5fb2b0193 100644 --- a/src/PIL/CurImagePlugin.py +++ b/src/PIL/CurImagePlugin.py @@ -15,6 +15,8 @@ # # See the README file for information on usage and redistribution. # +from __future__ import annotations + from . import BmpImagePlugin, Image from ._binary import i16le as i16 from ._binary import i32le as i32 diff --git a/src/PIL/DcxImagePlugin.py b/src/PIL/DcxImagePlugin.py index cde9d42f0..f7344df44 100644 --- a/src/PIL/DcxImagePlugin.py +++ b/src/PIL/DcxImagePlugin.py @@ -20,6 +20,7 @@ # # See the README file for information on usage and redistribution. # +from __future__ import annotations from . import Image from ._binary import i32le as i32 diff --git a/src/PIL/DdsImagePlugin.py b/src/PIL/DdsImagePlugin.py index 1758c9a4d..5b6ac2ead 100644 --- a/src/PIL/DdsImagePlugin.py +++ b/src/PIL/DdsImagePlugin.py @@ -9,6 +9,7 @@ The contents of this file are hereby released in the public domain (CC0) Full text of the CC0 license: https://creativecommons.org/publicdomain/zero/1.0/ """ +from __future__ import annotations import io import struct diff --git a/src/PIL/EpsImagePlugin.py b/src/PIL/EpsImagePlugin.py index c05208c80..d2e60aa07 100644 --- a/src/PIL/EpsImagePlugin.py +++ b/src/PIL/EpsImagePlugin.py @@ -19,6 +19,7 @@ # # See the README file for information on usage and redistribution. # +from __future__ import annotations import io import os diff --git a/src/PIL/ExifTags.py b/src/PIL/ExifTags.py index 2347c6d4c..60a4d9774 100644 --- a/src/PIL/ExifTags.py +++ b/src/PIL/ExifTags.py @@ -13,6 +13,7 @@ This module provides constants and clear-text names for various well-known EXIF tags. """ +from __future__ import annotations from enum import IntEnum diff --git a/src/PIL/FitsImagePlugin.py b/src/PIL/FitsImagePlugin.py index 1ff8a7e91..7dce2d60f 100644 --- a/src/PIL/FitsImagePlugin.py +++ b/src/PIL/FitsImagePlugin.py @@ -8,6 +8,7 @@ # # See the README file for information on usage and redistribution. # +from __future__ import annotations import math diff --git a/src/PIL/FliImagePlugin.py b/src/PIL/FliImagePlugin.py index b05a16259..9769761fc 100644 --- a/src/PIL/FliImagePlugin.py +++ b/src/PIL/FliImagePlugin.py @@ -14,6 +14,7 @@ # # See the README file for information on usage and redistribution. # +from __future__ import annotations import os diff --git a/src/PIL/FontFile.py b/src/PIL/FontFile.py index 085917ac3..9621770e2 100644 --- a/src/PIL/FontFile.py +++ b/src/PIL/FontFile.py @@ -13,7 +13,7 @@ # # See the README file for information on usage and redistribution. # - +from __future__ import annotations import os diff --git a/src/PIL/FpxImagePlugin.py b/src/PIL/FpxImagePlugin.py index a0999130e..75680a94e 100644 --- a/src/PIL/FpxImagePlugin.py +++ b/src/PIL/FpxImagePlugin.py @@ -14,6 +14,8 @@ # # See the README file for information on usage and redistribution. # +from __future__ import annotations + import olefile from . import Image, ImageFile diff --git a/src/PIL/FtexImagePlugin.py b/src/PIL/FtexImagePlugin.py index c2e4ead71..d5513a56a 100644 --- a/src/PIL/FtexImagePlugin.py +++ b/src/PIL/FtexImagePlugin.py @@ -50,6 +50,7 @@ bytes for that mipmap level. Note: All data is stored in little-Endian (Intel) byte order. """ +from __future__ import annotations import struct from enum import IntEnum diff --git a/src/PIL/GbrImagePlugin.py b/src/PIL/GbrImagePlugin.py index ec6e9de6e..6722fa2b1 100644 --- a/src/PIL/GbrImagePlugin.py +++ b/src/PIL/GbrImagePlugin.py @@ -23,6 +23,7 @@ # Version 2 files are saved by GIMP v2.8 (at least) # Version 3 files have a format specifier of 18 for 16bit floats in # the color depth field. This is currently unsupported by Pillow. +from __future__ import annotations from . import Image, ImageFile from ._binary import i32be as i32 diff --git a/src/PIL/GdImageFile.py b/src/PIL/GdImageFile.py index 3599994a8..d84876eb6 100644 --- a/src/PIL/GdImageFile.py +++ b/src/PIL/GdImageFile.py @@ -25,7 +25,7 @@ implementation is provided for convenience and demonstrational purposes only. """ - +from __future__ import annotations from . import ImageFile, ImagePalette, UnidentifiedImageError from ._binary import i16be as i16 diff --git a/src/PIL/GifImagePlugin.py b/src/PIL/GifImagePlugin.py index 4ddd5095c..57d87078b 100644 --- a/src/PIL/GifImagePlugin.py +++ b/src/PIL/GifImagePlugin.py @@ -23,6 +23,7 @@ # # See the README file for information on usage and redistribution. # +from __future__ import annotations import itertools import math diff --git a/src/PIL/GimpGradientFile.py b/src/PIL/GimpGradientFile.py index 8e801be0b..2d8c78ea9 100644 --- a/src/PIL/GimpGradientFile.py +++ b/src/PIL/GimpGradientFile.py @@ -18,7 +18,7 @@ Stuff to translate curve segments to palette values (derived from the corresponding code in GIMP, written by Federico Mena Quintero. See the GIMP distribution for more information.) """ - +from __future__ import annotations from math import log, pi, sin, sqrt diff --git a/src/PIL/GimpPaletteFile.py b/src/PIL/GimpPaletteFile.py index d38892894..a3109ebaa 100644 --- a/src/PIL/GimpPaletteFile.py +++ b/src/PIL/GimpPaletteFile.py @@ -13,6 +13,7 @@ # # See the README file for information on usage and redistribution. # +from __future__ import annotations import re diff --git a/src/PIL/GribStubImagePlugin.py b/src/PIL/GribStubImagePlugin.py index c1c71da08..f8106800c 100644 --- a/src/PIL/GribStubImagePlugin.py +++ b/src/PIL/GribStubImagePlugin.py @@ -8,6 +8,7 @@ # # See the README file for information on usage and redistribution. # +from __future__ import annotations from . import Image, ImageFile diff --git a/src/PIL/Hdf5StubImagePlugin.py b/src/PIL/Hdf5StubImagePlugin.py index c26b480ac..65409e269 100644 --- a/src/PIL/Hdf5StubImagePlugin.py +++ b/src/PIL/Hdf5StubImagePlugin.py @@ -8,6 +8,7 @@ # # See the README file for information on usage and redistribution. # +from __future__ import annotations from . import Image, ImageFile diff --git a/src/PIL/IcnsImagePlugin.py b/src/PIL/IcnsImagePlugin.py index b415a3219..d877b4ecb 100644 --- a/src/PIL/IcnsImagePlugin.py +++ b/src/PIL/IcnsImagePlugin.py @@ -16,6 +16,7 @@ # # See the README file for information on usage and redistribution. # +from __future__ import annotations import io import os diff --git a/src/PIL/IcoImagePlugin.py b/src/PIL/IcoImagePlugin.py index 7f0f0047c..1b22f8645 100644 --- a/src/PIL/IcoImagePlugin.py +++ b/src/PIL/IcoImagePlugin.py @@ -20,7 +20,7 @@ # Icon format references: # * https://en.wikipedia.org/wiki/ICO_(file_format) # * https://msdn.microsoft.com/en-us/library/ms997538.aspx - +from __future__ import annotations import warnings from io import BytesIO diff --git a/src/PIL/ImImagePlugin.py b/src/PIL/ImImagePlugin.py index b42ba7cac..97d726a8a 100644 --- a/src/PIL/ImImagePlugin.py +++ b/src/PIL/ImImagePlugin.py @@ -24,7 +24,7 @@ # # See the README file for information on usage and redistribution. # - +from __future__ import annotations import os import re diff --git a/src/PIL/ImageCms.py b/src/PIL/ImageCms.py index 0df3a4c6c..9d27f2513 100644 --- a/src/PIL/ImageCms.py +++ b/src/PIL/ImageCms.py @@ -14,6 +14,7 @@ # See the README file for information on usage and redistribution. See # below for the original description. +from __future__ import annotations import sys from enum import IntEnum diff --git a/src/PIL/ImageColor.py b/src/PIL/ImageColor.py index 894461c83..bfad27c82 100644 --- a/src/PIL/ImageColor.py +++ b/src/PIL/ImageColor.py @@ -16,6 +16,7 @@ # # See the README file for information on usage and redistribution. # +from __future__ import annotations import re diff --git a/src/PIL/ImageDraw.py b/src/PIL/ImageDraw.py index 6509d4c8e..8611dcc36 100644 --- a/src/PIL/ImageDraw.py +++ b/src/PIL/ImageDraw.py @@ -29,6 +29,7 @@ # # See the README file for information on usage and redistribution. # +from __future__ import annotations import math import numbers diff --git a/src/PIL/ImageDraw2.py b/src/PIL/ImageDraw2.py index 7ce0224a6..35ee5834e 100644 --- a/src/PIL/ImageDraw2.py +++ b/src/PIL/ImageDraw2.py @@ -22,7 +22,7 @@ .. seealso:: :py:mod:`PIL.ImageDraw` """ - +from __future__ import annotations from . import Image, ImageColor, ImageDraw, ImageFont, ImagePath diff --git a/src/PIL/ImageEnhance.py b/src/PIL/ImageEnhance.py index d7fdec262..93a50d2a2 100644 --- a/src/PIL/ImageEnhance.py +++ b/src/PIL/ImageEnhance.py @@ -17,6 +17,7 @@ # # See the README file for information on usage and redistribution. # +from __future__ import annotations from . import Image, ImageFilter, ImageStat diff --git a/src/PIL/ImageFilter.py b/src/PIL/ImageFilter.py index c24f86ef3..021b40c0e 100644 --- a/src/PIL/ImageFilter.py +++ b/src/PIL/ImageFilter.py @@ -14,6 +14,8 @@ # # See the README file for information on usage and redistribution. # +from __future__ import annotations + import functools diff --git a/src/PIL/ImageGrab.py b/src/PIL/ImageGrab.py index bcfffc3dc..a4993d3d4 100644 --- a/src/PIL/ImageGrab.py +++ b/src/PIL/ImageGrab.py @@ -14,6 +14,7 @@ # # See the README file for information on usage and redistribution. # +from __future__ import annotations import io import os diff --git a/src/PIL/ImageMath.py b/src/PIL/ImageMath.py index 047187195..7ca512e75 100644 --- a/src/PIL/ImageMath.py +++ b/src/PIL/ImageMath.py @@ -14,6 +14,7 @@ # # See the README file for information on usage and redistribution. # +from __future__ import annotations import builtins diff --git a/src/PIL/ImageMode.py b/src/PIL/ImageMode.py index a0b335142..54c3d01c4 100644 --- a/src/PIL/ImageMode.py +++ b/src/PIL/ImageMode.py @@ -12,6 +12,7 @@ # # See the README file for information on usage and redistribution. # +from __future__ import annotations import sys diff --git a/src/PIL/ImageMorph.py b/src/PIL/ImageMorph.py index 6fccc315b..282e7d2a5 100644 --- a/src/PIL/ImageMorph.py +++ b/src/PIL/ImageMorph.py @@ -4,6 +4,7 @@ # 2014-06-04 Initial version. # # Copyright (c) 2014 Dov Grobgeld +from __future__ import annotations import re diff --git a/src/PIL/ImageOps.py b/src/PIL/ImageOps.py index f183c8f27..a9e626b2b 100644 --- a/src/PIL/ImageOps.py +++ b/src/PIL/ImageOps.py @@ -16,6 +16,7 @@ # # See the README file for information on usage and redistribution. # +from __future__ import annotations import functools import operator diff --git a/src/PIL/ImagePalette.py b/src/PIL/ImagePalette.py index 212948793..fbcfa309d 100644 --- a/src/PIL/ImagePalette.py +++ b/src/PIL/ImagePalette.py @@ -15,6 +15,7 @@ # # See the README file for information on usage and redistribution. # +from __future__ import annotations import array diff --git a/src/PIL/ImagePath.py b/src/PIL/ImagePath.py index 3d3538c97..77e8a609a 100644 --- a/src/PIL/ImagePath.py +++ b/src/PIL/ImagePath.py @@ -13,6 +13,7 @@ # # See the README file for information on usage and redistribution. # +from __future__ import annotations from . import Image diff --git a/src/PIL/ImageQt.py b/src/PIL/ImageQt.py index 56c1aa525..6377c7501 100644 --- a/src/PIL/ImageQt.py +++ b/src/PIL/ImageQt.py @@ -15,6 +15,7 @@ # # See the README file for information on usage and redistribution. # +from __future__ import annotations import sys from io import BytesIO diff --git a/src/PIL/ImageSequence.py b/src/PIL/ImageSequence.py index 2d96b8b13..e09b001e8 100644 --- a/src/PIL/ImageSequence.py +++ b/src/PIL/ImageSequence.py @@ -14,6 +14,7 @@ # ## +from __future__ import annotations class Iterator: diff --git a/src/PIL/ImageShow.py b/src/PIL/ImageShow.py index 3d8fa2e40..fad3e0980 100644 --- a/src/PIL/ImageShow.py +++ b/src/PIL/ImageShow.py @@ -11,6 +11,8 @@ # # See the README file for information on usage and redistribution. # +from __future__ import annotations + import os import shutil import subprocess diff --git a/src/PIL/ImageStat.py b/src/PIL/ImageStat.py index edc39fb53..13864e59c 100644 --- a/src/PIL/ImageStat.py +++ b/src/PIL/ImageStat.py @@ -20,6 +20,7 @@ # # See the README file for information on usage and redistribution. # +from __future__ import annotations import math diff --git a/src/PIL/ImageTk.py b/src/PIL/ImageTk.py index bf98eb2c8..10b2cc69a 100644 --- a/src/PIL/ImageTk.py +++ b/src/PIL/ImageTk.py @@ -24,6 +24,7 @@ # # See the README file for information on usage and redistribution. # +from __future__ import annotations import tkinter from io import BytesIO diff --git a/src/PIL/ImageTransform.py b/src/PIL/ImageTransform.py index 7881f0d26..1fdaa9140 100644 --- a/src/PIL/ImageTransform.py +++ b/src/PIL/ImageTransform.py @@ -12,6 +12,7 @@ # # See the README file for information on usage and redistribution. # +from __future__ import annotations from . import Image diff --git a/src/PIL/ImageWin.py b/src/PIL/ImageWin.py index c7c64b35a..75910d2d9 100644 --- a/src/PIL/ImageWin.py +++ b/src/PIL/ImageWin.py @@ -16,6 +16,7 @@ # # See the README file for information on usage and redistribution. # +from __future__ import annotations from . import Image diff --git a/src/PIL/ImtImagePlugin.py b/src/PIL/ImtImagePlugin.py index d409fcd59..7469c592d 100644 --- a/src/PIL/ImtImagePlugin.py +++ b/src/PIL/ImtImagePlugin.py @@ -13,7 +13,7 @@ # # See the README file for information on usage and redistribution. # - +from __future__ import annotations import re diff --git a/src/PIL/IptcImagePlugin.py b/src/PIL/IptcImagePlugin.py index 3a40cf987..e7dc3e4e4 100644 --- a/src/PIL/IptcImagePlugin.py +++ b/src/PIL/IptcImagePlugin.py @@ -14,6 +14,8 @@ # # See the README file for information on usage and redistribution. # +from __future__ import annotations + import os import tempfile diff --git a/src/PIL/Jpeg2KImagePlugin.py b/src/PIL/Jpeg2KImagePlugin.py index bb0cb676a..4b778a0d3 100644 --- a/src/PIL/Jpeg2KImagePlugin.py +++ b/src/PIL/Jpeg2KImagePlugin.py @@ -13,6 +13,8 @@ # # See the README file for information on usage and redistribution. # +from __future__ import annotations + import io import os import struct diff --git a/src/PIL/JpegImagePlugin.py b/src/PIL/JpegImagePlugin.py index 5add65f45..59bade303 100644 --- a/src/PIL/JpegImagePlugin.py +++ b/src/PIL/JpegImagePlugin.py @@ -31,6 +31,8 @@ # # See the README file for information on usage and redistribution. # +from __future__ import annotations + import array import io import math diff --git a/src/PIL/JpegPresets.py b/src/PIL/JpegPresets.py index a678e248e..81b82c73c 100644 --- a/src/PIL/JpegPresets.py +++ b/src/PIL/JpegPresets.py @@ -64,6 +64,8 @@ https://web.archive.org/web/20120328125543/http://www.jpegcameras.com/libjpeg/li """ # fmt: off +from __future__ import annotations + presets = { 'web_low': {'subsampling': 2, # "4:2:0" 'quantization': [ diff --git a/src/PIL/McIdasImagePlugin.py b/src/PIL/McIdasImagePlugin.py index bb79e71de..9a85c0d15 100644 --- a/src/PIL/McIdasImagePlugin.py +++ b/src/PIL/McIdasImagePlugin.py @@ -15,6 +15,7 @@ # # See the README file for information on usage and redistribution. # +from __future__ import annotations import struct diff --git a/src/PIL/MicImagePlugin.py b/src/PIL/MicImagePlugin.py index 9300d3545..f4529d9ae 100644 --- a/src/PIL/MicImagePlugin.py +++ b/src/PIL/MicImagePlugin.py @@ -15,7 +15,7 @@ # # See the README file for information on usage and redistribution. # - +from __future__ import annotations import olefile diff --git a/src/PIL/MpegImagePlugin.py b/src/PIL/MpegImagePlugin.py index bfa88fe99..f4e598ca3 100644 --- a/src/PIL/MpegImagePlugin.py +++ b/src/PIL/MpegImagePlugin.py @@ -12,7 +12,7 @@ # # See the README file for information on usage and redistribution. # - +from __future__ import annotations from . import Image, ImageFile from ._binary import i8 diff --git a/src/PIL/MpoImagePlugin.py b/src/PIL/MpoImagePlugin.py index 89083b4ff..199a10090 100644 --- a/src/PIL/MpoImagePlugin.py +++ b/src/PIL/MpoImagePlugin.py @@ -17,6 +17,7 @@ # # See the README file for information on usage and redistribution. # +from __future__ import annotations import itertools import os diff --git a/src/PIL/MspImagePlugin.py b/src/PIL/MspImagePlugin.py index 3f3609f1c..77dac65b6 100644 --- a/src/PIL/MspImagePlugin.py +++ b/src/PIL/MspImagePlugin.py @@ -22,6 +22,7 @@ # Figure 206. Windows Paint Version 2: "LinS" Format. Used in Windows V2.03 # # See also: https://www.fileformat.info/format/mspaint/egff.htm +from __future__ import annotations import io import struct diff --git a/src/PIL/PSDraw.py b/src/PIL/PSDraw.py index c01534bbf..848fc2f71 100644 --- a/src/PIL/PSDraw.py +++ b/src/PIL/PSDraw.py @@ -14,6 +14,7 @@ # # See the README file for information on usage and redistribution. # +from __future__ import annotations import sys diff --git a/src/PIL/PaletteFile.py b/src/PIL/PaletteFile.py index 4a2c497fc..dc3175402 100644 --- a/src/PIL/PaletteFile.py +++ b/src/PIL/PaletteFile.py @@ -12,6 +12,7 @@ # # See the README file for information on usage and redistribution. # +from __future__ import annotations from ._binary import o8 diff --git a/src/PIL/PalmImagePlugin.py b/src/PIL/PalmImagePlugin.py index 606739c87..65be7fef7 100644 --- a/src/PIL/PalmImagePlugin.py +++ b/src/PIL/PalmImagePlugin.py @@ -6,6 +6,7 @@ ## # Image plugin for Palm pixmap images (output only). ## +from __future__ import annotations from . import Image, ImageFile from ._binary import o8 diff --git a/src/PIL/PcdImagePlugin.py b/src/PIL/PcdImagePlugin.py index c7cbca8c5..a0515b302 100644 --- a/src/PIL/PcdImagePlugin.py +++ b/src/PIL/PcdImagePlugin.py @@ -13,7 +13,7 @@ # # See the README file for information on usage and redistribution. # - +from __future__ import annotations from . import Image, ImageFile diff --git a/src/PIL/PcfFontFile.py b/src/PIL/PcfFontFile.py index 8b0014f3a..d602a1633 100644 --- a/src/PIL/PcfFontFile.py +++ b/src/PIL/PcfFontFile.py @@ -15,6 +15,7 @@ # # See the README file for information on usage and redistribution. # +from __future__ import annotations import io diff --git a/src/PIL/PcxImagePlugin.py b/src/PIL/PcxImagePlugin.py index 67990b0ad..98ecefd05 100644 --- a/src/PIL/PcxImagePlugin.py +++ b/src/PIL/PcxImagePlugin.py @@ -24,6 +24,7 @@ # # See the README file for information on usage and redistribution. # +from __future__ import annotations import io import logging diff --git a/src/PIL/PdfImagePlugin.py b/src/PIL/PdfImagePlugin.py index b6bb60911..3506aadce 100644 --- a/src/PIL/PdfImagePlugin.py +++ b/src/PIL/PdfImagePlugin.py @@ -19,6 +19,7 @@ ## # Image plugin for PDF images (output only). ## +from __future__ import annotations import io import math diff --git a/src/PIL/PdfParser.py b/src/PIL/PdfParser.py index 8bdb65cce..014460006 100644 --- a/src/PIL/PdfParser.py +++ b/src/PIL/PdfParser.py @@ -1,3 +1,5 @@ +from __future__ import annotations + import calendar import codecs import collections diff --git a/src/PIL/PixarImagePlugin.py b/src/PIL/PixarImagePlugin.py index 850272311..af866feb3 100644 --- a/src/PIL/PixarImagePlugin.py +++ b/src/PIL/PixarImagePlugin.py @@ -18,6 +18,7 @@ # # See the README file for information on usage and redistribution. # +from __future__ import annotations from . import Image, ImageFile from ._binary import i16le as i16 diff --git a/src/PIL/PngImagePlugin.py b/src/PIL/PngImagePlugin.py index dbcdee1c2..e4ed93880 100644 --- a/src/PIL/PngImagePlugin.py +++ b/src/PIL/PngImagePlugin.py @@ -30,6 +30,7 @@ # # See the README file for information on usage and redistribution. # +from __future__ import annotations import itertools import logging diff --git a/src/PIL/PpmImagePlugin.py b/src/PIL/PpmImagePlugin.py index 93f1528c5..25dbfa5b0 100644 --- a/src/PIL/PpmImagePlugin.py +++ b/src/PIL/PpmImagePlugin.py @@ -13,7 +13,7 @@ # # See the README file for information on usage and redistribution. # - +from __future__ import annotations from . import Image, ImageFile from ._binary import i16be as i16 diff --git a/src/PIL/PsdImagePlugin.py b/src/PIL/PsdImagePlugin.py index 46970da04..5cff56413 100644 --- a/src/PIL/PsdImagePlugin.py +++ b/src/PIL/PsdImagePlugin.py @@ -15,6 +15,7 @@ # # See the README file for information on usage and redistribution. # +from __future__ import annotations import io diff --git a/src/PIL/PyAccess.py b/src/PIL/PyAccess.py index 24d30d2a6..23ff154f6 100644 --- a/src/PIL/PyAccess.py +++ b/src/PIL/PyAccess.py @@ -18,6 +18,7 @@ # * Fill.c uses the integer form, but it's still going to use the old # Access.c implementation. # +from __future__ import annotations import logging import sys diff --git a/src/PIL/QoiImagePlugin.py b/src/PIL/QoiImagePlugin.py index 66344faac..a7b9d4a9e 100644 --- a/src/PIL/QoiImagePlugin.py +++ b/src/PIL/QoiImagePlugin.py @@ -5,6 +5,7 @@ # # See the README file for information on usage and redistribution. # +from __future__ import annotations import os diff --git a/src/PIL/SgiImagePlugin.py b/src/PIL/SgiImagePlugin.py index a2a259c89..f9a10f610 100644 --- a/src/PIL/SgiImagePlugin.py +++ b/src/PIL/SgiImagePlugin.py @@ -20,7 +20,7 @@ # # See the README file for information on usage and redistribution. # - +from __future__ import annotations import os import struct diff --git a/src/PIL/SpiderImagePlugin.py b/src/PIL/SpiderImagePlugin.py index 14cad8f9a..86582fb12 100644 --- a/src/PIL/SpiderImagePlugin.py +++ b/src/PIL/SpiderImagePlugin.py @@ -32,6 +32,8 @@ # Details about the Spider image format: # https://spider.wadsworth.org/spider_doc/spider/docs/image_doc.html # +from __future__ import annotations + import os import struct import sys diff --git a/src/PIL/SunImagePlugin.py b/src/PIL/SunImagePlugin.py index 6a8d5d86b..11ce3dfef 100644 --- a/src/PIL/SunImagePlugin.py +++ b/src/PIL/SunImagePlugin.py @@ -15,7 +15,7 @@ # # See the README file for information on usage and redistribution. # - +from __future__ import annotations from . import Image, ImageFile, ImagePalette from ._binary import i32be as i32 diff --git a/src/PIL/TarIO.py b/src/PIL/TarIO.py index 32928f6af..26522d93f 100644 --- a/src/PIL/TarIO.py +++ b/src/PIL/TarIO.py @@ -13,6 +13,7 @@ # # See the README file for information on usage and redistribution. # +from __future__ import annotations import io diff --git a/src/PIL/TgaImagePlugin.py b/src/PIL/TgaImagePlugin.py index f24ee4f5c..65c7484f7 100644 --- a/src/PIL/TgaImagePlugin.py +++ b/src/PIL/TgaImagePlugin.py @@ -15,7 +15,7 @@ # # See the README file for information on usage and redistribution. # - +from __future__ import annotations import warnings diff --git a/src/PIL/TiffImagePlugin.py b/src/PIL/TiffImagePlugin.py index a78a5aef1..fc242ca64 100644 --- a/src/PIL/TiffImagePlugin.py +++ b/src/PIL/TiffImagePlugin.py @@ -38,6 +38,8 @@ # # See the README file for information on usage and redistribution. # +from __future__ import annotations + import io import itertools import logging diff --git a/src/PIL/TiffTags.py b/src/PIL/TiffTags.py index b02c637b6..88ff2f4fc 100644 --- a/src/PIL/TiffTags.py +++ b/src/PIL/TiffTags.py @@ -16,6 +16,7 @@ # This module provides constants and clear-text names for various # well-known TIFF tags. ## +from __future__ import annotations from collections import namedtuple diff --git a/src/PIL/WalImageFile.py b/src/PIL/WalImageFile.py index 3d9f97f84..c5bf3e04c 100644 --- a/src/PIL/WalImageFile.py +++ b/src/PIL/WalImageFile.py @@ -22,6 +22,7 @@ and has been tested with a few sample files found using google. is not registered for use with :py:func:`PIL.Image.open()`. To open a WAL file, use the :py:func:`PIL.WalImageFile.open()` function instead. """ +from __future__ import annotations from . import Image, ImageFile from ._binary import i32le as i32 diff --git a/src/PIL/WebPImagePlugin.py b/src/PIL/WebPImagePlugin.py index eed58a13b..59556206a 100644 --- a/src/PIL/WebPImagePlugin.py +++ b/src/PIL/WebPImagePlugin.py @@ -1,3 +1,5 @@ +from __future__ import annotations + from io import BytesIO from . import Image, ImageFile diff --git a/src/PIL/WmfImagePlugin.py b/src/PIL/WmfImagePlugin.py index 3e5fb0151..b5b8c69b1 100644 --- a/src/PIL/WmfImagePlugin.py +++ b/src/PIL/WmfImagePlugin.py @@ -18,6 +18,7 @@ # https://winprotocoldoc.blob.core.windows.net/productionwindowsarchives/MS-WMF/[MS-WMF].pdf # http://wvware.sourceforge.net/caolan/index.html # http://wvware.sourceforge.net/caolan/ora-wmf.html +from __future__ import annotations from . import Image, ImageFile from ._binary import i16le as word diff --git a/src/PIL/XVThumbImagePlugin.py b/src/PIL/XVThumbImagePlugin.py index eda60c5c5..47ba1c548 100644 --- a/src/PIL/XVThumbImagePlugin.py +++ b/src/PIL/XVThumbImagePlugin.py @@ -16,6 +16,7 @@ # To do: # FIXME: make save work (this requires quantization support) # +from __future__ import annotations from . import Image, ImageFile, ImagePalette from ._binary import o8 diff --git a/src/PIL/XbmImagePlugin.py b/src/PIL/XbmImagePlugin.py index 71cd57d74..566acbfe5 100644 --- a/src/PIL/XbmImagePlugin.py +++ b/src/PIL/XbmImagePlugin.py @@ -18,6 +18,7 @@ # # See the README file for information on usage and redistribution. # +from __future__ import annotations import re diff --git a/src/PIL/XpmImagePlugin.py b/src/PIL/XpmImagePlugin.py index 8491d3b7e..bf73c9bef 100644 --- a/src/PIL/XpmImagePlugin.py +++ b/src/PIL/XpmImagePlugin.py @@ -13,7 +13,7 @@ # # See the README file for information on usage and redistribution. # - +from __future__ import annotations import re diff --git a/src/PIL/__init__.py b/src/PIL/__init__.py index 2bb8f6d7f..3fcac8643 100644 --- a/src/PIL/__init__.py +++ b/src/PIL/__init__.py @@ -12,6 +12,7 @@ Use PIL.__version__ for this Pillow version. ;-) """ +from __future__ import annotations from . import _version diff --git a/src/PIL/__main__.py b/src/PIL/__main__.py index a05323f93..943789923 100644 --- a/src/PIL/__main__.py +++ b/src/PIL/__main__.py @@ -1,3 +1,5 @@ +from __future__ import annotations + from .features import pilinfo pilinfo() diff --git a/src/PIL/_binary.py b/src/PIL/_binary.py index a74ee9eb6..c60c9cec1 100644 --- a/src/PIL/_binary.py +++ b/src/PIL/_binary.py @@ -13,7 +13,7 @@ """Binary input/output support routines.""" - +from __future__ import annotations from struct import pack, unpack_from diff --git a/src/PIL/_tkinter_finder.py b/src/PIL/_tkinter_finder.py index 597c21b5e..03a6eba44 100644 --- a/src/PIL/_tkinter_finder.py +++ b/src/PIL/_tkinter_finder.py @@ -1,5 +1,7 @@ """ Find compiled module linking to Tcl / Tk libraries """ +from __future__ import annotations + import sys import tkinter from tkinter import _tkinter as tk diff --git a/src/PIL/_util.py b/src/PIL/_util.py index ba27b7e49..4634d335b 100644 --- a/src/PIL/_util.py +++ b/src/PIL/_util.py @@ -1,3 +1,5 @@ +from __future__ import annotations + import os from pathlib import Path diff --git a/src/PIL/_version.py b/src/PIL/_version.py index 279b6e228..7d994caf4 100644 --- a/src/PIL/_version.py +++ b/src/PIL/_version.py @@ -1,2 +1,4 @@ # Master version for Pillow +from __future__ import annotations + __version__ = "10.2.0.dev0" diff --git a/src/PIL/features.py b/src/PIL/features.py index f14e60cf5..b14d6df13 100644 --- a/src/PIL/features.py +++ b/src/PIL/features.py @@ -1,3 +1,5 @@ +from __future__ import annotations + import collections import os import sys From 64ddace6c40a3e0f9e30ceb89c90dc1b82e87658 Mon Sep 17 00:00:00 2001 From: Andrew Murray Date: Fri, 22 Dec 2023 23:06:35 +1100 Subject: [PATCH 19/21] Add 'from __future__ import annotations' using Ruff/isort --- src/PIL/JpegPresets.py | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/src/PIL/JpegPresets.py b/src/PIL/JpegPresets.py index 81b82c73c..9ecfdb259 100644 --- a/src/PIL/JpegPresets.py +++ b/src/PIL/JpegPresets.py @@ -62,10 +62,9 @@ Libjpeg ref.: https://web.archive.org/web/20120328125543/http://www.jpegcameras.com/libjpeg/libjpeg-3.html """ - -# fmt: off from __future__ import annotations +# fmt: off presets = { 'web_low': {'subsampling': 2, # "4:2:0" 'quantization': [ From 76809f09ef86d3feaaed3256a0e47dd5cec76520 Mon Sep 17 00:00:00 2001 From: Hugo van Kemenade Date: Fri, 22 Dec 2023 16:23:28 +0200 Subject: [PATCH 20/21] Add type hints for ImageMode --- src/PIL/ImageMode.py | 13 ++++++++++--- 1 file changed, 10 insertions(+), 3 deletions(-) diff --git a/src/PIL/ImageMode.py b/src/PIL/ImageMode.py index 54c3d01c4..661db24ad 100644 --- a/src/PIL/ImageMode.py +++ b/src/PIL/ImageMode.py @@ -23,18 +23,25 @@ _modes = None class ModeDescriptor: """Wrapper for mode strings.""" - def __init__(self, mode, bands, basemode, basetype, typestr): + def __init__( + self, + mode: str, + bands: str | tuple[str, ...], + basemode: str, + basetype: str | tuple[str, ...], + typestr: str, + ) -> None: self.mode = mode self.bands = bands self.basemode = basemode self.basetype = basetype self.typestr = typestr - def __str__(self): + def __str__(self) -> str: return self.mode -def getmode(mode): +def getmode(mode: str) -> ModeDescriptor: """Gets a mode descriptor for the given mode.""" global _modes if not _modes: From 17af8eca02fe7b4e0545811e5ab9843e26a030b1 Mon Sep 17 00:00:00 2001 From: Hugo van Kemenade Date: Sat, 23 Dec 2023 02:16:46 -0700 Subject: [PATCH 21/21] Add type hints for ImageMode Co-authored-by: Andrew Murray <3112309+radarhere@users.noreply.github.com> --- src/PIL/ImageMode.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/PIL/ImageMode.py b/src/PIL/ImageMode.py index 661db24ad..d61dd6fea 100644 --- a/src/PIL/ImageMode.py +++ b/src/PIL/ImageMode.py @@ -26,9 +26,9 @@ class ModeDescriptor: def __init__( self, mode: str, - bands: str | tuple[str, ...], + bands: tuple[str, ...], basemode: str, - basetype: str | tuple[str, ...], + basetype: str, typestr: str, ) -> None: self.mode = mode