Skip to content

Commit b935e29

Browse files
committed
Added type hints
1 parent 334c26d commit b935e29

24 files changed

+90
-66
lines changed

Tests/check_imaging_leaks.py

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -23,7 +23,10 @@ def _get_mem_usage() -> float:
2323

2424

2525
def _test_leak(
26-
min_iterations: int, max_iterations: int, fn: Callable[..., None], *args: Any
26+
min_iterations: int,
27+
max_iterations: int,
28+
fn: Callable[..., Image.Image | None],
29+
*args: Any,
2730
) -> None:
2831
mem_limit = None
2932
for i in range(max_iterations):

Tests/check_png_dos.py

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,7 @@ def test_ignore_dos_text() -> None:
1717
finally:
1818
ImageFile.LOAD_TRUNCATED_IMAGES = False
1919

20+
assert isinstance(im, PngImagePlugin.PngImageFile)
2021
for s in im.text.values():
2122
assert len(s) < 1024 * 1024, "Text chunk larger than 1M"
2223

@@ -32,6 +33,7 @@ def test_dos_text() -> None:
3233
assert msg, "Decompressed Data Too Large"
3334
return
3435

36+
assert isinstance(im, PngImagePlugin.PngImageFile)
3537
for s in im.text.values():
3638
assert len(s) < 1024 * 1024, "Text chunk larger than 1M"
3739

@@ -57,6 +59,7 @@ def test_dos_total_memory() -> None:
5759
return
5860

5961
total_len = 0
62+
assert isinstance(im2, PngImagePlugin.PngImageFile)
6063
for txt in im2.text.values():
6164
total_len += len(txt)
6265
assert total_len < 64 * 1024 * 1024, "Total text chunks greater than 64M"

Tests/helper.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -351,7 +351,7 @@ def is_mingw() -> bool:
351351

352352

353353
class CachedProperty:
354-
def __init__(self, func: Callable[[Any], None]) -> None:
354+
def __init__(self, func: Callable[[Any], Any]) -> None:
355355
self.func = func
356356

357357
def __get__(self, instance: Any, cls: type[Any] | None = None) -> Any:

Tests/test_file_container.py

Lines changed: 6 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -23,41 +23,38 @@ def test_isatty() -> None:
2323

2424
def test_seek_mode_0() -> None:
2525
# Arrange
26-
mode = 0
2726
with open(TEST_FILE, "rb") as fh:
2827
container = ContainerIO.ContainerIO(fh, 22, 100)
2928

3029
# Act
31-
container.seek(33, mode)
32-
container.seek(33, mode)
30+
container.seek(33, 0)
31+
container.seek(33, 0)
3332

3433
# Assert
3534
assert container.tell() == 33
3635

3736

3837
def test_seek_mode_1() -> None:
3938
# Arrange
40-
mode = 1
4139
with open(TEST_FILE, "rb") as fh:
4240
container = ContainerIO.ContainerIO(fh, 22, 100)
4341

4442
# Act
45-
container.seek(33, mode)
46-
container.seek(33, mode)
43+
container.seek(33, 1)
44+
container.seek(33, 1)
4745

4846
# Assert
4947
assert container.tell() == 66
5048

5149

5250
def test_seek_mode_2() -> None:
5351
# Arrange
54-
mode = 2
5552
with open(TEST_FILE, "rb") as fh:
5653
container = ContainerIO.ContainerIO(fh, 22, 100)
5754

5855
# Act
59-
container.seek(33, mode)
60-
container.seek(33, mode)
56+
container.seek(33, 2)
57+
container.seek(33, 2)
6158

6259
# Assert
6360
assert container.tell() == 100

Tests/test_file_jpeg.py

Lines changed: 25 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@
66
from io import BytesIO
77
from pathlib import Path
88
from types import ModuleType
9-
from typing import Any
9+
from typing import Any, cast
1010

1111
import pytest
1212

@@ -45,14 +45,20 @@
4545

4646
@skip_unless_feature("jpg")
4747
class TestFileJpeg:
48-
def roundtrip(self, im: Image.Image, **options: Any) -> Image.Image:
48+
def roundtrip_with_bytes(
49+
self, im: Image.Image, **options: Any
50+
) -> tuple[JpegImagePlugin.JpegImageFile, int]:
4951
out = BytesIO()
5052
im.save(out, "JPEG", **options)
5153
test_bytes = out.tell()
5254
out.seek(0)
53-
im = Image.open(out)
54-
im.bytes = test_bytes # for testing only
55-
return im
55+
reloaded = cast(JpegImagePlugin.JpegImageFile, Image.open(out))
56+
return reloaded, test_bytes
57+
58+
def roundtrip(
59+
self, im: Image.Image, **options: Any
60+
) -> JpegImagePlugin.JpegImageFile:
61+
return self.roundtrip_with_bytes(im, **options)[0]
5662

