Skip to content

Commit

Permalink
Merge pull request #7769 from radarhere/type_hints
Browse files Browse the repository at this point in the history
  • Loading branch information
hugovk committed Feb 6, 2024
2 parents 3e04ca5 + 65cb0b0 commit 811dd15
Show file tree
Hide file tree
Showing 18 changed files with 235 additions and 162 deletions.
6 changes: 3 additions & 3 deletions Tests/test_bmp_reference.py
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@
base = os.path.join("Tests", "images", "bmp")


def get_files(d, ext: str = ".bmp"):
def get_files(d: str, ext: str = ".bmp") -> list[str]:
return [
os.path.join(base, d, f) for f in os.listdir(os.path.join(base, d)) if ext in f
]
Expand All @@ -29,7 +29,7 @@ def test_bad() -> None:
pass


def test_questionable():
def test_questionable() -> None:
"""These shouldn't crash/dos, but it's not well defined that these
are in spec"""
supported = [
Expand Down Expand Up @@ -80,7 +80,7 @@ def test_good() -> None:
"rgb32bf.bmp": "rgb24.png",
}

def get_compare(f):
def get_compare(f: str) -> str:
name = os.path.split(f)[1]
if name in file_map:
return os.path.join(base, "html", file_map[name])
Expand Down
12 changes: 9 additions & 3 deletions Tests/test_box_blur.py
Original file line number Diff line number Diff line change
Expand Up @@ -23,11 +23,11 @@ def test_imageops_box_blur() -> None:
assert isinstance(i, Image.Image)


def box_blur(image, radius: int = 1, n: int = 1):
def box_blur(image: Image.Image, radius: float = 1, n: int = 1) -> Image.Image:
return image._new(image.im.box_blur((radius, radius), n))


def assert_image(im, data, delta: int = 0) -> None:
def assert_image(im: Image.Image, data: list[list[int]], delta: int = 0) -> None:
it = iter(im.getdata())
for data_row in data:
im_row = [next(it) for _ in range(im.size[0])]
Expand All @@ -37,7 +37,13 @@ def assert_image(im, data, delta: int = 0) -> None:
next(it)


def assert_blur(im, radius, data, passes: int = 1, delta: int = 0) -> None:
def assert_blur(
im: Image.Image,
radius: float,
data: list[list[int]],
passes: int = 1,
delta: int = 0,
) -> None:
# check grayscale image
assert_image(box_blur(im, radius, passes), data, delta)
rgba = Image.merge("RGBA", (im, im, im, im))
Expand Down
6 changes: 3 additions & 3 deletions Tests/test_file_apng.py
Original file line number Diff line number Diff line change
Expand Up @@ -47,7 +47,7 @@ def test_apng_basic() -> None:
"filename",
("Tests/images/apng/split_fdat.png", "Tests/images/apng/split_fdat_zero_chunk.png"),
)
def test_apng_fdat(filename) -> None:
def test_apng_fdat(filename: str) -> None:
with Image.open(filename) as im:
im.seek(im.n_frames - 1)
assert im.getpixel((0, 0)) == (0, 255, 0, 255)
Expand Down Expand Up @@ -338,7 +338,7 @@ def test_apng_syntax_errors() -> None:
"sequence_fdat_fctl.png",
),
)
def test_apng_sequence_errors(test_file) -> None:
def test_apng_sequence_errors(test_file: str) -> None:
with pytest.raises(SyntaxError):
with Image.open(f"Tests/images/apng/{test_file}") as im:
im.seek(im.n_frames - 1)
Expand Down Expand Up @@ -681,7 +681,7 @@ def test_seek_after_close() -> None:
@pytest.mark.parametrize("default_image", (True, False))
@pytest.mark.parametrize("duplicate", (True, False))
def test_different_modes_in_later_frames(
mode, default_image, duplicate, tmp_path: Path
mode: str, default_image: bool, duplicate: bool, tmp_path: Path
) -> None:
test_file = str(tmp_path / "temp.png")

Expand Down
10 changes: 5 additions & 5 deletions Tests/test_file_container.py
Original file line number Diff line number Diff line change
Expand Up @@ -64,7 +64,7 @@ def test_seek_mode_2() -> None:


@pytest.mark.parametrize("bytesmode", (True, False))
def test_read_n0(bytesmode) -> None:
def test_read_n0(bytesmode: bool) -> None:
# Arrange
with open(TEST_FILE, "rb" if bytesmode else "r") as fh:
container = ContainerIO.ContainerIO(fh, 22, 100)
Expand All @@ -80,7 +80,7 @@ def test_read_n0(bytesmode) -> None:


@pytest.mark.parametrize("bytesmode", (True, False))
def test_read_n(bytesmode) -> None:
def test_read_n(bytesmode: bool) -> None:
# Arrange
with open(TEST_FILE, "rb" if bytesmode else "r") as fh:
container = ContainerIO.ContainerIO(fh, 22, 100)
Expand All @@ -96,7 +96,7 @@ def test_read_n(bytesmode) -> None:


@pytest.mark.parametrize("bytesmode", (True, False))
def test_read_eof(bytesmode) -> None:
def test_read_eof(bytesmode: bool) -> None:
# Arrange
with open(TEST_FILE, "rb" if bytesmode else "r") as fh:
container = ContainerIO.ContainerIO(fh, 22, 100)
Expand All @@ -112,7 +112,7 @@ def test_read_eof(bytesmode) -> None:


@pytest.mark.parametrize("bytesmode", (True, False))
def test_readline(bytesmode) -> None:
def test_readline(bytesmode: bool) -> None:
# Arrange
with open(TEST_FILE, "rb" if bytesmode else "r") as fh:
container = ContainerIO.ContainerIO(fh, 0, 120)
Expand All @@ -127,7 +127,7 @@ def test_readline(bytesmode) -> None:


@pytest.mark.parametrize("bytesmode", (True, False))
def test_readlines(bytesmode) -> None:
def test_readlines(bytesmode: bool) -> None:
# Arrange
expected = [
"This is line 1\n",
Expand Down
30 changes: 19 additions & 11 deletions Tests/test_file_gif.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@
import warnings
from io import BytesIO
from pathlib import Path
from typing import Generator

import pytest

Expand Down Expand Up @@ -144,13 +145,13 @@ def test_strategy() -> None:


def test_optimize() -> None:
def test_grayscale(optimize):
def test_grayscale(optimize: int) -> int:
im = Image.new("L", (1, 1), 0)
filename = BytesIO()
im.save(filename, "GIF", optimize=optimize)
return len(filename.getvalue())

def test_bilevel(optimize):
def test_bilevel(optimize: int) -> int:
im = Image.new("1", (1, 1), 0)
test_file = BytesIO()
im.save(test_file, "GIF", optimize=optimize)
Expand Down Expand Up @@ -178,7 +179,9 @@ def test_bilevel(optimize):
(4, 513, 256),
),
)
def test_optimize_correctness(colors, size, expected_palette_length) -> None:
def test_optimize_correctness(
colors: int, size: int, expected_palette_length: int
) -> None:
# 256 color Palette image, posterize to > 128 and < 128 levels.
# Size bigger and smaller than 512x512.
# Check the palette for number of colors allocated.
Expand Down Expand Up @@ -297,7 +300,7 @@ def test_roundtrip_save_all_1(tmp_path: Path) -> None:
("Tests/images/dispose_bgnd_rgba.gif", "RGBA"),
),
)
def test_loading_multiple_palettes(path, mode) -> None:
def test_loading_multiple_palettes(path: str, mode: str) -> None:
with Image.open(path) as im:
assert im.mode == "P"
first_frame_colors = im.palette.colors.keys()
Expand Down Expand Up @@ -347,9 +350,9 @@ def test_palette_handling(tmp_path: Path) -> None:
def test_palette_434(tmp_path: Path) -> None:
# see https://github.com/python-pillow/Pillow/issues/434

def roundtrip(im, *args, **kwargs):
def roundtrip(im: Image.Image, **kwargs: bool) -> Image.Image:
out = str(tmp_path / "temp.gif")
im.copy().save(out, *args, **kwargs)
im.copy().save(out, **kwargs)
reloaded = Image.open(out)

