Skip to content

Commit b9d3c21

Browse files
authored
Merge pull request #7816 from radarhere/type_hints
Added type hints to additional tests
2 parents 380bc17 + 7200f47 commit b9d3c21

19 files changed

+63
-46
lines changed

Tests/test_deprecate.py

+3-3
Original file line numberDiff line numberDiff line change
@@ -20,7 +20,7 @@
2020
),
2121
],
2222
)
23-
def test_version(version, expected) -> None:
23+
def test_version(version: int | None, expected: str) -> None:
2424
with pytest.warns(DeprecationWarning, match=expected):
2525
_deprecate.deprecate("Old thing", version, "new thing")
2626

@@ -46,7 +46,7 @@ def test_unknown_version() -> None:
4646
),
4747
],
4848
)
49-
def test_old_version(deprecated, plural, expected) -> None:
49+
def test_old_version(deprecated: str, plural: bool, expected: str) -> None:
5050
expected = r""
5151
with pytest.raises(RuntimeError, match=expected):
5252
_deprecate.deprecate(deprecated, 1, plural=plural)
@@ -76,7 +76,7 @@ def test_replacement_and_action() -> None:
7676
"Upgrade to new thing.",
7777
],
7878
)
79-
def test_action(action) -> None:
79+
def test_action(action: str) -> None:
8080
expected = (
8181
r"Old thing is deprecated and will be removed in Pillow 11 \(2024-10-15\)\. "
8282
r"Upgrade to new thing\."

Tests/test_file_ico.py

+1-1
Original file line numberDiff line numberDiff line change
@@ -135,7 +135,7 @@ def test_different_bit_depths(tmp_path: Path) -> None:
135135

136136

137137
@pytest.mark.parametrize("mode", ("1", "L", "P", "RGB", "RGBA"))
138-
def test_save_to_bytes_bmp(mode) -> None:
138+
def test_save_to_bytes_bmp(mode: str) -> None:
139139
output = io.BytesIO()
140140
im = hopper(mode)
141141
im.save(output, "ico", bitmap_format="bmp", sizes=[(32, 32), (64, 64)])

Tests/test_file_iptc.py

+1-1
Original file line numberDiff line numberDiff line change
@@ -98,7 +98,7 @@ def test_i() -> None:
9898
assert ret == 97
9999

100100

101-
def test_dump(monkeypatch) -> None:
101+
def test_dump(monkeypatch: pytest.MonkeyPatch) -> None:
102102
# Arrange
103103
c = b"abc"
104104
# Temporarily redirect stdout

Tests/test_file_msp.py

+1-1
Original file line numberDiff line numberDiff line change
@@ -52,7 +52,7 @@ def test_open_windows_v1() -> None:
5252
assert isinstance(im, MspImagePlugin.MspImageFile)
5353

5454

55-
def _assert_file_image_equal(source_path, target_path) -> None:
55+
def _assert_file_image_equal(source_path: str, target_path: str) -> None:
5656
with Image.open(source_path) as im:
5757
assert_image_equal_tofile(im, target_path)
5858

Tests/test_file_png.py

+2
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@
66
import zlib
77
from io import BytesIO
88
from pathlib import Path
9+
from types import ModuleType
910
from typing import Any
1011

1112
import pytest
@@ -23,6 +24,7 @@
2324
skip_unless_feature,
2425
)
2526

27+
ElementTree: ModuleType | None
2628
try:
2729
from defusedxml import ElementTree
2830
except ImportError:

Tests/test_file_psd.py

+1-1
Original file line numberDiff line numberDiff line change
@@ -157,7 +157,7 @@ def test_combined_larger_than_size() -> None:
157157
("Tests/images/timeout-dedc7a4ebd856d79b4359bbcc79e8ef231ce38f6.psd", OSError),
158158
],
159159
)
160-
def test_crashes(test_file, raises) -> None:
160+
def test_crashes(test_file: str, raises) -> None:
161161
with open(test_file, "rb") as f:
162162
with pytest.raises(raises):
163163
with Image.open(f):