5763
def gen_random_image(self, size: tuple[int, int], mode: str = "RGB") -> Image.Image:
5864
"""Generates a very hard to compress file
@@ -246,13 +252,13 @@ def test_large_icc_meta(self, tmp_path: Path) -> None:
246252
im.save(f, progressive=True, quality=94, exif=b" " * 43668)
247253

248254
def test_optimize(self) -> None:
249-
im1 = self.roundtrip(hopper())
250-
im2 = self.roundtrip(hopper(), optimize=0)
251-
im3 = self.roundtrip(hopper(), optimize=1)
255+
im1, im1_bytes = self.roundtrip_with_bytes(hopper())
256+
im2, im2_bytes = self.roundtrip_with_bytes(hopper(), optimize=0)
257+
im3, im3_bytes = self.roundtrip_with_bytes(hopper(), optimize=1)
252258
assert_image_equal(im1, im2)
253259
assert_image_equal(im1, im3)
254-
assert im1.bytes >= im2.bytes
255-
assert im1.bytes >= im3.bytes
260+
assert im1_bytes >= im2_bytes
261+
assert im1_bytes >= im3_bytes
256262

257263
def test_optimize_large_buffer(self, tmp_path: Path) -> None:
258264
# https://github.com/python-pillow/Pillow/issues/148
@@ -262,15 +268,15 @@ def test_optimize_large_buffer(self, tmp_path: Path) -> None:
262268
im.save(f, format="JPEG", optimize=True)
263269

264270
def test_progressive(self) -> None:
265-
im1 = self.roundtrip(hopper())
271+
im1, im1_bytes = self.roundtrip_with_bytes(hopper())
266272
im2 = self.roundtrip(hopper(), progressive=False)
267-
im3 = self.roundtrip(hopper(), progressive=True)
273+
im3, im3_bytes = self.roundtrip_with_bytes(hopper(), progressive=True)
268274
assert not im1.info.get("progressive")
269275
assert not im2.info.get("progressive")
270276
assert im3.info.get("progressive")
271277

272278
assert_image_equal(im1, im3)
273-
assert im1.bytes >= im3.bytes
279+
assert im1_bytes >= im3_bytes
274280

275281
def test_progressive_large_buffer(self, tmp_path: Path) -> None:
276282
f = str(tmp_path / "temp.jpg")
@@ -341,6 +347,7 @@ def test_empty_exif_gps(self) -> None:
341347
assert exif.get_ifd(0x8825) == {}
342348

343349
transposed = ImageOps.exif_transpose(im)
350+
assert transposed is not None
344351
exif = transposed.getexif()
345352
assert exif.get_ifd(0x8825) == {}
346353

@@ -419,14 +426,14 @@ def test_progressive_compat(self) -> None:
419426
assert im3.info.get("progression")
420427

421428
def test_quality(self) -> None:
422-
im1 = self.roundtrip(hopper())
423-
im2 = self.roundtrip(hopper(), quality=50)
429+
im1, im1_bytes = self.roundtrip_with_bytes(hopper())
430+
im2, im2_bytes = self.roundtrip_with_bytes(hopper(), quality=50)
424431
assert_image(im1, im2.mode, im2.size)
425-
assert im1.bytes >= im2.bytes
432+
assert im1_bytes >= im2_bytes
426433

427-
im3 = self.roundtrip(hopper(), quality=0)
434+
im3, im3_bytes = self.roundtrip_with_bytes(hopper(), quality=0)
428435
assert_image(im1, im3.mode, im3.size)
429-
assert im2.bytes > im3.bytes
436+
assert im2_bytes > im3_bytes
430437

431438
def test_smooth(self) -> None:
432439
im1 = self.roundtrip(hopper())

Tests/test_file_jpeg2k.py

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -40,10 +40,8 @@
4040
def roundtrip(im: Image.Image, **options: Any) -> Image.Image:
4141
out = BytesIO()
4242
im.save(out, "JPEG2000", **options)
43-
test_bytes = out.tell()
4443
out.seek(0)
4544
with Image.open(out) as im:
46-
im.bytes = test_bytes # for testing only
4745
im.load()
4846
return im
4947

@@ -340,6 +338,7 @@ def test_parser_feed() -> None:
340338
p.feed(data)
341339

342340
# Assert
341+
assert p.image is not None
343342
assert p.image.size == (640, 480)
344343

345344

Tests/test_file_libtiff.py

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -27,7 +27,7 @@
2727

2828
@skip_unless_feature("libtiff")
2929
class LibTiffTestCase:
30-
def _assert_noerr(self, tmp_path: Path, im: Image.Image) -> None:
30+
def _assert_noerr(self, tmp_path: Path, im: TiffImagePlugin.TiffImageFile) -> None:
3131
"""Helper tests that assert basic sanity about the g4 tiff reading"""
3232
# 1 bit
3333
assert im.mode == "1"
@@ -524,7 +524,8 @@ def test_bw_compression_w_rgb(self, compression: str, tmp_path: Path) -> None:
524524
im.save(out, compression=compression)
525525

526526
def test_fp_leak(self) -> None:
527-
im = Image.open("Tests/images/hopper_g4_500.tif")
527+
im: Image.Image | None = Image.open("Tests/images/hopper_g4_500.tif")
528+
assert im is not None
528529
fn = im.fp.fileno()
529530

530531
os.fstat(fn)
@@ -716,6 +717,7 @@ def test_fd_duplication(self, tmp_path: Path) -> None:
716717
f.write(src.read())
717718

718719
im = Image.open(tmpfile)
720+
assert isinstance(im, TiffImagePlugin.TiffImageFile)
719721
im.n_frames
720722
im.close()
721723
# Should not raise PermissionError.
@@ -1097,6 +1099,7 @@ def test_save_multistrip(self, compression: str, tmp_path: Path) -> None:
10971099

10981100
with Image.open(out) as im:
10991101
# Assert that there are multiple strips
1102+
assert isinstance(im, TiffImagePlugin.TiffImageFile)
11001103
assert len(im.tag_v2[STRIPOFFSETS]) > 1
11011104

11021105
@pytest.mark.parametrize("argument", (True, False))
@@ -1113,6 +1116,7 @@ def test_save_single_strip(self, argument: bool, tmp_path: Path) -> None:
11131116
im.save(out, **arguments)
11141117

11151118
with Image.open(out) as im:
1119+
assert isinstance(im, TiffImagePlugin.TiffImageFile)
11161120
assert len(im.tag_v2[STRIPOFFSETS]) == 1
11171121
finally:
11181122
TiffImagePlugin.STRIP_SIZE = 65536

Tests/test_file_mpo.py

Lines changed: 4 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -2,11 +2,11 @@
22

33
import warnings
44
from io import BytesIO
5-
from typing import Any
5+
from typing import Any, cast
66

77
import pytest
88

9-
from PIL import Image
9+
from PIL import Image, MpoImagePlugin
1010

1111
from .helper import (
1212
assert_image_equal,
@@ -20,14 +20,11 @@
2020
pytestmark = skip_unless_feature("jpg")
2121

2222

23-
def roundtrip(im: Image.Image, **options: Any) -> Image.Image:
23+
def roundtrip(im: Image.Image, **options: Any) -> MpoImagePlugin.MpoImageFile:
2424
out = BytesIO()
2525
im.save(out, "MPO", **options)
26-
test_bytes = out.tell()
2726
out.seek(0)
28-
im = Image.open(out)
29-
im.bytes = test_bytes # for testing only
30-
return im
27+
return cast(MpoImagePlugin.MpoImageFile, Image.open(out))
3128

3229

3330
@pytest.mark.parametrize("test_file", test_files)

Tests/test_file_png.py

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@
77
from io import BytesIO
88
from pathlib import Path
99
from types import ModuleType
10-
from typing import Any
10+
from typing import Any, cast
1111

1212
import pytest
1313

@@ -59,11 +59,11 @@ def load(data: bytes) -> Image.Image:
5959
return Image.open(BytesIO(data))
6060

6161

62-
def roundtrip(im: Image.Image, **options: Any) -> Image.Image:
62+
def roundtrip(im: Image.Image, **options: Any) -> PngImagePlugin.PngImageFile:
6363
out = BytesIO()
6464
im.save(out, "PNG", **options)
6565
out.seek(0)
66-
return Image.open(out)
66+
return cast(PngImagePlugin.PngImageFile, Image.open(out))
6767

6868

6969
@skip_unless_feature("zlib")

Tests/test_file_tiff.py

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -623,6 +623,7 @@ def test_rowsperstrip(self, tmp_path: Path) -> None:
623623
im.save(outfile, tiffinfo={278: 256})
624624

625625
with Image.open(outfile) as im:
626+
assert isinstance(im, TiffImagePlugin.TiffImageFile)
626627
assert im.tag_v2[278] == 256
627628

628629
def test_strip_raw(self) -> None:

0 commit comments

Comments
 (0)