diff --git a/Tests/test_color_lut.py b/Tests/test_color_lut.py index 26945ae1a69..03b8e9ec79b 100644 --- a/Tests/test_color_lut.py +++ b/Tests/test_color_lut.py @@ -1,7 +1,6 @@ from __future__ import annotations from array import array -from types import ModuleType import pytest @@ -9,6 +8,10 @@ from .helper import assert_image_equal +TYPE_CHECKING = False +if TYPE_CHECKING: + from types import ModuleType + numpy: ModuleType | None try: import numpy diff --git a/Tests/test_file_apng.py b/Tests/test_file_apng.py index b57a1d1ad8c..c57a1d22f1e 100644 --- a/Tests/test_file_apng.py +++ b/Tests/test_file_apng.py @@ -1,12 +1,15 @@ from __future__ import annotations from io import BytesIO -from pathlib import Path import pytest from PIL import Image, ImageSequence, PngImagePlugin +TYPE_CHECKING = False +if TYPE_CHECKING: + from pathlib import Path + # APNG browser support tests and fixtures via: # https://philip.html5.org/tests/apng/tests.html diff --git a/Tests/test_file_avif.py b/Tests/test_file_avif.py index d667c416919..4ff85f81381 100644 --- a/Tests/test_file_avif.py +++ b/Tests/test_file_avif.py @@ -4,10 +4,8 @@ import os import re import warnings -from collections.abc import Generator, Sequence from contextlib import contextmanager from io import BytesIO -from pathlib import Path from typing import Any import pytest @@ -32,6 +30,11 @@ skip_unless_feature_version, ) +TYPE_CHECKING = False +if TYPE_CHECKING: + from collections.abc import Generator, Sequence + from pathlib import Path + try: from PIL import _avif diff --git a/Tests/test_file_blp.py b/Tests/test_file_blp.py index 5f6b263a1e3..8ef8a64171e 100644 --- a/Tests/test_file_blp.py +++ b/Tests/test_file_blp.py @@ -1,7 +1,5 @@ from __future__ import annotations -from pathlib import Path - import pytest from PIL import BlpImagePlugin, Image @@ -12,6 +10,10 @@ hopper, ) +TYPE_CHECKING = False +if TYPE_CHECKING: + from pathlib import Path + def test_load_blp1() -> None: with Image.open("Tests/images/blp/blp1_jpeg.blp") as im: diff --git a/Tests/test_file_bmp.py b/Tests/test_file_bmp.py index 3fc50ced227..fb73fac923d 100644 --- a/Tests/test_file_bmp.py +++ b/Tests/test_file_bmp.py @@ -1,7 +1,6 @@ from __future__ import annotations import io -from pathlib import Path import pytest @@ -16,6 +15,10 @@ hopper, ) +TYPE_CHECKING = False +if TYPE_CHECKING: + from pathlib import Path + @pytest.mark.parametrize("mode", ("1", "L", "P", "RGB")) def test_sanity(mode: str, tmp_path: Path) -> None: diff --git a/Tests/test_file_bufrstub.py b/Tests/test_file_bufrstub.py index 8c6bb1a69f7..b5e726832e0 100644 --- a/Tests/test_file_bufrstub.py +++ b/Tests/test_file_bufrstub.py @@ -1,6 +1,5 @@ from __future__ import annotations -from pathlib import Path from typing import IO import pytest @@ -9,6 +8,10 @@ from .helper import hopper +TYPE_CHECKING = False +if TYPE_CHECKING: + from pathlib import Path + TEST_FILE = "Tests/images/gfs.t06z.rassda.tm00.bufr_d" diff --git a/Tests/test_file_dds.py b/Tests/test_file_dds.py index 6d0ae20eaa4..7e1b811e975 100644 --- a/Tests/test_file_dds.py +++ b/Tests/test_file_dds.py @@ -3,7 +3,6 @@ from __future__ import annotations from io import BytesIO -from pathlib import Path import pytest @@ -17,6 +16,10 @@ hopper, ) +TYPE_CHECKING = False +if TYPE_CHECKING: + from pathlib import Path + TEST_FILE_DXT1 = "Tests/images/dxt1-rgb-4bbp-noalpha_MipMaps-1.dds" TEST_FILE_DXT3 = "Tests/images/dxt3-argb-8bbp-explicitalpha_MipMaps-1.dds" TEST_FILE_DXT5 = "Tests/images/dxt5-argb-8bbp-interpolatedalpha_MipMaps-1.dds" diff --git a/Tests/test_file_eps.py b/Tests/test_file_eps.py index 85e3d4d8936..e3b7f0981bb 100644 --- a/Tests/test_file_eps.py +++ b/Tests/test_file_eps.py @@ -2,7 +2,6 @@ import io import subprocess -from pathlib import Path import pytest @@ -19,6 +18,10 @@ timeout_unless_slower_valgrind, ) +TYPE_CHECKING = False +if TYPE_CHECKING: + from pathlib import Path + HAS_GHOSTSCRIPT = EpsImagePlugin.has_ghostscript() # Our two EPS test files (they are identical except for their bounding boxes) diff --git a/Tests/test_file_gif.py b/Tests/test_file_gif.py index 52997e694c1..6b599b70050 100644 --- a/Tests/test_file_gif.py +++ b/Tests/test_file_gif.py @@ -1,9 +1,7 @@ from __future__ import annotations import warnings -from collections.abc import Generator from io import BytesIO -from pathlib import Path from typing import Any import pytest @@ -19,6 +17,11 @@ netpbm_available, ) +TYPE_CHECKING = False +if TYPE_CHECKING: + from collections.abc import Generator + from pathlib import Path + # sample gif stream TEST_GIF = "Tests/images/hopper.gif" diff --git a/Tests/test_file_gribstub.py b/Tests/test_file_gribstub.py index 05925d50202..520d63a1b2d 100644 --- a/Tests/test_file_gribstub.py +++ b/Tests/test_file_gribstub.py @@ -1,6 +1,5 @@ from __future__ import annotations -from pathlib import Path from typing import IO import pytest @@ -9,6 +8,10 @@ from .helper import hopper +TYPE_CHECKING = False +if TYPE_CHECKING: + from pathlib import Path + TEST_FILE = "Tests/images/WAlaska.wind.7days.grb" diff --git a/Tests/test_file_hdf5stub.py b/Tests/test_file_hdf5stub.py index e1a56309b90..853663d40d0 100644 --- a/Tests/test_file_hdf5stub.py +++ b/Tests/test_file_hdf5stub.py @@ -1,13 +1,16 @@ from __future__ import annotations from io import BytesIO -from pathlib import Path from typing import IO import pytest from PIL import Hdf5StubImagePlugin, Image, ImageFile +TYPE_CHECKING = False +if TYPE_CHECKING: + from pathlib import Path + TEST_FILE = "Tests/images/hdf5.h5" diff --git a/Tests/test_file_icns.py b/Tests/test_file_icns.py index c492a343cb3..7155a638aa1 100644 --- a/Tests/test_file_icns.py +++ b/Tests/test_file_icns.py @@ -3,7 +3,6 @@ import io import os import warnings -from pathlib import Path import pytest @@ -11,6 +10,10 @@ from .helper import assert_image_equal, assert_image_similar_tofile, skip_unless_feature +TYPE_CHECKING = False +if TYPE_CHECKING: + from pathlib import Path + # sample icon file TEST_FILE = "Tests/images/pillow.icns" diff --git a/Tests/test_file_ico.py b/Tests/test_file_ico.py index 36b608a0a98..c4edcec4f1e 100644 --- a/Tests/test_file_ico.py +++ b/Tests/test_file_ico.py @@ -2,7 +2,6 @@ import io import os -from pathlib import Path import pytest @@ -10,6 +9,10 @@ from .helper import assert_image_equal, assert_image_equal_tofile, hopper +TYPE_CHECKING = False +if TYPE_CHECKING: + from pathlib import Path + TEST_ICO_FILE = "Tests/images/hopper.ico" diff --git a/Tests/test_file_im.py b/Tests/test_file_im.py index dfd33078847..bf65ebca346 100644 --- a/Tests/test_file_im.py +++ b/Tests/test_file_im.py @@ -2,7 +2,6 @@ import filecmp import warnings -from pathlib import Path import pytest @@ -10,6 +9,10 @@ from .helper import assert_image_equal_tofile, hopper, is_pypy +TYPE_CHECKING = False +if TYPE_CHECKING: + from pathlib import Path + # sample im TEST_IM = "Tests/images/hopper.im" diff --git a/Tests/test_file_jpeg.py b/Tests/test_file_jpeg.py index 40407da0c20..0e16d867a3b 100644 --- a/Tests/test_file_jpeg.py +++ b/Tests/test_file_jpeg.py @@ -5,8 +5,6 @@ import struct import warnings from io import BytesIO -from pathlib import Path -from types import ModuleType from typing import Any, cast import pytest @@ -35,6 +33,11 @@ timeout_unless_slower_valgrind, ) +TYPE_CHECKING = False +if TYPE_CHECKING: + from pathlib import Path + from types import ModuleType + ElementTree: ModuleType | None try: from defusedxml import ElementTree @@ -53,7 +56,7 @@ def roundtrip_with_bytes( im.save(out, "JPEG", **options) test_bytes = out.tell() out.seek(0) - reloaded = cast(JpegImagePlugin.JpegImageFile, Image.open(out)) + reloaded = cast("JpegImagePlugin.JpegImageFile", Image.open(out)) return reloaded, test_bytes def roundtrip( diff --git a/Tests/test_file_jpeg2k.py b/Tests/test_file_jpeg2k.py index 6b58ec9a8a2..d0f13d84f75 100644 --- a/Tests/test_file_jpeg2k.py +++ b/Tests/test_file_jpeg2k.py @@ -3,9 +3,7 @@ import os import re import struct -from collections.abc import Generator from io import BytesIO -from pathlib import Path from typing import Any import pytest @@ -27,6 +25,11 @@ skip_unless_feature_version, ) +TYPE_CHECKING = False +if TYPE_CHECKING: + from collections.abc import Generator + from pathlib import Path + EXTRA_DIR = "Tests/images/jpeg2000" pytestmark = skip_unless_feature("jpg_2000") diff --git a/Tests/test_file_libtiff.py b/Tests/test_file_libtiff.py index c9849a056a3..e4ebf4f22c3 100644 --- a/Tests/test_file_libtiff.py +++ b/Tests/test_file_libtiff.py @@ -6,8 +6,7 @@ import os import re import sys -from pathlib import Path -from typing import Any, NamedTuple +from typing import NamedTuple import pytest @@ -32,6 +31,11 @@ skip_unless_feature, ) +TYPE_CHECKING = False +if TYPE_CHECKING: + from pathlib import Path + from typing import Any + @skip_unless_feature("libtiff") class LibTiffTestCase: diff --git a/Tests/test_file_libtiff_small.py b/Tests/test_file_libtiff_small.py index 65ba80c2076..a17959ef8ef 100644 --- a/Tests/test_file_libtiff_small.py +++ b/Tests/test_file_libtiff_small.py @@ -1,12 +1,15 @@ from __future__ import annotations from io import BytesIO -from pathlib import Path from PIL import Image from .test_file_libtiff import LibTiffTestCase +TYPE_CHECKING = False +if TYPE_CHECKING: + from pathlib import Path + class TestFileLibTiffSmall(LibTiffTestCase): """The small lena image was failing on open in the libtiff diff --git a/Tests/test_file_mcidas.py b/Tests/test_file_mcidas.py index d1410f5036c..babbbf1598a 100644 --- a/Tests/test_file_mcidas.py +++ b/Tests/test_file_mcidas.py @@ -1,7 +1,6 @@ from __future__ import annotations import struct -from pathlib import Path import pytest @@ -9,6 +8,10 @@ from .helper import assert_image_equal_tofile +TYPE_CHECKING = False +if TYPE_CHECKING: + from pathlib import Path + def test_invalid_file() -> None: invalid_file = "Tests/images/flower.jpg" diff --git a/Tests/test_file_msp.py b/Tests/test_file_msp.py index 8c91922bd0b..cba60e598c5 100644 --- a/Tests/test_file_msp.py +++ b/Tests/test_file_msp.py @@ -1,7 +1,6 @@ from __future__ import annotations import os -from pathlib import Path import pytest @@ -9,6 +8,10 @@ from .helper import assert_image_equal, assert_image_equal_tofile, hopper +TYPE_CHECKING = False +if TYPE_CHECKING: + from pathlib import Path + TEST_FILE = "Tests/images/hopper.msp" EXTRA_DIR = "Tests/images/picins" YA_EXTRA_DIR = "Tests/images/msp" diff --git a/Tests/test_file_palm.py b/Tests/test_file_palm.py index 58208ba99fa..7547b93216f 100644 --- a/Tests/test_file_palm.py +++ b/Tests/test_file_palm.py @@ -2,7 +2,6 @@ import os.path import subprocess -from pathlib import Path import pytest @@ -10,6 +9,10 @@ from .helper import assert_image_equal, hopper, magick_command +TYPE_CHECKING = False +if TYPE_CHECKING: + from pathlib import Path + def helper_save_as_palm(tmp_path: Path, mode: str) -> None: # Arrange diff --git a/Tests/test_file_pcx.py b/Tests/test_file_pcx.py index 76fd09dac9b..fc4bb328a7d 100644 --- a/Tests/test_file_pcx.py +++ b/Tests/test_file_pcx.py @@ -9,6 +9,10 @@ from .helper import assert_image_equal, hopper +TYPE_CHECKING = False +if TYPE_CHECKING: + from pathlib import Path + def _roundtrip(tmp_path: Path, im: Image.Image) -> None: f = tmp_path / "temp.pcx" diff --git a/Tests/test_file_pdf.py b/Tests/test_file_pdf.py index 3fb8ae62b84..7f821d110a4 100644 --- a/Tests/test_file_pdf.py +++ b/Tests/test_file_pdf.py @@ -5,8 +5,6 @@ import os.path import tempfile import time -from collections.abc import Generator -from pathlib import Path from typing import Any import pytest @@ -20,6 +18,11 @@ timeout_unless_slower_valgrind, ) +TYPE_CHECKING = False +if TYPE_CHECKING: + from collections.abc import Generator + from pathlib import Path + def helper_save_as_pdf(tmp_path: Path, mode: str, **kwargs: Any) -> str: # Arrange diff --git a/Tests/test_file_png.py b/Tests/test_file_png.py index f4fe1de013d..89b2ec79ec0 100644 --- a/Tests/test_file_png.py +++ b/Tests/test_file_png.py @@ -5,8 +5,6 @@ import warnings import zlib from io import BytesIO, TextIOWrapper -from pathlib import Path -from types import ModuleType from typing import Any, cast import pytest @@ -24,6 +22,11 @@ skip_unless_feature, ) +TYPE_CHECKING = False +if TYPE_CHECKING: + from pathlib import Path + from types import ModuleType + ElementTree: ModuleType | None try: from defusedxml import ElementTree @@ -63,7 +66,7 @@ def roundtrip(im: Image.Image, **options: Any) -> PngImagePlugin.PngImageFile: out = BytesIO() im.save(out, "PNG", **options) out.seek(0) - return cast(PngImagePlugin.PngImageFile, Image.open(out)) + return cast("PngImagePlugin.PngImageFile", Image.open(out)) @skip_unless_feature("zlib") diff --git a/Tests/test_file_ppm.py b/Tests/test_file_ppm.py index d0b1cbf8e74..ccd32fdee55 100644 --- a/Tests/test_file_ppm.py +++ b/Tests/test_file_ppm.py @@ -2,7 +2,6 @@ import sys from io import BytesIO, TextIOWrapper -from pathlib import Path import pytest @@ -15,6 +14,10 @@ hopper, ) +TYPE_CHECKING = False +if TYPE_CHECKING: + from pathlib import Path + # sample ppm stream TEST_FILE = "Tests/images/hopper.ppm" diff --git a/Tests/test_file_qoi.py b/Tests/test_file_qoi.py index 3057dabc05e..01614dcdadd 100644 --- a/Tests/test_file_qoi.py +++ b/Tests/test_file_qoi.py @@ -1,7 +1,6 @@ from __future__ import annotations from io import BytesIO -from pathlib import Path import pytest @@ -9,6 +8,10 @@ from .helper import assert_image_equal_tofile, hopper +TYPE_CHECKING = False +if TYPE_CHECKING: + from pathlib import Path + def test_sanity() -> None: with Image.open("Tests/images/hopper.qoi") as im: diff --git a/Tests/test_file_sgi.py b/Tests/test_file_sgi.py index abf424dbf11..a2b1858ce1f 100644 --- a/Tests/test_file_sgi.py +++ b/Tests/test_file_sgi.py @@ -1,7 +1,6 @@ from __future__ import annotations from io import BytesIO -from pathlib import Path import pytest @@ -14,6 +13,10 @@ hopper, ) +TYPE_CHECKING = False +if TYPE_CHECKING: + from pathlib import Path + def test_rgb() -> None: # Created with ImageMagick then renamed: diff --git a/Tests/test_file_spider.py b/Tests/test_file_spider.py index 933f2f8b4e8..51e54798dfb 100644 --- a/Tests/test_file_spider.py +++ b/Tests/test_file_spider.py @@ -3,7 +3,6 @@ import tempfile import warnings from io import BytesIO -from pathlib import Path import pytest @@ -11,6 +10,10 @@ from .helper import assert_image_equal, hopper, is_pypy +TYPE_CHECKING = False +if TYPE_CHECKING: + from pathlib import Path + TEST_FILE = "Tests/images/hopper.spider" diff --git a/Tests/test_file_tar.py b/Tests/test_file_tar.py index a6a6fa64727..78ca0c2787a 100644 --- a/Tests/test_file_tar.py +++ b/Tests/test_file_tar.py @@ -1,7 +1,6 @@ from __future__ import annotations import warnings -from pathlib import Path import pytest @@ -9,6 +8,10 @@ from .helper import is_pypy +TYPE_CHECKING = False +if TYPE_CHECKING: + from pathlib import Path + # Sample tar archive TEST_TAR_FILE = "Tests/images/hopper.tar" diff --git a/Tests/test_file_tga.py b/Tests/test_file_tga.py index 82bcf48caba..03ab96e05a1 100644 --- a/Tests/test_file_tga.py +++ b/Tests/test_file_tga.py @@ -2,7 +2,6 @@ import os from io import BytesIO -from pathlib import Path import pytest @@ -10,6 +9,10 @@ from .helper import assert_image_equal, assert_image_equal_tofile, hopper +TYPE_CHECKING = False +if TYPE_CHECKING: + from pathlib import Path + _TGA_DIR = os.path.join("Tests", "images", "tga") _TGA_DIR_COMMON = os.path.join(_TGA_DIR, "common") diff --git a/Tests/test_file_tiff.py b/Tests/test_file_tiff.py index 145ab3e8920..232cd72e5a3 100644 --- a/Tests/test_file_tiff.py +++ b/Tests/test_file_tiff.py @@ -2,10 +2,7 @@ import os import warnings -from collections.abc import Generator from io import BytesIO -from pathlib import Path -from types import ModuleType import pytest @@ -31,6 +28,12 @@ timeout_unless_slower_valgrind, ) +TYPE_CHECKING = False +if TYPE_CHECKING: + from collections.abc import Generator + from pathlib import Path + from types import ModuleType + ElementTree: ModuleType | None try: from defusedxml import ElementTree diff --git a/Tests/test_file_tiff_metadata.py b/Tests/test_file_tiff_metadata.py index a9a367f88c6..ce185bc306e 100644 --- a/Tests/test_file_tiff_metadata.py +++ b/Tests/test_file_tiff_metadata.py @@ -2,7 +2,6 @@ import io import struct -from pathlib import Path import pytest @@ -11,6 +10,10 @@ from .helper import assert_deep_equal, hopper +TYPE_CHECKING = False +if TYPE_CHECKING: + from pathlib import Path + TAG_IDS: dict[str, int] = { info.name: info.value for info in TiffTags.TAGS_V2.values() diff --git a/Tests/test_file_webp.py b/Tests/test_file_webp.py index 7360c1df06f..d6cc39fd877 100644 --- a/Tests/test_file_webp.py +++ b/Tests/test_file_webp.py @@ -4,7 +4,6 @@ import re import sys import warnings -from pathlib import Path from typing import Any import pytest @@ -19,6 +18,10 @@ skip_unless_feature, ) +TYPE_CHECKING = False +if TYPE_CHECKING: + from pathlib import Path + try: from PIL import _webp diff --git a/Tests/test_file_webp_alpha.py b/Tests/test_file_webp_alpha.py index b1aa45f6b52..a524a3169b0 100644 --- a/Tests/test_file_webp_alpha.py +++ b/Tests/test_file_webp_alpha.py @@ -1,7 +1,5 @@ from __future__ import annotations -from pathlib import Path - import pytest from PIL import Image @@ -13,6 +11,10 @@ hopper, ) +TYPE_CHECKING = False +if TYPE_CHECKING: + from pathlib import Path + pytest.importorskip("PIL._webp", reason="WebP support not installed") diff --git a/Tests/test_file_webp_animated.py b/Tests/test_file_webp_animated.py index 7ae93e76b09..7565aafb0f2 100644 --- a/Tests/test_file_webp_animated.py +++ b/Tests/test_file_webp_animated.py @@ -1,8 +1,5 @@ from __future__ import annotations -from collections.abc import Generator -from pathlib import Path - import pytest from PIL import GifImagePlugin, Image, WebPImagePlugin @@ -15,6 +12,11 @@ skip_unless_feature, ) +TYPE_CHECKING = False +if TYPE_CHECKING: + from collections.abc import Generator + from pathlib import Path + pytestmark = skip_unless_feature("webp") diff --git a/Tests/test_file_webp_lossless.py b/Tests/test_file_webp_lossless.py index b4c0448ac75..8a43249feab 100644 --- a/Tests/test_file_webp_lossless.py +++ b/Tests/test_file_webp_lossless.py @@ -1,13 +1,15 @@ from __future__ import annotations -from pathlib import Path - import pytest from PIL import Image from .helper import assert_image_equal, hopper +TYPE_CHECKING = False +if TYPE_CHECKING: + from pathlib import Path + pytest.importorskip("PIL._webp", reason="WebP support not installed") RGB_MODE = "RGB" diff --git a/Tests/test_file_webp_metadata.py b/Tests/test_file_webp_metadata.py index 3de412b832b..f6af81ed5d1 100644 --- a/Tests/test_file_webp_metadata.py +++ b/Tests/test_file_webp_metadata.py @@ -1,8 +1,6 @@ from __future__ import annotations from io import BytesIO -from pathlib import Path -from types import ModuleType import pytest @@ -10,6 +8,11 @@ from .helper import mark_if_feature_version, skip_unless_feature +TYPE_CHECKING = False +if TYPE_CHECKING: + from pathlib import Path + from types import ModuleType + pytestmark = skip_unless_feature("webp") ElementTree: ModuleType | None diff --git a/Tests/test_file_wmf.py b/Tests/test_file_wmf.py index 56901f46b07..698853d7ed0 100644 --- a/Tests/test_file_wmf.py +++ b/Tests/test_file_wmf.py @@ -1,7 +1,6 @@ from __future__ import annotations from io import BytesIO -from pathlib import Path from typing import IO import pytest @@ -10,6 +9,10 @@ from .helper import assert_image_equal_tofile, assert_image_similar_tofile, hopper +TYPE_CHECKING = False +if TYPE_CHECKING: + from pathlib import Path + def test_load_raw() -> None: # Test basic EMF open and rendering diff --git a/Tests/test_file_xbm.py b/Tests/test_file_xbm.py index 154f3dcc061..1988c417f6e 100644 --- a/Tests/test_file_xbm.py +++ b/Tests/test_file_xbm.py @@ -1,7 +1,6 @@ from __future__ import annotations from io import BytesIO -from pathlib import Path import pytest @@ -9,6 +8,10 @@ from .helper import hopper +TYPE_CHECKING = False +if TYPE_CHECKING: + from pathlib import Path + PIL151 = b""" #define basic_width 32 #define basic_height 32 diff --git a/Tests/test_font_leaks.py b/Tests/test_font_leaks.py index a5da76faa0b..abff5bc6f28 100644 --- a/Tests/test_font_leaks.py +++ b/Tests/test_font_leaks.py @@ -1,11 +1,13 @@ from __future__ import annotations -import pytest - from PIL import Image, ImageDraw, ImageFont, _util from .helper import PillowLeakTestCase, features, skip_unless_feature +TYPE_CHECKING = False +if TYPE_CHECKING: + import pytest + original_core = ImageFont.core diff --git a/Tests/test_font_pcf.py b/Tests/test_font_pcf.py index d5b080add96..d32fdf50413 100644 --- a/Tests/test_font_pcf.py +++ b/Tests/test_font_pcf.py @@ -2,7 +2,6 @@ import os from io import BytesIO -from pathlib import Path from typing import AnyStr import pytest @@ -14,6 +13,10 @@ skip_unless_feature, ) +TYPE_CHECKING = False +if TYPE_CHECKING: + from pathlib import Path + fontname = "Tests/fonts/10x20-ISO8859-1.pcf" message = "hello, world" diff --git a/Tests/test_font_pcf_charsets.py b/Tests/test_font_pcf_charsets.py index 6ebaa35ffa8..58dec008174 100644 --- a/Tests/test_font_pcf_charsets.py +++ b/Tests/test_font_pcf_charsets.py @@ -1,7 +1,6 @@ from __future__ import annotations import os -from pathlib import Path from typing import TypedDict import pytest @@ -13,6 +12,10 @@ skip_unless_feature, ) +TYPE_CHECKING = False +if TYPE_CHECKING: + from pathlib import Path + fontname = "Tests/fonts/ter-x20b.pcf" diff --git a/Tests/test_fontfile.py b/Tests/test_fontfile.py index bf857e230b8..b16be01ce36 100644 --- a/Tests/test_fontfile.py +++ b/Tests/test_fontfile.py @@ -1,12 +1,15 @@ from __future__ import annotations from io import BytesIO -from pathlib import Path import pytest from PIL import FontFile, Image +TYPE_CHECKING = False +if TYPE_CHECKING: + from pathlib import Path + def test_puti16() -> None: fp = BytesIO() diff --git a/Tests/test_image.py b/Tests/test_image.py index 413631bd8f0..a2a72a97fcb 100644 --- a/Tests/test_image.py +++ b/Tests/test_image.py @@ -8,8 +8,6 @@ import tempfile import warnings from pathlib import Path -from types import ModuleType -from typing import IO import pytest @@ -36,6 +34,11 @@ timeout_unless_slower_valgrind, ) +TYPE_CHECKING = False +if TYPE_CHECKING: + from types import ModuleType + from typing import IO + ElementTree: ModuleType | None try: from defusedxml import ElementTree diff --git a/Tests/test_image_access.py b/Tests/test_image_access.py index 5a2dc664a7f..cdd346fb93d 100644 --- a/Tests/test_image_access.py +++ b/Tests/test_image_access.py @@ -4,7 +4,6 @@ import subprocess import sys import sysconfig -from types import ModuleType import pytest @@ -12,6 +11,10 @@ from .helper import assert_image_equal, hopper, is_win32 +TYPE_CHECKING = False +if TYPE_CHECKING: + from types import ModuleType + numpy: ModuleType | None try: import numpy diff --git a/Tests/test_image_convert.py b/Tests/test_image_convert.py index 547a6c2c678..7458e8cb4ae 100644 --- a/Tests/test_image_convert.py +++ b/Tests/test_image_convert.py @@ -1,13 +1,15 @@ from __future__ import annotations -from pathlib import Path - import pytest from PIL import Image from .helper import assert_image, assert_image_equal, assert_image_similar, hopper +TYPE_CHECKING = False +if TYPE_CHECKING: + from pathlib import Path + def test_sanity() -> None: def convert(im: Image.Image, mode: str) -> None: diff --git a/Tests/test_image_putdata.py b/Tests/test_image_putdata.py index 226cb4c14d8..1e727316d1d 100644 --- a/Tests/test_image_putdata.py +++ b/Tests/test_image_putdata.py @@ -63,7 +63,7 @@ def test_mode_i(mode: str) -> None: im = Image.new(mode, src.size, 0) im.putdata(data, 2, 256) - target = tuple(2 * elt + 256 for elt in cast(tuple[int, ...], data)) + target = tuple(2 * elt + 256 for elt in cast("tuple[int, ...]", data)) assert im.get_flattened_data() == target @@ -73,7 +73,7 @@ def test_mode_F() -> None: im = Image.new("F", src.size, 0) im.putdata(data, 2.0, 256.0) - target = tuple(2.0 * float(elt) + 256.0 for elt in cast(tuple[int, ...], data)) + target = tuple(2.0 * float(elt) + 256.0 for elt in cast("tuple[int, ...]", data)) assert im.get_flattened_data() == target diff --git a/Tests/test_image_resample.py b/Tests/test_image_resample.py index 61b2842cc66..dedf810e488 100644 --- a/Tests/test_image_resample.py +++ b/Tests/test_image_resample.py @@ -1,6 +1,5 @@ from __future__ import annotations -from collections.abc import Generator from contextlib import contextmanager import pytest @@ -14,6 +13,10 @@ mark_if_feature_version, ) +TYPE_CHECKING = False +if TYPE_CHECKING: + from collections.abc import Generator + class TestImagingResampleVulnerability: # see https://github.com/python-pillow/Pillow/issues/1710 diff --git a/Tests/test_image_resize.py b/Tests/test_image_resize.py index b2abe4c9810..98380ffd446 100644 --- a/Tests/test_image_resize.py +++ b/Tests/test_image_resize.py @@ -4,9 +4,7 @@ from __future__ import annotations -from collections.abc import Generator from itertools import permutations -from pathlib import Path import pytest @@ -20,6 +18,11 @@ skip_unless_feature, ) +TYPE_CHECKING = False +if TYPE_CHECKING: + from collections.abc import Generator + from pathlib import Path + class TestImagingCoreResize: def resize( diff --git a/Tests/test_image_split.py b/Tests/test_image_split.py index 43068535e6e..d51a54f9f5c 100644 --- a/Tests/test_image_split.py +++ b/Tests/test_image_split.py @@ -1,13 +1,15 @@ from __future__ import annotations -from pathlib import Path - import pytest from PIL import Image, features from .helper import assert_image_equal, hopper +TYPE_CHECKING = False +if TYPE_CHECKING: + from pathlib import Path + def test_split() -> None: def split(mode: str) -> list[tuple[str, int, int]]: diff --git a/Tests/test_image_transpose.py b/Tests/test_image_transpose.py index d384d81414a..50525639c00 100644 --- a/Tests/test_image_transpose.py +++ b/Tests/test_image_transpose.py @@ -2,12 +2,15 @@ import pytest -from PIL import Image from PIL.Image import Transpose from . import helper from .helper import assert_image_equal +TYPE_CHECKING = False +if TYPE_CHECKING: + from PIL import Image + HOPPER = { mode: helper.hopper(mode).crop((0, 0, 121, 127)).copy() for mode in ["L", "RGB", "I;16", "I;16L", "I;16B"] diff --git a/Tests/test_imagecms.py b/Tests/test_imagecms.py index 7b8051486d4..e95623025de 100644 --- a/Tests/test_imagecms.py +++ b/Tests/test_imagecms.py @@ -6,7 +6,6 @@ import shutil import sys from io import BytesIO -from pathlib import Path from typing import Literal, cast import pytest @@ -22,6 +21,11 @@ is_pypy, ) +TYPE_CHECKING = False +if TYPE_CHECKING: + from pathlib import Path + from typing import Any + try: from PIL import ImageCms from PIL.ImageCms import ImageCmsProfile @@ -31,10 +35,6 @@ # Skipped via setup_module() pass -TYPE_CHECKING = False -if TYPE_CHECKING: - from typing import Any - SRGB = "Tests/icc/sRGB_IEC61966-2-1_black_scaled.icc" HAVE_PROFILE = os.path.exists(SRGB) @@ -644,9 +644,9 @@ def test_auxiliary_channels_isolated() -> None: continue # convert with and without AUX data, test colors are equal - src_colorSpace = cast(Literal["LAB", "XYZ", "sRGB"], src_format[1]) + src_colorSpace = cast("Literal['LAB', 'XYZ', 'sRGB']", src_format[1]) source_profile = ImageCms.createProfile(src_colorSpace) - dst_colorSpace = cast(Literal["LAB", "XYZ", "sRGB"], dst_format[1]) + dst_colorSpace = cast("Literal['LAB', 'XYZ', 'sRGB']", dst_format[1]) destination_profile = ImageCms.createProfile(dst_colorSpace) source_image = src_format[3] test_transform = ImageCms.buildTransform( diff --git a/Tests/test_imagedraw2.py b/Tests/test_imagedraw2.py index e0d368228a0..47943393fd4 100644 --- a/Tests/test_imagedraw2.py +++ b/Tests/test_imagedraw2.py @@ -5,7 +5,6 @@ import pytest from PIL import Image, ImageDraw, ImageDraw2, features -from PIL._typing import Coords from .helper import ( assert_image_equal, @@ -15,6 +14,10 @@ skip_unless_feature, ) +TYPE_CHECKING = False +if TYPE_CHECKING: + from PIL._typing import Coords + BLACK = (0, 0, 0) WHITE = (255, 255, 255) GRAY = (190, 190, 190) diff --git a/Tests/test_imagefont.py b/Tests/test_imagefont.py index 2a8f20ce82e..536a985435b 100644 --- a/Tests/test_imagefont.py +++ b/Tests/test_imagefont.py @@ -13,7 +13,6 @@ import pytest from PIL import Image, ImageDraw, ImageFont, features -from PIL._typing import StrOrBytesPath from .helper import ( assert_image_equal, @@ -25,6 +24,10 @@ skip_unless_feature_version, ) +TYPE_CHECKING = False +if TYPE_CHECKING: + from PIL._typing import StrOrBytesPath + FONT_PATH = "Tests/fonts/FreeMono.ttf" FONT_SIZE = 20 diff --git a/Tests/test_imagemorph.py b/Tests/test_imagemorph.py index 1d2fae1a6fa..74bdbd9e154 100644 --- a/Tests/test_imagemorph.py +++ b/Tests/test_imagemorph.py @@ -1,14 +1,16 @@ # Test the ImageMorphology functionality from __future__ import annotations -from pathlib import Path - import pytest from PIL import Image, ImageMorph, _imagingmorph from .helper import assert_image_equal_tofile, hopper, timeout_unless_slower_valgrind +TYPE_CHECKING = False +if TYPE_CHECKING: + from pathlib import Path + def string_to_img(image_string: str) -> Image.Image: """Turn a string image representation into a binary image""" diff --git a/Tests/test_imageops_usm.py b/Tests/test_imageops_usm.py index 14620c98e47..7fa354c11a0 100644 --- a/Tests/test_imageops_usm.py +++ b/Tests/test_imageops_usm.py @@ -1,11 +1,13 @@ from __future__ import annotations -from collections.abc import Generator - import pytest from PIL import Image, ImageFile, ImageFilter +TYPE_CHECKING = False +if TYPE_CHECKING: + from collections.abc import Generator + @pytest.fixture def test_images() -> Generator[dict[str, ImageFile.ImageFile]]: diff --git a/Tests/test_imagepalette.py b/Tests/test_imagepalette.py index ceaf0034b04..2fcf6cffead 100644 --- a/Tests/test_imagepalette.py +++ b/Tests/test_imagepalette.py @@ -1,7 +1,6 @@ from __future__ import annotations import io -from pathlib import Path import pytest @@ -9,6 +8,10 @@ from .helper import assert_image_equal, assert_image_equal_tofile +TYPE_CHECKING = False +if TYPE_CHECKING: + from pathlib import Path + def test_sanity() -> None: palette = ImagePalette.ImagePalette("RGB", list(range(256)) * 3) diff --git a/Tests/test_imagepath.py b/Tests/test_imagepath.py index 3f56c71a51d..ba018f2d9a1 100644 --- a/Tests/test_imagepath.py +++ b/Tests/test_imagepath.py @@ -3,12 +3,15 @@ import array import math import struct -from collections.abc import Sequence import pytest from PIL import Image, ImagePath +TYPE_CHECKING = False +if TYPE_CHECKING: + from collections.abc import Sequence + def test_path() -> None: p = ImagePath.Path(list(range(10))) diff --git a/Tests/test_imagesequence.py b/Tests/test_imagesequence.py index 32da22e043f..13e06460011 100644 --- a/Tests/test_imagesequence.py +++ b/Tests/test_imagesequence.py @@ -1,13 +1,15 @@ from __future__ import annotations -from pathlib import Path - import pytest from PIL import Image, ImageSequence, PsdImagePlugin, TiffImagePlugin from .helper import assert_image_equal, hopper, skip_unless_feature +TYPE_CHECKING = False +if TYPE_CHECKING: + from pathlib import Path + def test_sanity(tmp_path: Path) -> None: test_file = tmp_path / "temp.im" diff --git a/Tests/test_imagewin_pointers.py b/Tests/test_imagewin_pointers.py index b7421051384..9c7abc4ddf4 100644 --- a/Tests/test_imagewin_pointers.py +++ b/Tests/test_imagewin_pointers.py @@ -1,12 +1,15 @@ from __future__ import annotations from io import BytesIO -from pathlib import Path from PIL import Image, ImageWin from .helper import hopper, is_win32 +TYPE_CHECKING = False +if TYPE_CHECKING: + from pathlib import Path + # see https://github.com/python-pillow/Pillow/pull/1431#issuecomment-144692652 if is_win32(): diff --git a/Tests/test_mode_i16.py b/Tests/test_mode_i16.py index b78b7984fe2..a444b51317d 100644 --- a/Tests/test_mode_i16.py +++ b/Tests/test_mode_i16.py @@ -1,13 +1,15 @@ from __future__ import annotations -from pathlib import Path - import pytest from PIL import Image from .helper import hopper +TYPE_CHECKING = False +if TYPE_CHECKING: + from pathlib import Path + original = hopper().resize((32, 32)).convert("I") diff --git a/Tests/test_numpy.py b/Tests/test_numpy.py index 290c9914d54..f89b172e8ee 100644 --- a/Tests/test_numpy.py +++ b/Tests/test_numpy.py @@ -4,7 +4,7 @@ import pytest -from PIL import Image, _typing +from PIL import Image from .helper import assert_deep_equal, assert_image, hopper, skip_unless_feature @@ -12,6 +12,8 @@ if TYPE_CHECKING: import numpy import numpy.typing as npt + + from PIL import _typing else: numpy = pytest.importorskip("numpy", reason="NumPy not installed") diff --git a/Tests/test_pickle.py b/Tests/test_pickle.py index 2447ae67ad7..56e173a4d64 100644 --- a/Tests/test_pickle.py +++ b/Tests/test_pickle.py @@ -1,7 +1,6 @@ from __future__ import annotations import pickle -from pathlib import Path import pytest @@ -9,6 +8,10 @@ from .helper import assert_image_equal, skip_unless_feature +TYPE_CHECKING = False +if TYPE_CHECKING: + from pathlib import Path + FONT_SIZE = 20 FONT_PATH = "Tests/fonts/DejaVuSans/DejaVuSans.ttf" diff --git a/Tests/test_psdraw.py b/Tests/test_psdraw.py index e5c6f7d85cc..e017bc54e6a 100644 --- a/Tests/test_psdraw.py +++ b/Tests/test_psdraw.py @@ -3,12 +3,15 @@ import os import sys from io import BytesIO -from pathlib import Path - -import pytest from PIL import Image, PSDraw +TYPE_CHECKING = False +if TYPE_CHECKING: + from pathlib import Path + + import pytest + def _create_document(ps: PSDraw.PSDraw) -> None: title = "hopper" diff --git a/Tests/test_tiff_ifdrational.py b/Tests/test_tiff_ifdrational.py index 8cf48ba7dc6..3a4802b9287 100644 --- a/Tests/test_tiff_ifdrational.py +++ b/Tests/test_tiff_ifdrational.py @@ -2,7 +2,6 @@ import math from fractions import Fraction -from pathlib import Path import pytest @@ -11,6 +10,10 @@ from .helper import hopper, skip_unless_feature +TYPE_CHECKING = False +if TYPE_CHECKING: + from pathlib import Path + def _test_equal( num: float | Fraction | IFDRational, diff --git a/checks/check_imaging_leaks.py b/checks/check_imaging_leaks.py index 65090b6b6ae..14f3c309814 100644 --- a/checks/check_imaging_leaks.py +++ b/checks/check_imaging_leaks.py @@ -1,13 +1,16 @@ from __future__ import annotations import sys -from collections.abc import Callable from typing import Any import pytest from PIL import Image +TYPE_CHECKING = False +if TYPE_CHECKING: + from collections.abc import Callable + min_iterations = 100 max_iterations = 10000 diff --git a/checks/check_j2k_overflow.py b/checks/check_j2k_overflow.py index 58566c4b219..ffeb3b187f4 100644 --- a/checks/check_j2k_overflow.py +++ b/checks/check_j2k_overflow.py @@ -1,11 +1,13 @@ from __future__ import annotations -from pathlib import Path - import pytest from PIL import Image +TYPE_CHECKING = False +if TYPE_CHECKING: + from pathlib import Path + def test_j2k_overflow(tmp_path: Path) -> None: im = Image.new("RGBA", (1024, 131584)) diff --git a/checks/check_large_memory.py b/checks/check_large_memory.py index c9feda3b1b0..012a94b47fc 100644 --- a/checks/check_large_memory.py +++ b/checks/check_large_memory.py @@ -1,13 +1,16 @@ from __future__ import annotations import sys -from pathlib import Path -from types import ModuleType import pytest from PIL import Image +TYPE_CHECKING = False +if TYPE_CHECKING: + from pathlib import Path + from types import ModuleType + # This test is not run automatically. # # It requires > 2gb memory for the >2 gigapixel image generated in the diff --git a/checks/check_large_memory_numpy.py b/checks/check_large_memory_numpy.py index 458b0ab72d2..bf1ad9ae0de 100644 --- a/checks/check_large_memory_numpy.py +++ b/checks/check_large_memory_numpy.py @@ -1,12 +1,15 @@ from __future__ import annotations import sys -from pathlib import Path import pytest from PIL import Image +TYPE_CHECKING = False +if TYPE_CHECKING: + from pathlib import Path + # This test is not run automatically. # # It requires > 2gb memory for the >2 gigapixel image generated in the diff --git a/checks/check_png_dos.py b/checks/check_png_dos.py index 1bfb94ab7f7..4eab65fcfd8 100644 --- a/checks/check_png_dos.py +++ b/checks/check_png_dos.py @@ -3,10 +3,12 @@ import zlib from io import BytesIO -import pytest - from PIL import Image, ImageFile, PngImagePlugin +TYPE_CHECKING = False +if TYPE_CHECKING: + import pytest + TEST_FILE = "Tests/images/png_decompression_dos.png" diff --git a/docs/conf.py b/docs/conf.py index 189758944d9..45d8840eeb9 100644 --- a/docs/conf.py +++ b/docs/conf.py @@ -121,7 +121,11 @@ # generating warnings in “nitpicky mode”. Note that type should include the domain name # if present. Example entries would be ('py:func', 'int') or # ('envvar', 'LD_LIBRARY_PATH'). -nitpick_ignore = [("py:class", "_CmsProfileCompatible")] +nitpick_ignore = [ + ("py:class", "_CmsProfileCompatible"), + ("py:class", "_Ink"), + ("py:class", "_Palette"), +] # -- Options for HTML output ---------------------------------------------- diff --git a/docs/reference/internal_modules.rst b/docs/reference/internal_modules.rst index 41a8837b30a..fb0b5a1a894 100644 --- a/docs/reference/internal_modules.rst +++ b/docs/reference/internal_modules.rst @@ -37,6 +37,10 @@ on some Python versions. Typing alias. +.. py:class:: Coords + + Typing alias. + .. py:class:: IntegralLike Typing alias. diff --git a/pyproject.toml b/pyproject.toml index eb53829d21f..9cd398030fc 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -153,6 +153,7 @@ lint.select = [ "PT", # flake8-pytest-style "PYI", # flake8-pyi "RUF100", # unused noqa (yesqa) + "TC", # flake8-type-checking "UP", # pyupgrade "W", # pycodestyle warnings "YTT", # flake8-2020 diff --git a/setup.py b/setup.py index 168d4f237c9..8240340e4a7 100644 --- a/setup.py +++ b/setup.py @@ -15,7 +15,6 @@ import subprocess import sys import warnings -from collections.abc import Iterator from pybind11.setup_helpers import ParallelCompile from setuptools import Extension, setup @@ -23,6 +22,8 @@ TYPE_CHECKING = False if TYPE_CHECKING: + from collections.abc import Iterator + from setuptools import _BuildInfo configuration: dict[str, list[str]] = {} diff --git a/src/PIL/BdfFontFile.py b/src/PIL/BdfFontFile.py index 098779bfd6e..ebc8a9e6505 100644 --- a/src/PIL/BdfFontFile.py +++ b/src/PIL/BdfFontFile.py @@ -23,10 +23,12 @@ from __future__ import annotations -from typing import BinaryIO - from . import FontFile, Image +TYPE_CHECKING = False +if TYPE_CHECKING: + from typing import BinaryIO + def bdf_char( f: BinaryIO, diff --git a/src/PIL/BlpImagePlugin.py b/src/PIL/BlpImagePlugin.py index c3f5ae3ce6e..fddfd1fd377 100644 --- a/src/PIL/BlpImagePlugin.py +++ b/src/PIL/BlpImagePlugin.py @@ -36,10 +36,13 @@ import struct from enum import IntEnum from io import BytesIO -from typing import IO from . import Image, ImageFile +TYPE_CHECKING = False +if TYPE_CHECKING: + from typing import IO + class Format(IntEnum): JPEG = 0 diff --git a/src/PIL/BmpImagePlugin.py b/src/PIL/BmpImagePlugin.py index 907931b926e..d6ebf3c3aa3 100644 --- a/src/PIL/BmpImagePlugin.py +++ b/src/PIL/BmpImagePlugin.py @@ -25,7 +25,6 @@ from __future__ import annotations import os -from typing import IO, Any from . import Image, ImageFile, ImagePalette from ._binary import i16le as i16 @@ -34,6 +33,10 @@ from ._binary import o16le as o16 from ._binary import o32le as o32 +TYPE_CHECKING = False +if TYPE_CHECKING: + from typing import IO, Any + # # -------------------------------------------------------------------- # Read BMP file diff --git a/src/PIL/BufrStubImagePlugin.py b/src/PIL/BufrStubImagePlugin.py index d82c4c746c3..5250b7caf4b 100644 --- a/src/PIL/BufrStubImagePlugin.py +++ b/src/PIL/BufrStubImagePlugin.py @@ -11,10 +11,13 @@ from __future__ import annotations import os -from typing import IO from . import Image, ImageFile +TYPE_CHECKING = False +if TYPE_CHECKING: + from typing import IO + _handler = None diff --git a/src/PIL/ContainerIO.py b/src/PIL/ContainerIO.py index 31427a7abff..9cdec4787c5 100644 --- a/src/PIL/ContainerIO.py +++ b/src/PIL/ContainerIO.py @@ -16,12 +16,12 @@ from __future__ import annotations import io -from collections.abc import Iterable -from typing import IO, AnyStr, NoReturn +from typing import IO, AnyStr TYPE_CHECKING = False if TYPE_CHECKING: - from typing import Self + from collections.abc import Iterable + from typing import NoReturn, Self class ContainerIO(IO[AnyStr]): diff --git a/src/PIL/DdsImagePlugin.py b/src/PIL/DdsImagePlugin.py index 2ca9f3abb27..e09a2b867a1 100644 --- a/src/PIL/DdsImagePlugin.py +++ b/src/PIL/DdsImagePlugin.py @@ -15,13 +15,16 @@ import struct import sys from enum import IntEnum, IntFlag -from typing import IO from . import Image, ImageFile, ImagePalette from ._binary import i32le as i32 from ._binary import o8 from ._binary import o32le as o32 +TYPE_CHECKING = False +if TYPE_CHECKING: + from typing import IO + # Magic ("DDS ") DDS_MAGIC = 0x20534444 diff --git a/src/PIL/EpsImagePlugin.py b/src/PIL/EpsImagePlugin.py index 363ba19e130..8717e4df55b 100644 --- a/src/PIL/EpsImagePlugin.py +++ b/src/PIL/EpsImagePlugin.py @@ -27,11 +27,14 @@ import subprocess import sys import tempfile -from typing import IO from . import Image, ImageFile from ._binary import i32le as i32 +TYPE_CHECKING = False +if TYPE_CHECKING: + from typing import IO + # -------------------------------------------------------------------- diff --git a/src/PIL/FontFile.py b/src/PIL/FontFile.py index c3be4ae3ddd..fc32848cd6d 100644 --- a/src/PIL/FontFile.py +++ b/src/PIL/FontFile.py @@ -16,10 +16,13 @@ from __future__ import annotations import os -from typing import BinaryIO from . import Image, ImageFont, _binary +TYPE_CHECKING = False +if TYPE_CHECKING: + from typing import BinaryIO + WIDTH = 800 diff --git a/src/PIL/GdImageFile.py b/src/PIL/GdImageFile.py index 4ff96f1fa04..c8ba8784560 100644 --- a/src/PIL/GdImageFile.py +++ b/src/PIL/GdImageFile.py @@ -28,12 +28,15 @@ class is not registered for use with :py:func:`PIL.Image.open()`. To open a from __future__ import annotations -from typing import IO - from . import Image, ImageFile, ImagePalette, UnidentifiedImageError from ._binary import i16be as i16 from ._binary import i32be as i32 -from ._typing import StrOrBytesPath + +TYPE_CHECKING = False +if TYPE_CHECKING: + from typing import IO + + from ._typing import StrOrBytesPath class GdImageFile(ImageFile.ImageFile): diff --git a/src/PIL/GifImagePlugin.py b/src/PIL/GifImagePlugin.py index b8db5d83284..e686dc80851 100644 --- a/src/PIL/GifImagePlugin.py +++ b/src/PIL/GifImagePlugin.py @@ -31,7 +31,7 @@ import subprocess from enum import IntEnum from functools import cached_property -from typing import Any, NamedTuple, cast +from typing import NamedTuple, cast from . import ( Image, @@ -49,7 +49,7 @@ TYPE_CHECKING = False if TYPE_CHECKING: - from typing import IO, Literal + from typing import IO, Any, Literal from . import _imaging from ._typing import Buffer @@ -355,7 +355,7 @@ def _rgb(color: int) -> tuple[int, int, int]: if color * 3 + 3 > len(self._frame_palette.palette): color = 0 return cast( - tuple[int, int, int], + "tuple[int, int, int]", tuple(self._frame_palette.palette[color * 3 : color * 3 + 3]), ) else: diff --git a/src/PIL/GribStubImagePlugin.py b/src/PIL/GribStubImagePlugin.py index 3784ef2f134..aa1b1eda586 100644 --- a/src/PIL/GribStubImagePlugin.py +++ b/src/PIL/GribStubImagePlugin.py @@ -11,10 +11,13 @@ from __future__ import annotations import os -from typing import IO from . import Image, ImageFile +TYPE_CHECKING = False +if TYPE_CHECKING: + from typing import IO + _handler = None diff --git a/src/PIL/Hdf5StubImagePlugin.py b/src/PIL/Hdf5StubImagePlugin.py index 1a56660f7bd..16af6504070 100644 --- a/src/PIL/Hdf5StubImagePlugin.py +++ b/src/PIL/Hdf5StubImagePlugin.py @@ -11,10 +11,13 @@ from __future__ import annotations import os -from typing import IO from . import Image, ImageFile +TYPE_CHECKING = False +if TYPE_CHECKING: + from typing import IO + _handler = None diff --git a/src/PIL/IcnsImagePlugin.py b/src/PIL/IcnsImagePlugin.py index cb7a74c2e3b..6135e0693aa 100644 --- a/src/PIL/IcnsImagePlugin.py +++ b/src/PIL/IcnsImagePlugin.py @@ -22,10 +22,13 @@ import os import struct import sys -from typing import IO from . import Image, ImageFile, PngImagePlugin, features +TYPE_CHECKING = False +if TYPE_CHECKING: + from typing import IO + enable_jpeg2k = features.check_codec("jpg_2000") if enable_jpeg2k: from . import Jpeg2KImagePlugin diff --git a/src/PIL/IcoImagePlugin.py b/src/PIL/IcoImagePlugin.py index 8dd57ff858a..c145d251e1c 100644 --- a/src/PIL/IcoImagePlugin.py +++ b/src/PIL/IcoImagePlugin.py @@ -39,7 +39,7 @@ import warnings from io import BytesIO from math import ceil, log -from typing import IO, NamedTuple +from typing import NamedTuple from . import BmpImagePlugin, Image, ImageFile, PngImagePlugin from ._binary import i16le as i16 @@ -48,6 +48,10 @@ from ._binary import o16le as o16 from ._binary import o32le as o32 +TYPE_CHECKING = False +if TYPE_CHECKING: + from typing import IO + # # -------------------------------------------------------------------- diff --git a/src/PIL/ImImagePlugin.py b/src/PIL/ImImagePlugin.py index ef54f16e97e..78861f3edfb 100644 --- a/src/PIL/ImImagePlugin.py +++ b/src/PIL/ImImagePlugin.py @@ -28,11 +28,15 @@ import os import re -from typing import IO, Any from . import Image, ImageFile, ImagePalette from ._util import DeferredError +TYPE_CHECKING = False +if TYPE_CHECKING: + from typing import IO, Any + + # -------------------------------------------------------------------- # Standard tags diff --git a/src/PIL/Image.py b/src/PIL/Image.py index ddbaec20a05..48862b2dfc9 100644 --- a/src/PIL/Image.py +++ b/src/PIL/Image.py @@ -1193,7 +1193,7 @@ def convert_transparency( if trns is not None: try: new_im.info["transparency"] = new_im.palette.getcolor( - cast(tuple[int, ...], trns), # trns was converted to RGB + cast("tuple[int, ...]", trns), # trns was converted to RGB new_im, ) except Exception: @@ -1252,7 +1252,8 @@ def convert_transparency( if new_im.mode == "P" and new_im.palette: try: new_im.info["transparency"] = new_im.palette.getcolor( - cast(tuple[int, ...], trns), new_im # trns was converted to RGB + cast("tuple[int, ...]", trns), # trns was converted to RGB + new_im, ) except ValueError as e: del new_im.info["transparency"] @@ -2402,7 +2403,7 @@ def resize( factor_x = int((box[2] - box[0]) / size[0] / reducing_gap) or 1 factor_y = int((box[3] - box[1]) / size[1] / reducing_gap) or 1 if factor_x > 1 or factor_y > 1: - reduce_box = self._get_safe_box(size, cast(Resampling, resample), box) + reduce_box = self._get_safe_box(size, cast("Resampling", resample), box) factor = (factor_x, factor_y) self = ( self.reduce(factor, box=reduce_box) @@ -2692,7 +2693,7 @@ def save( else: fp = builtins.open(filename, "w+b") else: - fp = cast(IO[bytes], fp) + fp = cast("IO[bytes]", fp) try: save_handler(self, fp, filename) @@ -3216,7 +3217,7 @@ def new( and isinstance(color, (list, tuple)) and all(isinstance(i, int) for i in color) ): - color_ints: tuple[int, ...] = cast(tuple[int, ...], tuple(color)) + color_ints: tuple[int, ...] = cast("tuple[int, ...]", tuple(color)) if len(color_ints) == 3 or len(color_ints) == 4: # RGB or RGBA value for a P image from . import ImagePalette @@ -3627,7 +3628,7 @@ def open( fp = builtins.open(filename, "rb") exclusive_fp = True else: - fp = cast(IO[bytes], fp) + fp = cast("IO[bytes]", fp) try: fp.seek(0) diff --git a/src/PIL/ImageCms.py b/src/PIL/ImageCms.py index 9bcf8cb7fb7..5e59afd4fa6 100644 --- a/src/PIL/ImageCms.py +++ b/src/PIL/ImageCms.py @@ -23,17 +23,17 @@ import sys from enum import IntEnum, IntFlag from functools import reduce -from typing import Literal, SupportsFloat, SupportsInt, Union from . import Image -from ._typing import SupportsRead + +TYPE_CHECKING = False +if TYPE_CHECKING: + from typing import Literal, SupportsFloat, SupportsInt + + from ._typing import SupportsRead try: from . import _imagingcms as core - - _CmsProfileCompatible = Union[ - str, SupportsRead[bytes], core.CmsProfile, "ImageCmsProfile" - ] except ImportError as ex: # Allow error import for doc purposes, but error out when accessing # anything in core. @@ -265,6 +265,12 @@ def tobytes(self) -> bytes: return core.profile_tobytes(self.profile) +if TYPE_CHECKING: + _CmsProfileCompatible = ( + str | SupportsRead[bytes] | core.CmsProfile | ImageCmsProfile + ) + + class ImageCmsTransform(Image.ImagePointHandler): """ Transform. This can be used with the procedural API, or with the standard diff --git a/src/PIL/ImageDraw.py b/src/PIL/ImageDraw.py index 561c44729cf..e6e3be01bd6 100644 --- a/src/PIL/ImageDraw.py +++ b/src/PIL/ImageDraw.py @@ -33,14 +33,13 @@ import math import struct -from collections.abc import Sequence from typing import cast from . import Image, ImageColor, ImageFont, ImageText TYPE_CHECKING = False if TYPE_CHECKING: - from collections.abc import Callable + from collections.abc import Callable, Sequence from types import ModuleType from typing import Any, AnyStr @@ -237,10 +236,10 @@ def line( if joint == "curve" and width > 4: points: Sequence[Sequence[float]] if isinstance(xy[0], (list, tuple)): - points = cast(Sequence[Sequence[float]], xy) + points = cast("Sequence[Sequence[float]]", xy) else: points = [ - cast(Sequence[float], tuple(xy[i : i + 2])) + cast("Sequence[float]", tuple(xy[i : i + 2])) for i in range(0, len(xy), 2) ] for i in range(1, len(points) - 1): @@ -399,9 +398,9 @@ def rounded_rectangle( ) -> None: """Draw a rounded rectangle.""" if isinstance(xy[0], (list, tuple)): - (x0, y0), (x1, y1) = cast(Sequence[Sequence[float]], xy) + (x0, y0), (x1, y1) = cast("Sequence[Sequence[float]]", xy) else: - x0, y0, x1, y1 = cast(Sequence[float], xy) + x0, y0, x1, y1 = cast("Sequence[float]", xy) if x1 < x0: msg = "x1 must be greater than or equal to x0" raise ValueError(msg) @@ -920,7 +919,7 @@ def _compute_regular_polygon_vertices( msg = "bounding_circle should only contain numeric data" raise ValueError(msg) - *centroid, polygon_radius = cast(list[float], list(bounding_circle)) + *centroid, polygon_radius = cast("list[float]", list(bounding_circle)) elif len(bounding_circle) == 2 and isinstance(bounding_circle[0], (list, tuple)): if not all( isinstance(i, (int, float)) for i in bounding_circle[0] @@ -932,8 +931,8 @@ def _compute_regular_polygon_vertices( msg = "bounding_circle centre should contain 2D coordinates (e.g. (x, y))" raise ValueError(msg) - centroid = cast(list[float], list(bounding_circle[0])) - polygon_radius = cast(float, bounding_circle[1]) + centroid = cast("list[float]", list(bounding_circle[0])) + polygon_radius = cast("float", bounding_circle[1]) else: msg = ( "bounding_circle should contain 2D coordinates " diff --git a/src/PIL/ImageDraw2.py b/src/PIL/ImageDraw2.py index 2c9e39b2c41..333edb71d34 100644 --- a/src/PIL/ImageDraw2.py +++ b/src/PIL/ImageDraw2.py @@ -25,10 +25,13 @@ from __future__ import annotations -from typing import Any, AnyStr, BinaryIO - from . import Image, ImageColor, ImageDraw, ImageFont, ImagePath -from ._typing import Coords, StrOrBytesPath + +TYPE_CHECKING = False +if TYPE_CHECKING: + from typing import Any, AnyStr, BinaryIO + + from ._typing import Coords, StrOrBytesPath class Pen: diff --git a/src/PIL/ImageFile.py b/src/PIL/ImageFile.py index eaa1e45812c..c5bba90c11d 100644 --- a/src/PIL/ImageFile.py +++ b/src/PIL/ImageFile.py @@ -34,14 +34,14 @@ import logging import os import struct -from typing import IO, Any, NamedTuple, cast +from typing import IO, NamedTuple, cast from . import ExifTags, Image from ._util import DeferredError, is_path TYPE_CHECKING = False if TYPE_CHECKING: - from typing import Self + from typing import Any, Self from ._typing import StrOrBytesPath @@ -142,7 +142,7 @@ def __init__( self._exclusive_fp = True else: # stream - self.fp = cast(IO[bytes], fp) + self.fp = cast("IO[bytes]", fp) self.filename = filename if filename is not None else "" # can be overridden self._exclusive_fp = False diff --git a/src/PIL/ImageFilter.py b/src/PIL/ImageFilter.py index 823365af076..8b9ffe39be9 100644 --- a/src/PIL/ImageFilter.py +++ b/src/PIL/ImageFilter.py @@ -18,12 +18,11 @@ import abc import functools -from collections.abc import Sequence from typing import cast TYPE_CHECKING = False if TYPE_CHECKING: - from collections.abc import Callable + from collections.abc import Callable, Sequence from types import ModuleType from typing import Any @@ -455,7 +454,7 @@ def __init__( # Convert to a flat list if table and isinstance(table[0], (list, tuple)): - raw_table = cast(Sequence[Sequence[int]], table) + raw_table = cast("Sequence[Sequence[int]]", table) flat_table: list[int] = [] for pixel in raw_table: if len(pixel) != channels: diff --git a/src/PIL/ImageFont.py b/src/PIL/ImageFont.py index 224beef695a..3c26e99bccc 100644 --- a/src/PIL/ImageFont.py +++ b/src/PIL/ImageFont.py @@ -35,17 +35,19 @@ from enum import IntEnum from io import BytesIO from types import ModuleType -from typing import IO, Any, BinaryIO, NotRequired, TypedDict, cast +from typing import IO, NotRequired, TypedDict, cast from . import Image -from ._typing import StrOrBytesPath from ._util import DeferredError, is_path TYPE_CHECKING = False if TYPE_CHECKING: + from typing import Any, BinaryIO + from . import ImageFile from ._imaging import ImagingFont from ._imagingft import Font + from ._typing import StrOrBytesPath class Axis(TypedDict): @@ -299,7 +301,7 @@ def load_from_bytes(f: IO[bytes]) -> None: font, size, index, encoding, layout_engine=layout_engine ) else: - load_from_bytes(cast(IO[bytes], font)) + load_from_bytes(cast("IO[bytes]", font)) def __getstate__(self) -> list[Any]: return [self.path, self.size, self.index, self.encoding, self.layout_engine] diff --git a/src/PIL/ImageOps.py b/src/PIL/ImageOps.py index cdec4d5dc7d..810fcefca54 100644 --- a/src/PIL/ImageOps.py +++ b/src/PIL/ImageOps.py @@ -21,11 +21,15 @@ import functools import operator import re -from collections.abc import Sequence -from typing import Literal, Protocol, cast, overload +from typing import Protocol, cast, overload from . import ExifTags, Image, ImagePalette +TYPE_CHECKING = False +if TYPE_CHECKING: + from collections.abc import Sequence + from typing import Literal + # # helpers @@ -214,9 +218,9 @@ def colorize( raise ValueError(msg) # Define colors from arguments - rgb_black = cast(Sequence[int], _color(black, "RGB")) - rgb_white = cast(Sequence[int], _color(white, "RGB")) - rgb_mid = cast(Sequence[int], _color(mid, "RGB")) if mid is not None else None + rgb_black = cast("Sequence[int]", _color(black, "RGB")) + rgb_white = cast("Sequence[int]", _color(white, "RGB")) + rgb_mid = cast("Sequence[int]", _color(mid, "RGB")) if mid is not None else None # Empty lists for the mapping red = [] diff --git a/src/PIL/ImagePalette.py b/src/PIL/ImagePalette.py index cd1e9583826..c25d80e47c1 100644 --- a/src/PIL/ImagePalette.py +++ b/src/PIL/ImagePalette.py @@ -18,13 +18,14 @@ from __future__ import annotations import array -from collections.abc import Sequence -from typing import IO from . import GimpGradientFile, GimpPaletteFile, ImageColor, PaletteFile TYPE_CHECKING = False if TYPE_CHECKING: + from collections.abc import Sequence + from typing import IO + from . import Image diff --git a/src/PIL/ImageSequence.py b/src/PIL/ImageSequence.py index 9d3553a75a8..0a6ad66091d 100644 --- a/src/PIL/ImageSequence.py +++ b/src/PIL/ImageSequence.py @@ -16,13 +16,13 @@ ## from __future__ import annotations -from . import Image - TYPE_CHECKING = False if TYPE_CHECKING: from collections.abc import Callable from typing import Self + from . import Image + class Iterator: """ diff --git a/src/PIL/ImageShow.py b/src/PIL/ImageShow.py index dd8aa0d36c2..f24f4cf1056 100644 --- a/src/PIL/ImageShow.py +++ b/src/PIL/ImageShow.py @@ -19,10 +19,13 @@ import subprocess import sys from shlex import quote -from typing import Any from . import Image +TYPE_CHECKING = False +if TYPE_CHECKING: + from typing import Any + _viewers: list[Viewer] = [] diff --git a/src/PIL/ImageText.py b/src/PIL/ImageText.py index 96601813ce0..327dc87307c 100644 --- a/src/PIL/ImageText.py +++ b/src/PIL/ImageText.py @@ -5,7 +5,10 @@ from typing import AnyStr, Generic, NamedTuple from . import ImageFont -from ._typing import _Ink + +TYPE_CHECKING = False +if TYPE_CHECKING: + from ._typing import _Ink class _Line(NamedTuple): diff --git a/src/PIL/ImageTk.py b/src/PIL/ImageTk.py index 3a4cb81e9ef..fb02b0211ca 100644 --- a/src/PIL/ImageTk.py +++ b/src/PIL/ImageTk.py @@ -28,12 +28,13 @@ import tkinter from io import BytesIO -from typing import Any from . import Image, ImageFile TYPE_CHECKING = False if TYPE_CHECKING: + from typing import Any + from ._typing import CapsuleType # -------------------------------------------------------------------- diff --git a/src/PIL/ImageTransform.py b/src/PIL/ImageTransform.py index fb144ff38a1..f71f6c53be6 100644 --- a/src/PIL/ImageTransform.py +++ b/src/PIL/ImageTransform.py @@ -14,11 +14,13 @@ # from __future__ import annotations -from collections.abc import Sequence -from typing import Any - from . import Image +TYPE_CHECKING = False +if TYPE_CHECKING: + from collections.abc import Sequence + from typing import Any + class Transform(Image.ImageTransformHandler): """Base class for other transforms defined in :py:mod:`~PIL.ImageTransform`.""" diff --git a/src/PIL/IptcImagePlugin.py b/src/PIL/IptcImagePlugin.py index 9c8be8b4e36..d00450a7055 100644 --- a/src/PIL/IptcImagePlugin.py +++ b/src/PIL/IptcImagePlugin.py @@ -212,7 +212,7 @@ class FakeImage: fake_im = FakeImage() fake_im.__class__ = IptcImageFile # type: ignore[assignment] - iptc_im = cast(IptcImageFile, fake_im) + iptc_im = cast("IptcImageFile", fake_im) # parse the IPTC information chunk iptc_im.info = {} diff --git a/src/PIL/Jpeg2KImagePlugin.py b/src/PIL/Jpeg2KImagePlugin.py index 7d27fcc8fff..13f7cc774f0 100644 --- a/src/PIL/Jpeg2KImagePlugin.py +++ b/src/PIL/Jpeg2KImagePlugin.py @@ -93,9 +93,9 @@ def next_box_type(self) -> bytes: self.remaining_in_box = -1 # Read the length and type of the next box - lbox, tbox = cast(tuple[int, bytes], self.read_fields(">I4s")) + lbox, tbox = cast("tuple[int, bytes]", self.read_fields(">I4s")) if lbox == 1: - lbox = cast(int, self.read_fields(">Q")[0]) + lbox = cast("int", self.read_fields(">Q")[0]) hlen = 16 else: hlen = 8 diff --git a/src/PIL/MpegImagePlugin.py b/src/PIL/MpegImagePlugin.py index 47ebe9d62c4..666179c68cc 100644 --- a/src/PIL/MpegImagePlugin.py +++ b/src/PIL/MpegImagePlugin.py @@ -16,7 +16,10 @@ from . import Image, ImageFile from ._binary import i8 -from ._typing import SupportsRead + +TYPE_CHECKING = False +if TYPE_CHECKING: + from ._typing import SupportsRead # # Bitstream parser diff --git a/src/PIL/MpoImagePlugin.py b/src/PIL/MpoImagePlugin.py index bee0a56f9ac..69374482dd3 100644 --- a/src/PIL/MpoImagePlugin.py +++ b/src/PIL/MpoImagePlugin.py @@ -21,7 +21,7 @@ import os import struct -from typing import IO, Any, cast +from typing import cast from . import ( Image, @@ -33,6 +33,10 @@ from ._binary import o32le from ._util import DeferredError +TYPE_CHECKING = False +if TYPE_CHECKING: + from typing import IO, Any + def _save(im: Image.Image, fp: IO[bytes], filename: str | bytes) -> None: JpegImagePlugin._save(im, fp, filename) @@ -183,7 +187,7 @@ def adopt( double call to _open. """ jpeg_instance.__class__ = MpoImageFile - mpo_instance = cast(MpoImageFile, jpeg_instance) + mpo_instance = cast("MpoImageFile", jpeg_instance) mpo_instance._after_jpeg_open(mpheader) return mpo_instance diff --git a/src/PIL/MspImagePlugin.py b/src/PIL/MspImagePlugin.py index 9df5cfd9345..24cece0b60c 100644 --- a/src/PIL/MspImagePlugin.py +++ b/src/PIL/MspImagePlugin.py @@ -26,12 +26,14 @@ import io import struct -from typing import IO from . import Image, ImageFile from ._binary import i16le as i16 from ._binary import o16le as o16 +TYPE_CHECKING = False +if TYPE_CHECKING: + from typing import IO # # read MSP files diff --git a/src/PIL/PSDraw.py b/src/PIL/PSDraw.py index e6b74a91888..d0e4d561a2a 100644 --- a/src/PIL/PSDraw.py +++ b/src/PIL/PSDraw.py @@ -17,11 +17,12 @@ from __future__ import annotations import sys -from typing import IO from . import EpsImagePlugin TYPE_CHECKING = False +if TYPE_CHECKING: + from typing import IO ## diff --git a/src/PIL/PaletteFile.py b/src/PIL/PaletteFile.py index 2a26e5d4e22..f7b4e708afa 100644 --- a/src/PIL/PaletteFile.py +++ b/src/PIL/PaletteFile.py @@ -14,10 +14,12 @@ # from __future__ import annotations -from typing import IO - from ._binary import o8 +TYPE_CHECKING = False +if TYPE_CHECKING: + from typing import IO + class PaletteFile: """File handler for Teragon-style palette files.""" diff --git a/src/PIL/PalmImagePlugin.py b/src/PIL/PalmImagePlugin.py index 232adf3d3bb..bd1371e5d05 100644 --- a/src/PIL/PalmImagePlugin.py +++ b/src/PIL/PalmImagePlugin.py @@ -8,12 +8,14 @@ ## from __future__ import annotations -from typing import IO - from . import Image, ImageFile from ._binary import o8 from ._binary import o16be as o16b +TYPE_CHECKING = False +if TYPE_CHECKING: + from typing import IO + # fmt: off _Palm8BitColormapValues = ( (255, 255, 255), (255, 204, 255), (255, 153, 255), (255, 102, 255), diff --git a/src/PIL/PcxImagePlugin.py b/src/PIL/PcxImagePlugin.py index 7fb1f2db9cf..74ff1f431ba 100644 --- a/src/PIL/PcxImagePlugin.py +++ b/src/PIL/PcxImagePlugin.py @@ -28,13 +28,16 @@ import io import logging -from typing import IO from . import Image, ImageFile, ImagePalette from ._binary import i16le as i16 from ._binary import o8 from ._binary import o16le as o16 +TYPE_CHECKING = False +if TYPE_CHECKING: + from typing import IO + logger = logging.getLogger(__name__) diff --git a/src/PIL/PdfImagePlugin.py b/src/PIL/PdfImagePlugin.py index cb26786b0d9..f01e43fa1fd 100644 --- a/src/PIL/PdfImagePlugin.py +++ b/src/PIL/PdfImagePlugin.py @@ -25,10 +25,13 @@ import math import os import time -from typing import IO, Any from . import Image, ImageFile, ImageSequence, PdfParser, features +TYPE_CHECKING = False +if TYPE_CHECKING: + from typing import IO, Any + # # -------------------------------------------------------------------- diff --git a/src/PIL/PngImagePlugin.py b/src/PIL/PngImagePlugin.py index 1f01ea9f04c..17f5c05b09c 100644 --- a/src/PIL/PngImagePlugin.py +++ b/src/PIL/PngImagePlugin.py @@ -1257,7 +1257,7 @@ def _write_multiple_frames( _apply_encoderinfo(default_im, im.encoderinfo) ImageFile._save( default_im, - cast(IO[bytes], _idat(fp, chunk)), + cast("IO[bytes]", _idat(fp, chunk)), [ImageFile._Tile("zip", (0, 0) + im.size, 0, rawmode)], ) @@ -1299,14 +1299,14 @@ def _write_multiple_frames( # first frame must be in IDAT chunks for backwards compatibility ImageFile._save( im_frame, - cast(IO[bytes], _idat(fp, chunk)), + cast("IO[bytes]", _idat(fp, chunk)), [ImageFile._Tile("zip", (0, 0) + im_frame.size, 0, rawmode)], ) else: fdat_chunks = _fdat(fp, chunk, seq_num) ImageFile._save( im_frame, - cast(IO[bytes], fdat_chunks), + cast("IO[bytes]", fdat_chunks), [ImageFile._Tile("zip", (0, 0) + im_frame.size, 0, rawmode)], ) seq_num = fdat_chunks.seq_num @@ -1511,7 +1511,7 @@ def _save( _apply_encoderinfo(single_im, im.encoderinfo) ImageFile._save( single_im, - cast(IO[bytes], _idat(fp, chunk)), + cast("IO[bytes]", _idat(fp, chunk)), [ImageFile._Tile("zip", (0, 0) + single_im.size, 0, rawmode)], ) diff --git a/src/PIL/PpmImagePlugin.py b/src/PIL/PpmImagePlugin.py index ca6093385be..05a79f15a7f 100644 --- a/src/PIL/PpmImagePlugin.py +++ b/src/PIL/PpmImagePlugin.py @@ -16,13 +16,16 @@ from __future__ import annotations import math -from typing import IO from . import Image, ImageFile from ._binary import i16be as i16 from ._binary import o8 from ._binary import o32le as o32 +TYPE_CHECKING = False +if TYPE_CHECKING: + from typing import IO + # # -------------------------------------------------------------------- diff --git a/src/PIL/PsdImagePlugin.py b/src/PIL/PsdImagePlugin.py index 201909abde6..f3f0714bd26 100644 --- a/src/PIL/PsdImagePlugin.py +++ b/src/PIL/PsdImagePlugin.py @@ -19,7 +19,6 @@ import io from functools import cached_property -from typing import IO from . import Image, ImageFile, ImagePalette from ._binary import i8 @@ -29,6 +28,10 @@ from ._binary import si32be as si32 from ._util import DeferredError +TYPE_CHECKING = False +if TYPE_CHECKING: + from typing import IO + MODES = { # (photoshop mode, bits) -> (pil mode, required channels) (0, 1): ("1", 1), diff --git a/src/PIL/SgiImagePlugin.py b/src/PIL/SgiImagePlugin.py index 76688ba5724..cd022a0b5d5 100644 --- a/src/PIL/SgiImagePlugin.py +++ b/src/PIL/SgiImagePlugin.py @@ -24,12 +24,15 @@ import os import struct -from typing import IO from . import Image, ImageFile from ._binary import i16be as i16 from ._binary import o8 +TYPE_CHECKING = False +if TYPE_CHECKING: + from typing import IO + def _accept(prefix: bytes) -> bool: return len(prefix) >= 2 and i16(prefix) == 474 diff --git a/src/PIL/SpiderImagePlugin.py b/src/PIL/SpiderImagePlugin.py index b8bf2282d74..be30a7aec20 100644 --- a/src/PIL/SpiderImagePlugin.py +++ b/src/PIL/SpiderImagePlugin.py @@ -37,12 +37,13 @@ import os import struct import sys -from typing import IO, Any from . import Image, ImageFile from ._util import DeferredError TYPE_CHECKING = False +if TYPE_CHECKING: + from typing import IO, Any def isInt(f: Any) -> int: diff --git a/src/PIL/TgaImagePlugin.py b/src/PIL/TgaImagePlugin.py index 8fd63b1df5b..c25e2b9ca08 100644 --- a/src/PIL/TgaImagePlugin.py +++ b/src/PIL/TgaImagePlugin.py @@ -19,7 +19,6 @@ import os import warnings -from typing import IO from . import Image, ImageFile, ImagePalette from ._binary import i16le as i16 @@ -27,6 +26,10 @@ from ._binary import o8 from ._binary import o16le as o16 +TYPE_CHECKING = False +if TYPE_CHECKING: + from typing import IO + # # -------------------------------------------------------------------- # Read RGA file diff --git a/src/PIL/TiffImagePlugin.py b/src/PIL/TiffImagePlugin.py index db37ab7e4c9..9722c6bb72b 100644 --- a/src/PIL/TiffImagePlugin.py +++ b/src/PIL/TiffImagePlugin.py @@ -365,7 +365,7 @@ def __init__( self._denominator = value.denominator else: if TYPE_CHECKING: - self._numerator = cast(IntegralLike, value) + self._numerator = cast("IntegralLike", value) else: self._numerator = value self._denominator = denominator @@ -424,7 +424,7 @@ def __setstate__(self, state: list[float | Fraction | IntegralLike]) -> None: assert isinstance(_val, (float, Fraction)) self._val = _val if TYPE_CHECKING: - self._numerator = cast(IntegralLike, _numerator) + self._numerator = cast("IntegralLike", _numerator) else: self._numerator = _numerator assert isinstance(_denominator, int) @@ -2058,7 +2058,7 @@ def __init__(self, fn: StrOrBytesPath | IO[bytes], new: bool = False) -> None: except OSError: self.f = open(fn, "w+b") else: - self.f = cast(IO[bytes], fn) + self.f = cast("IO[bytes]", fn) self.close_fp = False self.beginning = self.f.tell() self.setup() diff --git a/src/PIL/WalImageFile.py b/src/PIL/WalImageFile.py index 07bbf747155..a97872ff61a 100644 --- a/src/PIL/WalImageFile.py +++ b/src/PIL/WalImageFile.py @@ -25,11 +25,14 @@ from __future__ import annotations -from typing import IO - from . import Image, ImageFile from ._binary import i32le as i32 -from ._typing import StrOrBytesPath + +TYPE_CHECKING = False +if TYPE_CHECKING: + from typing import IO + + from ._typing import StrOrBytesPath class WalImageFile(ImageFile.ImageFile): diff --git a/src/PIL/WmfImagePlugin.py b/src/PIL/WmfImagePlugin.py index f5e244782fc..d30d1a9d339 100644 --- a/src/PIL/WmfImagePlugin.py +++ b/src/PIL/WmfImagePlugin.py @@ -20,13 +20,15 @@ # http://wvware.sourceforge.net/caolan/ora-wmf.html from __future__ import annotations -from typing import IO - from . import Image, ImageFile from ._binary import i16le as word from ._binary import si16le as short from ._binary import si32le as _long +TYPE_CHECKING = False +if TYPE_CHECKING: + from typing import IO + _handler = None diff --git a/src/PIL/XbmImagePlugin.py b/src/PIL/XbmImagePlugin.py index 1e57aa162ea..5e9bfb87c12 100644 --- a/src/PIL/XbmImagePlugin.py +++ b/src/PIL/XbmImagePlugin.py @@ -21,10 +21,13 @@ from __future__ import annotations import re -from typing import IO from . import Image, ImageFile +TYPE_CHECKING = False +if TYPE_CHECKING: + from typing import IO + # XBM header xbm_head = re.compile( rb"\s*#define[ \t]+.*_width[ \t]+(?P[0-9]+)[\r\n]+" diff --git a/src/PIL/_typing.py b/src/PIL/_typing.py index a941f89806f..a72a3a19fc0 100644 --- a/src/PIL/_typing.py +++ b/src/PIL/_typing.py @@ -7,7 +7,7 @@ TYPE_CHECKING = False if TYPE_CHECKING: - from numbers import _IntegralLike as IntegralLike + from numbers import _IntegralLike as IntegralLike # noqa: TC004 try: import numpy.typing as npt diff --git a/src/PIL/features.py b/src/PIL/features.py index ff32c251045..8d72d92cb05 100644 --- a/src/PIL/features.py +++ b/src/PIL/features.py @@ -4,12 +4,14 @@ import os import sys import warnings -from typing import IO import PIL from . import Image +TYPE_CHECKING = False +if TYPE_CHECKING: + from typing import IO modules = { "pil": ("PIL._imaging", "PILLOW_VERSION"), "tkinter": ("PIL._tkinter_finder", "tk_version"),