Tests/test_file_tga.py

+2-2
Original file line numberDiff line numberDiff line change
@@ -22,8 +22,8 @@
2222

2323

2424
@pytest.mark.parametrize("mode", _MODES)
25-
def test_sanity(mode, tmp_path: Path) -> None:
26-
def roundtrip(original_im) -> None:
25+
def test_sanity(mode: str, tmp_path: Path) -> None:
26+
def roundtrip(original_im: Image.Image) -> None:
2727
out = str(tmp_path / "temp.tga")
2828

2929
original_im.save(out, rle=rle)

Tests/test_file_tiff_metadata.py

+4-2
Original file line numberDiff line numberDiff line change
@@ -189,7 +189,9 @@ def test_iptc(tmp_path: Path) -> None:
189189

190190

191191
@pytest.mark.parametrize("value, expected", ((b"test", "test"), (1, "1")))
192-
def test_writing_other_types_to_ascii(value, expected, tmp_path: Path) -> None:
192+
def test_writing_other_types_to_ascii(
193+
value: bytes | int, expected: str, tmp_path: Path
194+
) -> None:
193195
info = TiffImagePlugin.ImageFileDirectory_v2()
194196

195197
tag = TiffTags.TAGS_V2[271]
@@ -206,7 +208,7 @@ def test_writing_other_types_to_ascii(value, expected, tmp_path: Path) -> None:
206208

207209

208210
@pytest.mark.parametrize("value", (1, IFDRational(1)))
209-
def test_writing_other_types_to_bytes(value, tmp_path: Path) -> None:
211+
def test_writing_other_types_to_bytes(value: int | IFDRational, tmp_path: Path) -> None:
210212
im = hopper()
211213
info = TiffImagePlugin.ImageFileDirectory_v2()
212214

Tests/test_imagecms.py

+12-7
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@
66
import shutil
77
from io import BytesIO
88
from pathlib import Path
9+
from typing import Any
910

1011
import pytest
1112

@@ -237,7 +238,7 @@ def test_invalid_color_temperature() -> None:
237238

238239

239240
@pytest.mark.parametrize("flag", ("my string", -1))
240-
def test_invalid_flag(flag) -> None:
241+
def test_invalid_flag(flag: str | int) -> None:
241242
with hopper() as im:
242243
with pytest.raises(
243244
ImageCms.PyCMSError, match="flags must be an integer between 0 and "
@@ -335,19 +336,21 @@ def test_extended_information() -> None:
335336
o = ImageCms.getOpenProfile(SRGB)
336337
p = o.profile
337338

338-
def assert_truncated_tuple_equal(tup1, tup2, digits: int = 10) -> None:
339+
def assert_truncated_tuple_equal(
340+
tup1: tuple[Any, ...], tup2: tuple[Any, ...], digits: int = 10
341+
) -> None:
339342
# Helper function to reduce precision of tuples of floats
340343
# recursively and then check equality.
341344
power = 10**digits
342345

343-
def truncate_tuple(tuple_or_float):
346+
def truncate_tuple(tuple_value: tuple[Any, ...]) -> tuple[Any, ...]:
344347
return tuple(
345348
(
346349
truncate_tuple(val)
347350
if isinstance(val, tuple)
348351
else int(val * power) / power
349352
)
350-
for val in tuple_or_float
353+
for val in tuple_value
351354
)
352355

353356
assert truncate_tuple(tup1) == truncate_tuple(tup2)
@@ -504,8 +507,10 @@ def test_profile_typesafety() -> None:
504507
ImageCms.ImageCmsProfile(1).tobytes()
505508

506509

507-
def assert_aux_channel_preserved(mode, transform_in_place, preserved_channel) -> None:
508-
def create_test_image():
510+
def assert_aux_channel_preserved(
511+
mode: str, transform_in_place: bool, preserved_channel: str
512+
) -> None:
513+
def create_test_image() -> Image.Image:
509514
# set up test image with something interesting in the tested aux channel.
510515
# fmt: off
511516
nine_grid_deltas = [
@@ -633,7 +638,7 @@ def test_auxiliary_channels_isolated() -> None:
633638

634639

635640
@pytest.mark.parametrize("mode", ("RGB", "RGBA", "RGBX"))
636-
def test_rgb_lab(mode) -> None:
641+
def test_rgb_lab(mode: str) -> None:
637642
im = Image.new(mode, (1, 1))
638643
converted_im = im.convert("LAB")
639644
assert converted_im.getpixel((0, 0)) == (0, 128, 128)

Tests/test_imagefont.py

+12-10
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@
77
import sys
88
from io import BytesIO
99
from pathlib import Path
10-
from typing import BinaryIO
10+
from typing import Any, BinaryIO
1111

1212
import pytest
1313
from packaging.version import parse as parse_version
@@ -44,7 +44,7 @@ def test_sanity() -> None:
4444
pytest.param(ImageFont.Layout.RAQM, marks=skip_unless_feature("raqm")),
4545
],
4646
)
47-
def layout_engine(request):
47+
def layout_engine(request: pytest.FixtureRequest) -> ImageFont.Layout:
4848
return request.param
4949