return reloaded
Expand Down Expand Up @@ -429,7 +432,7 @@ def test_seek_rewind() -> None:
("Tests/images/iss634.gif", 42),
),
)
def test_n_frames(path, n_frames) -> None:
def test_n_frames(path: str, n_frames: int) -> None:
# Test is_animated before n_frames
with Image.open(path) as im:
assert im.is_animated == (n_frames != 1)
Expand Down Expand Up @@ -541,7 +544,10 @@ def test_dispose_background_transparency() -> None:
),
),
)
def test_transparent_dispose(loading_strategy, expected_colors) -> None:
def test_transparent_dispose(
loading_strategy: GifImagePlugin.LoadingStrategy,
expected_colors: tuple[tuple[int | tuple[int, int, int, int], ...]],
) -> None:
GifImagePlugin.LOADING_STRATEGY = loading_strategy
try:
with Image.open("Tests/images/transparent_dispose.gif") as img:
Expand Down Expand Up @@ -889,7 +895,9 @@ def test_identical_frames(tmp_path: Path) -> None:
1500,
),
)
def test_identical_frames_to_single_frame(duration, tmp_path: Path) -> None:
def test_identical_frames_to_single_frame(
duration: int | list[int], tmp_path: Path
) -> None:
out = str(tmp_path / "temp.gif")
im_list = [
Image.new("L", (100, 100), "#000"),
Expand Down Expand Up @@ -1049,7 +1057,7 @@ def test_retain_comment_in_subsequent_frames(tmp_path: Path) -> None:
def test_version(tmp_path: Path) -> None:
out = str(tmp_path / "temp.gif")

def assert_version_after_save(im, version) -> None:
def assert_version_after_save(im: Image.Image, version: bytes) -> None:
im.save(out)
with Image.open(out) as reread:
assert reread.info["version"] == version
Expand Down Expand Up @@ -1088,7 +1096,7 @@ def test_append_images(tmp_path: Path) -> None:
assert reread.n_frames == 3

# Tests appending using a generator
def im_generator(ims):
def im_generator(ims: list[Image.Image]) -> Generator[Image.Image, None, None]:
yield from ims

im.save(out, save_all=True, append_images=im_generator(ims))
Expand Down
19 changes: 10 additions & 9 deletions Tests/test_file_mpo.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@

import warnings
from io import BytesIO
from typing import Any

import pytest

Expand All @@ -19,7 +20,7 @@
pytestmark = skip_unless_feature("jpg")


def roundtrip(im, **options):
def roundtrip(im: Image.Image, **options: Any) -> Image.Image:
out = BytesIO()
im.save(out, "MPO", **options)
test_bytes = out.tell()
Expand All @@ -30,7 +31,7 @@ def roundtrip(im, **options):


@pytest.mark.parametrize("test_file", test_files)
def test_sanity(test_file) -> None:
def test_sanity(test_file: str) -> None:
with Image.open(test_file) as im:
im.load()
assert im.mode == "RGB"
Expand Down Expand Up @@ -70,7 +71,7 @@ def test_context_manager() -> None:


@pytest.mark.parametrize("test_file", test_files)
def test_app(test_file) -> None:
def test_app(test_file: str) -> None:
# Test APP/COM reader (@PIL135)
with Image.open(test_file) as im:
assert im.applist[0][0] == "APP1"
Expand All @@ -82,7 +83,7 @@ def test_app(test_file) -> None:


@pytest.mark.parametrize("test_file", test_files)
def test_exif(test_file) -> None:
def test_exif(test_file: str) -> None:
with Image.open(test_file) as im_original:
im_reloaded = roundtrip(im_original, save_all=True, exif=im_original.getexif())

Expand Down Expand Up @@ -143,7 +144,7 @@ def test_reload_exif_after_seek() -> None:


@pytest.mark.parametrize("test_file", test_files)
def test_mp(test_file) -> None:
def test_mp(test_file: str) -> None:
with Image.open(test_file) as im:
mpinfo = im._getmp()
assert mpinfo[45056] == b"0100"
Expand All @@ -168,7 +169,7 @@ def test_mp_no_data() -> None:


@pytest.mark.parametrize("test_file", test_files)
def test_mp_attribute(test_file) -> None:
def test_mp_attribute(test_file: str) -> None:
with Image.open(test_file) as im:
mpinfo = im._getmp()
for frame_number, mpentry in enumerate(mpinfo[0xB002]):
Expand All @@ -185,7 +186,7 @@ def test_mp_attribute(test_file) -> None:


@pytest.mark.parametrize("test_file", test_files)
def test_seek(test_file) -> None:
def test_seek(test_file: str) -> None:
with Image.open(test_file) as im:
assert im.tell() == 0
# prior to first image raises an error, both blatant and borderline
Expand Down Expand Up @@ -229,7 +230,7 @@ def test_eoferror() -> None:


@pytest.mark.parametrize("test_file", test_files)
def test_image_grab(test_file) -> None:
def test_image_grab(test_file: str) -> None:
with Image.open(test_file) as im:
assert im.tell() == 0
im0 = im.tobytes()
Expand All @@ -244,7 +245,7 @@ def test_image_grab(test_file) -> None:


@pytest.mark.parametrize("test_file", test_files)
def test_save(test_file) -> None:
def test_save(test_file: str) -> None:
with Image.open(test_file) as im:
assert im.tell() == 0
jpg0 = roundtrip(im)
Expand Down
Loading

0 comments on commit 811dd15

Please sign in to comment.