mirror of
https://github.com/python-pillow/Pillow.git
synced 2024-12-24 17:06:16 +03:00
Added type hints
This commit is contained in:
parent
2bd54260b6
commit
6d78d42769
|
@ -23,7 +23,10 @@ def _get_mem_usage() -> float:
|
|||
|
||||
|
||||
def _test_leak(
|
||||
min_iterations: int, max_iterations: int, fn: Callable[..., None], *args: Any
|
||||
min_iterations: int,
|
||||
max_iterations: int,
|
||||
fn: Callable[..., Image.Image | None],
|
||||
*args: Any,
|
||||
) -> None:
|
||||
mem_limit = None
|
||||
for i in range(max_iterations):
|
||||
|
|
|
@ -17,6 +17,7 @@ def test_ignore_dos_text() -> None:
|
|||
finally:
|
||||
ImageFile.LOAD_TRUNCATED_IMAGES = False
|
||||
|
||||
assert isinstance(im, PngImagePlugin.PngImageFile)
|
||||
for s in im.text.values():
|
||||
assert len(s) < 1024 * 1024, "Text chunk larger than 1M"
|
||||
|
||||
|
@ -32,6 +33,7 @@ def test_dos_text() -> None:
|
|||
assert msg, "Decompressed Data Too Large"
|
||||
return
|
||||
|
||||
assert isinstance(im, PngImagePlugin.PngImageFile)
|
||||
for s in im.text.values():
|
||||
assert len(s) < 1024 * 1024, "Text chunk larger than 1M"
|
||||
|
||||
|
@ -57,6 +59,7 @@ def test_dos_total_memory() -> None:
|
|||
return
|
||||
|
||||
total_len = 0
|
||||
assert isinstance(im2, PngImagePlugin.PngImageFile)
|
||||
for txt in im2.text.values():
|
||||
total_len += len(txt)
|
||||
assert total_len < 64 * 1024 * 1024, "Total text chunks greater than 64M"
|
||||
|
|
|
@ -351,7 +351,7 @@ def is_mingw() -> bool:
|
|||
|
||||
|
||||
class CachedProperty:
|
||||
def __init__(self, func: Callable[[Any], None]) -> None:
|
||||
def __init__(self, func: Callable[[Any], Any]) -> None:
|
||||
self.func = func
|
||||
|
||||
def __get__(self, instance: Any, cls: type[Any] | None = None) -> Any:
|
||||
|
|
|
@ -1,5 +1,7 @@
|
|||
from __future__ import annotations
|
||||
|
||||
from typing import Literal
|
||||
|
||||
import pytest
|
||||
|
||||
from PIL import ContainerIO, Image
|
||||
|
@ -22,14 +24,14 @@ def test_isatty() -> None:
|
|||
|
||||
|
||||
@pytest.mark.parametrize(
|
||||
"mode, expected_value",
|
||||
"mode, expected_position",
|
||||
(
|
||||
(0, 33),
|
||||
(1, 66),
|
||||
(2, 100),
|
||||
),
|
||||
)
|
||||
def test_seek_mode(mode: int, expected_value: int) -> None:
|
||||
def test_seek_mode(mode: Literal[0, 1, 2], expected_position: int) -> None:
|
||||
# Arrange
|
||||
with open(TEST_FILE, "rb") as fh:
|
||||
container = ContainerIO.ContainerIO(fh, 22, 100)
|
||||
|
@ -39,7 +41,7 @@ def test_seek_mode(mode: int, expected_value: int) -> None:
|
|||
container.seek(33, mode)
|
||||
|
||||
# Assert
|
||||
assert container.tell() == expected_value
|
||||
assert container.tell() == expected_position
|
||||
|
||||
|
||||
@pytest.mark.parametrize("bytesmode", (True, False))
|
||||
|
|
|
@ -6,7 +6,7 @@ import warnings
|
|||
from io import BytesIO
|
||||
from pathlib import Path
|
||||
from types import ModuleType
|
||||
from typing import Any
|
||||
from typing import Any, cast
|
||||
|
||||
import pytest
|
||||
|
||||
|
@ -45,14 +45,20 @@ TEST_FILE = "Tests/images/hopper.jpg"
|
|||
|
||||
@skip_unless_feature("jpg")
|
||||
class TestFileJpeg:
|
||||
def roundtrip(self, im: Image.Image, **options: Any) -> Image.Image:
|
||||
def roundtrip_with_bytes(
|
||||
self, im: Image.Image, **options: Any
|
||||
) -> tuple[JpegImagePlugin.JpegImageFile, int]:
|
||||
out = BytesIO()
|
||||
im.save(out, "JPEG", **options)
|
||||
test_bytes = out.tell()
|
||||
out.seek(0)
|
||||
im = Image.open(out)
|
||||
im.bytes = test_bytes # for testing only
|
||||
return im
|
||||
reloaded = cast(JpegImagePlugin.JpegImageFile, Image.open(out))
|
||||
return reloaded, test_bytes
|
||||
|
||||
def roundtrip(
|
||||
self, im: Image.Image, **options: Any
|
||||
) -> JpegImagePlugin.JpegImageFile:
|
||||
return self.roundtrip_with_bytes(im, **options)[0]
|
||||
|
||||
def gen_random_image(self, size: tuple[int, int], mode: str = "RGB") -> Image.Image:
|
||||
"""Generates a very hard to compress file
|
||||
|
@ -246,13 +252,13 @@ class TestFileJpeg:
|
|||
im.save(f, progressive=True, quality=94, exif=b" " * 43668)
|
||||
|
||||
def test_optimize(self) -> None:
|
||||
im1 = self.roundtrip(hopper())
|
||||
im2 = self.roundtrip(hopper(), optimize=0)
|
||||
im3 = self.roundtrip(hopper(), optimize=1)
|
||||
im1, im1_bytes = self.roundtrip_with_bytes(hopper())
|
||||
im2, im2_bytes = self.roundtrip_with_bytes(hopper(), optimize=0)
|
||||
im3, im3_bytes = self.roundtrip_with_bytes(hopper(), optimize=1)
|
||||
assert_image_equal(im1, im2)
|
||||
assert_image_equal(im1, im3)
|
||||
assert im1.bytes >= im2.bytes
|
||||
assert im1.bytes >= im3.bytes
|
||||
assert im1_bytes >= im2_bytes
|
||||
assert im1_bytes >= im3_bytes
|
||||
|
||||
def test_optimize_large_buffer(self, tmp_path: Path) -> None:
|
||||
# https://github.com/python-pillow/Pillow/issues/148
|
||||
|
@ -262,15 +268,15 @@ class TestFileJpeg:
|
|||
im.save(f, format="JPEG", optimize=True)
|
||||
|
||||
def test_progressive(self) -> None:
|
||||
im1 = self.roundtrip(hopper())
|
||||
im1, im1_bytes = self.roundtrip_with_bytes(hopper())
|
||||
im2 = self.roundtrip(hopper(), progressive=False)
|
||||
im3 = self.roundtrip(hopper(), progressive=True)
|
||||
im3, im3_bytes = self.roundtrip_with_bytes(hopper(), progressive=True)
|
||||
assert not im1.info.get("progressive")
|
||||
assert not im2.info.get("progressive")
|
||||
assert im3.info.get("progressive")
|
||||
|
||||
assert_image_equal(im1, im3)
|
||||
assert im1.bytes >= im3.bytes
|
||||
assert im1_bytes >= im3_bytes
|
||||
|
||||
def test_progressive_large_buffer(self, tmp_path: Path) -> None:
|
||||
f = str(tmp_path / "temp.jpg")
|
||||
|
@ -341,6 +347,7 @@ class TestFileJpeg:
|
|||
assert exif.get_ifd(0x8825) == {}
|
||||
|
||||
transposed = ImageOps.exif_transpose(im)
|
||||
assert transposed is not None
|
||||
exif = transposed.getexif()
|
||||
assert exif.get_ifd(0x8825) == {}
|
||||
|
||||
|
@ -419,14 +426,14 @@ class TestFileJpeg:
|
|||
assert im3.info.get("progression")
|
||||
|
||||
def test_quality(self) -> None:
|
||||
im1 = self.roundtrip(hopper())
|
||||
im2 = self.roundtrip(hopper(), quality=50)
|
||||
im1, im1_bytes = self.roundtrip_with_bytes(hopper())
|
||||
im2, im2_bytes = self.roundtrip_with_bytes(hopper(), quality=50)
|
||||
assert_image(im1, im2.mode, im2.size)
|
||||
assert im1.bytes >= im2.bytes
|
||||
assert im1_bytes >= im2_bytes
|
||||
|
||||
im3 = self.roundtrip(hopper(), quality=0)
|
||||
im3, im3_bytes = self.roundtrip_with_bytes(hopper(), quality=0)
|
||||
assert_image(im1, im3.mode, im3.size)
|
||||
assert im2.bytes > im3.bytes
|
||||
assert im2_bytes > im3_bytes
|
||||
|
||||
def test_smooth(self) -> None:
|
||||
im1 = self.roundtrip(hopper())
|
||||
|
|
|
@ -40,10 +40,8 @@ test_card.load()
|
|||
def roundtrip(im: Image.Image, **options: Any) -> Image.Image:
|
||||
out = BytesIO()
|
||||
im.save(out, "JPEG2000", **options)
|
||||
test_bytes = out.tell()
|
||||
out.seek(0)
|
||||
with Image.open(out) as im:
|
||||
im.bytes = test_bytes # for testing only
|
||||
im.load()
|
||||
return im
|
||||
|
||||
|
@ -77,7 +75,9 @@ def test_invalid_file() -> None:
|
|||
def test_bytesio() -> None:
|
||||
with open("Tests/images/test-card-lossless.jp2", "rb") as f:
|
||||
data = BytesIO(f.read())
|
||||
assert_image_similar_tofile(test_card, data, 1.0e-3)
|
||||
with Image.open(data) as im:
|
||||
im.load()
|
||||
assert_image_similar(im, test_card, 1.0e-3)
|
||||
|
||||
|
||||
# These two test pre-written JPEG 2000 files that were not written with
|
||||
|
@ -340,6 +340,7 @@ def test_parser_feed() -> None:
|
|||
p.feed(data)
|
||||
|
||||
# Assert
|
||||
assert p.image is not None
|
||||
assert p.image.size == (640, 480)
|
||||
|
||||
|
||||
|
|
|
@ -27,7 +27,7 @@ from .helper import (
|
|||
|
||||
@skip_unless_feature("libtiff")
|
||||
class LibTiffTestCase:
|
||||
def _assert_noerr(self, tmp_path: Path, im: Image.Image) -> None:
|
||||
def _assert_noerr(self, tmp_path: Path, im: TiffImagePlugin.TiffImageFile) -> None:
|
||||
"""Helper tests that assert basic sanity about the g4 tiff reading"""
|
||||
# 1 bit
|
||||
assert im.mode == "1"
|
||||
|
@ -524,7 +524,8 @@ class TestFileLibTiff(LibTiffTestCase):
|
|||
im.save(out, compression=compression)
|
||||
|
||||
def test_fp_leak(self) -> None:
|
||||
im = Image.open("Tests/images/hopper_g4_500.tif")
|
||||
im: Image.Image | None = Image.open("Tests/images/hopper_g4_500.tif")
|
||||
assert im is not None
|
||||
fn = im.fp.fileno()
|
||||
|
||||
os.fstat(fn)
|
||||
|
@ -716,6 +717,7 @@ class TestFileLibTiff(LibTiffTestCase):
|
|||
f.write(src.read())
|
||||
|
||||
im = Image.open(tmpfile)
|
||||
assert isinstance(im, TiffImagePlugin.TiffImageFile)
|
||||
im.n_frames
|
||||
im.close()
|
||||
# Should not raise PermissionError.
|
||||
|
@ -1097,6 +1099,7 @@ class TestFileLibTiff(LibTiffTestCase):
|
|||
|
||||
with Image.open(out) as im:
|
||||
# Assert that there are multiple strips
|
||||
assert isinstance(im, TiffImagePlugin.TiffImageFile)
|
||||
assert len(im.tag_v2[STRIPOFFSETS]) > 1
|
||||
|
||||
@pytest.mark.parametrize("argument", (True, False))
|
||||
|
@ -1113,6 +1116,7 @@ class TestFileLibTiff(LibTiffTestCase):
|
|||
im.save(out, **arguments)
|
||||
|
||||
with Image.open(out) as im:
|
||||
assert isinstance(im, TiffImagePlugin.TiffImageFile)
|
||||
assert len(im.tag_v2[STRIPOFFSETS]) == 1
|
||||
finally:
|
||||
TiffImagePlugin.STRIP_SIZE = 65536
|
||||
|
|
|
@ -2,11 +2,11 @@ from __future__ import annotations
|
|||
|
||||
import warnings
|
||||
from io import BytesIO
|
||||
from typing import Any
|
||||
from typing import Any, cast
|
||||
|
||||
import pytest
|
||||
|
||||
from PIL import Image
|
||||
from PIL import Image, MpoImagePlugin
|
||||
|
||||
from .helper import (
|
||||
assert_image_equal,
|
||||
|
@ -20,14 +20,11 @@ test_files = ["Tests/images/sugarshack.mpo", "Tests/images/frozenpond.mpo"]
|
|||
pytestmark = skip_unless_feature("jpg")
|
||||
|
||||
|
||||
def roundtrip(im: Image.Image, **options: Any) -> Image.Image:
|
||||
def roundtrip(im: Image.Image, **options: Any) -> MpoImagePlugin.MpoImageFile:
|
||||
out = BytesIO()
|
||||
im.save(out, "MPO", **options)
|
||||
test_bytes = out.tell()
|
||||
out.seek(0)
|
||||
im = Image.open(out)
|
||||
im.bytes = test_bytes # for testing only
|
||||
return im
|
||||
return cast(MpoImagePlugin.MpoImageFile, Image.open(out))
|
||||
|
||||
|
||||
@pytest.mark.parametrize("test_file", test_files)
|
||||
|
|
|
@ -7,7 +7,7 @@ import zlib
|
|||
from io import BytesIO
|
||||
from pathlib import Path
|
||||
from types import ModuleType
|
||||
from typing import Any
|
||||
from typing import Any, cast
|
||||
|
||||
import pytest
|
||||
|
||||
|
@ -59,11 +59,11 @@ def load(data: bytes) -> Image.Image:
|
|||
return Image.open(BytesIO(data))
|
||||
|
||||
|
||||
def roundtrip(im: Image.Image, **options: Any) -> Image.Image:
|
||||
def roundtrip(im: Image.Image, **options: Any) -> PngImagePlugin.PngImageFile:
|
||||
out = BytesIO()
|
||||
im.save(out, "PNG", **options)
|
||||
out.seek(0)
|
||||
return Image.open(out)
|
||||
return cast(PngImagePlugin.PngImageFile, Image.open(out))
|
||||
|
||||
|
||||
@skip_unless_feature("zlib")
|
||||
|
|
|
@ -9,7 +9,7 @@ import pytest
|
|||
|
||||
from PIL import Image, ImageSequence, SpiderImagePlugin
|
||||
|
||||
from .helper import assert_image_equal_tofile, hopper, is_pypy
|
||||
from .helper import assert_image_equal, hopper, is_pypy
|
||||
|
||||
TEST_FILE = "Tests/images/hopper.spider"
|
||||
|
||||
|
@ -152,7 +152,7 @@ def test_nonstack_dos() -> None:
|
|||
assert i <= 1, "Non-stack DOS file test failed"
|
||||
|
||||
|
||||
# for issue #4093
|
||||
# for issue #4093s
|
||||
def test_odd_size() -> None:
|
||||
data = BytesIO()
|
||||
width = 100
|
||||
|
@ -160,4 +160,5 @@ def test_odd_size() -> None:
|
|||
im.save(data, format="SPIDER")
|
||||
|
||||
data.seek(0)
|
||||
assert_image_equal_tofile(im, data)
|
||||
with Image.open(data) as im2:
|
||||
assert_image_equal(im, im2)
|
||||
|
|
|
@ -623,6 +623,7 @@ class TestFileTiff:
|
|||
im.save(outfile, tiffinfo={278: 256})
|
||||
|
||||
with Image.open(outfile) as im:
|
||||
assert isinstance(im, TiffImagePlugin.TiffImageFile)
|
||||
assert im.tag_v2[278] == 256
|
||||
|
||||
def test_strip_raw(self) -> None:
|
||||
|
|
|
@ -138,13 +138,13 @@ class TestImage:
|
|||
assert im.height == 2
|
||||
|
||||
with pytest.raises(AttributeError):
|
||||
im.size = (3, 4)
|
||||
im.size = (3, 4) # type: ignore[misc]
|
||||
|
||||
def test_set_mode(self) -> None:
|
||||
im = Image.new("RGB", (1, 1))
|
||||
|
||||
with pytest.raises(AttributeError):
|
||||
im.mode = "P"
|
||||
im.mode = "P" # type: ignore[misc]
|
||||
|
||||
def test_invalid_image(self) -> None:
|
||||
im = io.BytesIO(b"")
|
||||
|
|
|
@ -14,6 +14,7 @@ from .helper import assert_image_equal, hopper, is_win32
|
|||
|
||||
# CFFI imports pycparser which doesn't support PYTHONOPTIMIZE=2
|
||||
# https://github.com/eliben/pycparser/pull/198#issuecomment-317001670
|
||||
cffi: ModuleType | None
|
||||
if os.environ.get("PYTHONOPTIMIZE") == "2":
|
||||
cffi = None
|
||||
else:
|
||||
|
|
|
@ -1,7 +1,6 @@
|
|||
from __future__ import annotations
|
||||
|
||||
import warnings
|
||||
from typing import Generator
|
||||
|
||||
import pytest
|
||||
|
||||
|
@ -17,17 +16,14 @@ pytestmark = pytest.mark.skipif(
|
|||
not ImageQt.qt_is_installed, reason="Qt bindings are not installed"
|
||||
)
|
||||
|
||||
|
||||
@pytest.fixture
|
||||
def test_images() -> Generator[Image.Image, None, None]:
|
||||
ims = [
|
||||
ims = [
|
||||
hopper(),
|
||||
Image.open("Tests/images/transparent.png"),
|
||||
Image.open("Tests/images/7x13.png"),
|
||||
]
|
||||
try:
|
||||
yield ims
|
||||
finally:
|
||||
]
|
||||
|
||||
|
||||
def teardown_module() -> None:
|
||||
for im in ims:
|
||||
im.close()
|
||||
|
||||
|
@ -44,26 +40,26 @@ def roundtrip(expected: Image.Image) -> None:
|
|||
assert_image_equal(result, expected.convert("RGB"))
|
||||
|
||||
|
||||
def test_sanity_1(test_images: Generator[Image.Image, None, None]) -> None:
|
||||
for im in test_images:
|
||||
def test_sanity_1() -> None:
|
||||
for im in ims:
|
||||
roundtrip(im.convert("1"))
|
||||
|
||||
|
||||
def test_sanity_rgb(test_images: Generator[Image.Image, None, None]) -> None:
|
||||
for im in test_images:
|
||||
def test_sanity_rgb() -> None:
|
||||
for im in ims:
|
||||
roundtrip(im.convert("RGB"))
|
||||
|
||||
|
||||
def test_sanity_rgba(test_images: Generator[Image.Image, None, None]) -> None:
|
||||
for im in test_images:
|
||||
def test_sanity_rgba() -> None:
|
||||
for im in ims:
|
||||
roundtrip(im.convert("RGBA"))
|
||||
|
||||
|
||||
def test_sanity_l(test_images: Generator[Image.Image, None, None]) -> None:
|
||||
for im in test_images:
|
||||
def test_sanity_l() -> None:
|
||||
for im in ims:
|
||||
roundtrip(im.convert("L"))
|
||||
|
||||
|
||||
def test_sanity_p(test_images: Generator[Image.Image, None, None]) -> None:
|
||||
for im in test_images:
|
||||
def test_sanity_p() -> None:
|
||||
for im in ims:
|
||||
roundtrip(im.convert("P"))
|
||||
|
|
|
@ -32,7 +32,7 @@ class TestImagingPaste:
|
|||
def assert_9points_paste(
|
||||
self,
|
||||
im: Image.Image,
|
||||
im2: Image.Image,
|
||||
im2: Image.Image | str | tuple[int, ...],
|
||||
mask: Image.Image,
|
||||
expected: list[tuple[int, int, int, int]],
|
||||
) -> None:
|
||||
|
|
|
@ -237,7 +237,7 @@ class TestCoreResampleConsistency:
|
|||
im = Image.new(mode, (512, 9), fill)
|
||||
return im.resize((9, 512), Image.Resampling.LANCZOS), im.load()[0, 0]
|
||||
|
||||
def run_case(self, case: tuple[Image.Image, Image.Image]) -> None:
|
||||
def run_case(self, case: tuple[Image.Image, int | tuple[int, ...]]) -> None:
|
||||
channel, color = case
|
||||
px = channel.load()
|
||||
for x in range(channel.size[0]):
|
||||
|
|
|
@ -154,7 +154,7 @@ class TestImagingCoreResize:
|
|||
|
||||
def test_unknown_filter(self) -> None:
|
||||
with pytest.raises(ValueError):
|
||||
self.resize(hopper(), (10, 10), 9)
|
||||
self.resize(hopper(), (10, 10), 9) # type: ignore[arg-type]
|
||||
|
||||
def test_cross_platform(self, tmp_path: Path) -> None:
|
||||
# This test is intended for only check for consistent behaviour across
|
||||
|
|
|
@ -73,15 +73,16 @@ def test_lut(op: str) -> None:
|
|||
|
||||
|
||||
def test_no_operator_loaded() -> None:
|
||||
im = Image.new("L", (1, 1))
|
||||
mop = ImageMorph.MorphOp()
|
||||
with pytest.raises(Exception) as e:
|
||||
mop.apply(None)
|
||||
mop.apply(im)
|
||||
assert str(e.value) == "No operator loaded"
|
||||
with pytest.raises(Exception) as e:
|
||||
mop.match(None)
|
||||
mop.match(im)
|
||||
assert str(e.value) == "No operator loaded"
|
||||
with pytest.raises(Exception) as e:
|
||||
mop.save_lut(None)
|
||||
mop.save_lut("")
|
||||
assert str(e.value) == "No operator loaded"
|
||||
|
||||
|
||||
|
|
|
@ -13,8 +13,12 @@ from .helper import (
|
|||
)
|
||||
|
||||
|
||||
class Deformer:
|
||||
def getmesh(self, im: Image.Image) -> list[tuple[tuple[int, ...], tuple[int, ...]]]:
|
||||
class Deformer(ImageOps.SupportsGetMesh):
|
||||
def getmesh(
|
||||
self, im: Image.Image
|
||||
) -> list[
|
||||
tuple[tuple[int, int, int, int], tuple[int, int, int, int, int, int, int, int]]
|
||||
]:
|
||||
x, y = im.size
|
||||
return [((0, 0, x, y), (0, 0, x, 0, x, y, y, 0))]
|
||||
|
||||
|
@ -376,6 +380,7 @@ def test_exif_transpose() -> None:
|
|||
else:
|
||||
original_exif = im.info["exif"]
|
||||
transposed_im = ImageOps.exif_transpose(im)
|
||||
assert transposed_im is not None
|
||||
assert_image_similar(base_im, transposed_im, 17)
|
||||
if orientation_im is base_im:
|
||||
assert "exif" not in im.info
|
||||
|
@ -387,6 +392,7 @@ def test_exif_transpose() -> None:
|
|||
|
||||
# Repeat the operation to test that it does not keep transposing
|
||||
transposed_im2 = ImageOps.exif_transpose(transposed_im)
|
||||
assert transposed_im2 is not None
|
||||
assert_image_equal(transposed_im2, transposed_im)
|
||||
|
||||
check(base_im)
|
||||
|
@ -402,6 +408,7 @@ def test_exif_transpose() -> None:
|
|||
assert im.getexif()[0x0112] == 3
|
||||
|
||||
transposed_im = ImageOps.exif_transpose(im)
|
||||
assert transposed_im is not None
|
||||
assert 0x0112 not in transposed_im.getexif()
|
||||
|
||||
transposed_im._reload_exif()
|
||||
|
@ -414,12 +421,14 @@ def test_exif_transpose() -> None:
|
|||
assert im.getexif()[0x0112] == 3
|
||||
|
||||
transposed_im = ImageOps.exif_transpose(im)
|
||||
assert transposed_im is not None
|
||||
assert 0x0112 not in transposed_im.getexif()
|
||||
|
||||
# Orientation set directly on Image.Exif
|
||||
im = hopper()
|
||||
im.getexif()[0x0112] = 3
|
||||
transposed_im = ImageOps.exif_transpose(im)
|
||||
assert transposed_im is not None
|
||||
assert 0x0112 not in transposed_im.getexif()
|
||||
|
||||
|
||||
|
@ -499,7 +508,7 @@ def test_autocontrast_mask_real_input() -> None:
|
|||
|
||||
|
||||
def test_autocontrast_preserve_tone() -> None:
|
||||
def autocontrast(mode: str, preserve_tone: bool) -> Image.Image:
|
||||
def autocontrast(mode: str, preserve_tone: bool) -> list[int]:
|
||||
im = hopper(mode)
|
||||
return ImageOps.autocontrast(im, preserve_tone=preserve_tone).histogram()
|
||||
|
||||
|
|
|
@ -28,8 +28,8 @@ def test_filter_api(test_images: dict[str, Image.Image]) -> None:
|
|||
assert i.mode == "RGB"
|
||||
assert i.size == (128, 128)
|
||||
|
||||
test_filter = ImageFilter.UnsharpMask(2.0, 125, 8)
|
||||
i = im.filter(test_filter)
|
||||
test_filter2 = ImageFilter.UnsharpMask(2.0, 125, 8)
|
||||
i = im.filter(test_filter2)
|
||||
assert i.mode == "RGB"
|
||||
assert i.size == (128, 128)
|
||||
|
||||
|
|
|
@ -26,7 +26,7 @@ def test_sanity(tmp_path: Path) -> None:
|
|||
assert index == 1
|
||||
|
||||
with pytest.raises(AttributeError):
|
||||
ImageSequence.Iterator(0)
|
||||
ImageSequence.Iterator(0) # type: ignore[arg-type]
|
||||
|
||||
|
||||
def test_iterator() -> None:
|
||||
|
@ -72,6 +72,7 @@ def test_consecutive() -> None:
|
|||
for frame in ImageSequence.Iterator(im):
|
||||
if first_frame is None:
|
||||
first_frame = frame.copy()
|
||||
assert first_frame is not None
|
||||
for frame in ImageSequence.Iterator(im):
|
||||
assert_image_equal(frame, first_frame)
|
||||
break
|
||||
|
|
|
@ -68,10 +68,11 @@ def test_show_without_viewers() -> None:
|
|||
def test_viewer() -> None:
|
||||
viewer = ImageShow.Viewer()
|
||||
|
||||
assert viewer.get_format(None) is None
|
||||
im = Image.new("L", (1, 1))
|
||||
assert viewer.get_format(im) is None
|
||||
|
||||
with pytest.raises(NotImplementedError):
|
||||
viewer.get_command(None)
|
||||
viewer.get_command("")
|
||||
|
||||
|
||||
@pytest.mark.parametrize("viewer", ImageShow._viewers)
|
||||
|
|
|
@ -78,7 +78,7 @@ def test_basic(tmp_path: Path, mode: str) -> None:
|
|||
|
||||
|
||||
def test_tobytes() -> None:
|
||||
def tobytes(mode: str) -> Image.Image:
|
||||
def tobytes(mode: str) -> bytes:
|
||||
return Image.new(mode, (1, 1), 1).tobytes()
|
||||
|
||||
order = 1 if Image._ENDIAN == "<" else -1
|
||||
|
|
|
@ -47,9 +47,8 @@ def test_tiff_crashes(test_file: str) -> None:
|
|||
with Image.open(test_file) as im:
|
||||
im.load()
|
||||
except FileNotFoundError:
|
||||
if not on_ci():
|
||||
pytest.skip("test image not found")
|
||||
return
|
||||
if on_ci():
|
||||
raise
|
||||
pytest.skip("test image not found")
|
||||
except OSError:
|
||||
pass
|
||||
|
|
|
@ -38,7 +38,7 @@ from ._deprecate import deprecate
|
|||
split = re.compile(r"^%%([^:]*):[ \t]*(.*)[ \t]*$")
|
||||
field = re.compile(r"^%[%!\w]([^:]*)[ \t]*$")
|
||||
|
||||
gs_binary = None
|
||||
gs_binary: str | bool | None = None
|
||||
gs_windows_binary = None
|
||||
|
||||
|
||||
|
|
|
@ -75,7 +75,7 @@ class DecompressionBombError(Exception):
|
|||
|
||||
|
||||
# Limit to around a quarter gigabyte for a 24-bit (3 bpp) image
|
||||
MAX_IMAGE_PIXELS = int(1024 * 1024 * 1024 // 4 // 3)
|
||||
MAX_IMAGE_PIXELS: int | None = int(1024 * 1024 * 1024 // 4 // 3)
|
||||
|
||||
|
||||
try:
|
||||
|
|
|
@ -384,7 +384,7 @@ class Parser:
|
|||
"""
|
||||
|
||||
incremental = None
|
||||
image = None
|
||||
image: Image.Image | None = None
|
||||
data = None
|
||||
decoder = None
|
||||
offset = 0
|
||||
|
|
Loading…
Reference in New Issue
Block a user