5050

@@ -535,21 +535,23 @@ def test_unicode_extended(layout_engine: ImageFont.Layout) -> None:
535535
(("linux", "/usr/local/share/fonts"), ("darwin", "/System/Library/Fonts")),
536536
)
537537
@pytest.mark.skipif(is_win32(), reason="requires Unix or macOS")
538-
def test_find_font(monkeypatch, platform, font_directory) -> None:
538+
def test_find_font(
539+
monkeypatch: pytest.MonkeyPatch, platform: str, font_directory: str
540+
) -> None:
539541
def _test_fake_loading_font(path_to_fake: str, fontname: str) -> None:
540542
# Make a copy of FreeTypeFont so we can patch the original
541543
free_type_font = copy.deepcopy(ImageFont.FreeTypeFont)
542544
with monkeypatch.context() as m:
543545
m.setattr(ImageFont, "_FreeTypeFont", free_type_font, raising=False)
544546

545-
def loadable_font(filepath, size, index, encoding, *args, **kwargs):
547+
def loadable_font(
548+
filepath: str, size: int, index: int, encoding: str, *args: Any
549+
):
546550
if filepath == path_to_fake:
547551
return ImageFont._FreeTypeFont(
548-
FONT_PATH, size, index, encoding, *args, **kwargs
552+
FONT_PATH, size, index, encoding, *args
549553
)
550-
return ImageFont._FreeTypeFont(
551-
filepath, size, index, encoding, *args, **kwargs
552-
)
554+
return ImageFont._FreeTypeFont(filepath, size, index, encoding, *args)
553555

554556
m.setattr(ImageFont, "FreeTypeFont", loadable_font)
555557
font = ImageFont.truetype(fontname)
@@ -563,7 +565,7 @@ def loadable_font(filepath, size, index, encoding, *args, **kwargs):
563565
if platform == "linux":
564566
monkeypatch.setenv("XDG_DATA_DIRS", "/usr/share/:/usr/local/share/")
565567

566-
def fake_walker(path):
568+
def fake_walker(path: str) -> list[tuple[str, list[str], list[str]]]:
567569
if path == font_directory:
568570
return [
569571
(
@@ -1101,7 +1103,7 @@ def test_oom(test_file: str) -> None:
11011103
font.getmask("Test Text")
11021104

11031105

1104-
def test_raqm_missing_warning(monkeypatch) -> None:
1106+
def test_raqm_missing_warning(monkeypatch: pytest.MonkeyPatch) -> None:
11051107
monkeypatch.setattr(ImageFont.core, "HAVE_RAQM", False)
11061108
with pytest.warns(UserWarning) as record:
11071109
font = ImageFont.truetype(

Tests/test_imagegrab.py

+4-2
Original file line numberDiff line numberDiff line change
@@ -84,6 +84,7 @@ def test_grabclipboard(self) -> None:
8484
@pytest.mark.skipif(sys.platform != "win32", reason="Windows only")
8585
def test_grabclipboard_file(self) -> None:
8686
p = subprocess.Popen(["powershell", "-command", "-"], stdin=subprocess.PIPE)
87+
assert p.stdin is not None
8788
p.stdin.write(rb'Set-Clipboard -Path "Tests\images\hopper.gif"')
8889
p.communicate()
8990

@@ -94,6 +95,7 @@ def test_grabclipboard_file(self) -> None:
9495
@pytest.mark.skipif(sys.platform != "win32", reason="Windows only")
9596
def test_grabclipboard_png(self) -> None:
9697
p = subprocess.Popen(["powershell", "-command", "-"], stdin=subprocess.PIPE)
98+
assert p.stdin is not None
9799
p.stdin.write(
98100
rb"""$bytes = [System.IO.File]::ReadAllBytes("Tests\images\hopper.png")
99101
$ms = new-object System.IO.MemoryStream(, $bytes)
@@ -113,7 +115,7 @@ def test_grabclipboard_png(self) -> None:
113115
reason="Linux with wl-clipboard only",
114116
)
115117
@pytest.mark.parametrize("ext", ("gif", "png", "ico"))
116-
def test_grabclipboard_wl_clipboard(self, ext) -> None:
118+
def test_grabclipboard_wl_clipboard(self, ext: str) -> None:
117119
image_path = "Tests/images/hopper." + ext
118120
with open(image_path, "rb") as fp:
119121
subprocess.call(["wl-copy"], stdin=fp)
@@ -128,6 +130,6 @@ def test_grabclipboard_wl_clipboard(self, ext) -> None:
128130
reason="Linux with wl-clipboard only",
129131
)
130132
@pytest.mark.parametrize("arg", ("text", "--clear"))
131-
def test_grabclipboard_wl_clipboard_errors(self, arg):
133+
def test_grabclipboard_wl_clipboard_errors(self, arg: str) -> None:
132134
subprocess.call(["wl-copy", arg])
133135
assert ImageGrab.grabclipboard() is None

Tests/test_imagepath.py

+5-3
Original file line numberDiff line numberDiff line change
@@ -58,7 +58,9 @@ def test_path() -> None:
5858
ImagePath.Path((0, 1)),
5959
),
6060
)
61-
def test_path_constructors(coords) -> None:
61+
def test_path_constructors(
62+
coords: Sequence[float] | array.array[float] | ImagePath.Path,
63+
) -> None:
6264
# Arrange / Act
6365
p = ImagePath.Path(coords)
6466

@@ -206,9 +208,9 @@ class Evil:
206208
def __init__(self) -> None:
207209
self.corrupt = Image.core.path(0x4000000000000000)
208210

209-
def __getitem__(self, i):
211+
def __getitem__(self, i: int) -> bytes:
210212
x = self.corrupt[i]
211213
return struct.pack("dd", x[0], x[1])
212214

213-
def __setitem__(self, i, x) -> None:
215+
def __setitem__(self, i: int, x: bytes) -> None:
214216
self.corrupt[i] = struct.unpack("dd", x)

Tests/test_imageqt.py

+1-1
Original file line numberDiff line numberDiff line change
@@ -28,7 +28,7 @@ def test_rgb() -> None:
2828

2929
assert qRgb(0, 0, 0) == qRgba(0, 0, 0, 255)
3030

31-
def checkrgb(r, g, b) -> None:
31+
def checkrgb(r: int, g: int, b: int) -> None:
3232
val = ImageQt.rgb(r, g, b)
3333
val = val % 2**24 # drop the alpha
3434
assert val >> 16 == r

Tests/test_imageshow.py

+6-4
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,7 @@
11
from __future__ import annotations
22

3+
from typing import Any
4+
35
import pytest
46

57
from PIL import Image, ImageShow
@@ -24,9 +26,9 @@ def test_register() -> None:
2426
"order",
2527
[-1, 0],
2628
)
27-
def test_viewer_show(order) -> None:
29+
def test_viewer_show(order: int) -> None:
2830
class TestViewer(ImageShow.Viewer):
29-
def show_image(self, image, **options) -> bool:
31+
def show_image(self, image: Image.Image, **options: Any) -> bool:
3032
self.methodCalled = True
3133
return True
3234

@@ -48,7 +50,7 @@ def show_image(self, image, **options) -> bool:
4850
reason="Only run on CIs; hangs on Windows CIs",
4951
)
5052
@pytest.mark.parametrize("mode", ("1", "I;16", "LA", "RGB", "RGBA"))
51-
def test_show(mode) -> None:
53+
def test_show(mode: str) -> None:
5254
im = hopper(mode)
5355
assert ImageShow.show(im)
5456

@@ -73,7 +75,7 @@ def test_viewer() -> None:
7375

7476

7577
@pytest.mark.parametrize("viewer", ImageShow._viewers)
76-
def test_viewers(viewer) -> None:
78+
def test_viewers(viewer: ImageShow.Viewer) -> None:
7779
try:
7880
viewer.get_command("test.jpg")
7981
except NotImplementedError:

Tests/test_imagewin_pointers.py

+1-1
Original file line numberDiff line numberDiff line change
@@ -70,7 +70,7 @@ class BITMAPINFOHEADER(ctypes.Structure):
7070
]
7171
CreateDIBSection.restype = ctypes.wintypes.HBITMAP
7272

73-
def serialize_dib(bi, pixels):
73+
def serialize_dib(bi, pixels) -> bytearray:
7474
bf = BITMAPFILEHEADER()
7575
bf.bfType = 0x4D42
7676
bf.bfOffBits = ctypes.sizeof(bf) + bi.biSize

Tests/test_numpy.py

+3-3
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,7 @@
1414

1515

1616
def test_numpy_to_image() -> None:
17-
def to_image(dtype, bands: int = 1, boolean: int = 0):
17+
def to_image(dtype, bands: int = 1, boolean: int = 0) -> Image.Image:
1818
if bands == 1:
1919
if boolean:
2020
data = [0, 255] * 50
@@ -99,7 +99,7 @@ def test_1d_array() -> None:
9999
assert_image(Image.fromarray(a), "L", (1, 5))
100100

101101

102-
def _test_img_equals_nparray(img, np) -> None:
102+
def _test_img_equals_nparray(img: Image.Image, np) -> None:
103103
assert len(np.shape) >= 2
104104
np_size = np.shape[1], np.shape[0]
105105
assert img.size == np_size
@@ -157,7 +157,7 @@ def test_save_tiff_uint16() -> None:
157157
("HSV", numpy.uint8),
158158
),
159159
)
160-
def test_to_array(mode, dtype) -> None:
160+
def test_to_array(mode: str, dtype) -> None:
161161
img = hopper(mode)
162162

163163
# Resize to non-square

Tests/test_qt_image_qapplication.py

+2-2
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@
44

55
import pytest
66

7-
from PIL import ImageQt
7+
from PIL import Image, ImageQt
88

99
from .helper import assert_image_equal_tofile, assert_image_similar, hopper
1010

@@ -37,7 +37,7 @@ def __init__(self) -> None:
3737
lbl.setPixmap(pixmap1.copy())
3838

3939

40-
def roundtrip(expected) -> None:
40+
def roundtrip(expected: Image.Image) -> None:
4141
result = ImageQt.fromqpixmap(ImageQt.toqpixmap(expected))
4242
# Qt saves all pixmaps as rgb
4343
assert_image_similar(result, expected.convert("RGB"), 1)

0 commit comments

Comments
 (0)