Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Added type hints to additional tests #7784

Merged
merged 2 commits into from
Feb 7, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
4 changes: 3 additions & 1 deletion Tests/test_color_lut.py
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,9 @@


class TestColorLut3DCoreAPI:
def generate_identity_table(self, channels, size):
def generate_identity_table(
self, channels: int, size: int | tuple[int, int, int]
) -> tuple[int, int, int, int, list[float]]:
if isinstance(size, tuple):
size_1d, size_2d, size_3d = size
else:
Expand Down
32 changes: 16 additions & 16 deletions Tests/test_file_eps.py
Original file line number Diff line number Diff line change
Expand Up @@ -84,7 +84,7 @@
("filename", "size"), ((FILE1, (460, 352)), (FILE2, (360, 252)))
)
@pytest.mark.parametrize("scale", (1, 2))
def test_sanity(filename, size, scale) -> None:
def test_sanity(filename: str, size: tuple[int, int], scale: int) -> None:
expected_size = tuple(s * scale for s in size)
with Image.open(filename) as image:
image.load(scale=scale)
Expand Down Expand Up @@ -129,28 +129,28 @@ def test_binary_header_only() -> None:


@pytest.mark.parametrize("prefix", (b"", simple_binary_header))
def test_missing_version_comment(prefix) -> None:
def test_missing_version_comment(prefix: bytes) -> None:
data = io.BytesIO(prefix + b"\n".join(simple_eps_file_without_version))
with pytest.raises(SyntaxError):
EpsImagePlugin.EpsImageFile(data)


@pytest.mark.parametrize("prefix", (b"", simple_binary_header))
def test_missing_boundingbox_comment(prefix) -> None:
def test_missing_boundingbox_comment(prefix: bytes) -> None:
data = io.BytesIO(prefix + b"\n".join(simple_eps_file_without_boundingbox))
with pytest.raises(SyntaxError, match='EPS header missing "%%BoundingBox" comment'):
EpsImagePlugin.EpsImageFile(data)


@pytest.mark.parametrize("prefix", (b"", simple_binary_header))
def test_invalid_boundingbox_comment(prefix) -> None:
def test_invalid_boundingbox_comment(prefix: bytes) -> None:
data = io.BytesIO(prefix + b"\n".join(simple_eps_file_with_invalid_boundingbox))
with pytest.raises(OSError, match="cannot determine EPS bounding box"):
EpsImagePlugin.EpsImageFile(data)


@pytest.mark.parametrize("prefix", (b"", simple_binary_header))
def test_invalid_boundingbox_comment_valid_imagedata_comment(prefix) -> None:
def test_invalid_boundingbox_comment_valid_imagedata_comment(prefix: bytes) -> None:
data = io.BytesIO(
prefix + b"\n".join(simple_eps_file_with_invalid_boundingbox_valid_imagedata)
)
Expand All @@ -161,21 +161,21 @@ def test_invalid_boundingbox_comment_valid_imagedata_comment(prefix) -> None:


@pytest.mark.parametrize("prefix", (b"", simple_binary_header))
def test_ascii_comment_too_long(prefix) -> None:
def test_ascii_comment_too_long(prefix: bytes) -> None:
data = io.BytesIO(prefix + b"\n".join(simple_eps_file_with_long_ascii_comment))
with pytest.raises(SyntaxError, match="not an EPS file"):
EpsImagePlugin.EpsImageFile(data)


@pytest.mark.parametrize("prefix", (b"", simple_binary_header))
def test_long_binary_data(prefix) -> None:
def test_long_binary_data(prefix: bytes) -> None:
data = io.BytesIO(prefix + b"\n".join(simple_eps_file_with_long_binary_data))
EpsImagePlugin.EpsImageFile(data)


@pytest.mark.skipif(not HAS_GHOSTSCRIPT, reason="Ghostscript not available")
@pytest.mark.parametrize("prefix", (b"", simple_binary_header))
def test_load_long_binary_data(prefix) -> None:
def test_load_long_binary_data(prefix: bytes) -> None:
data = io.BytesIO(prefix + b"\n".join(simple_eps_file_with_long_binary_data))
with Image.open(data) as img:
img.load()
Expand Down Expand Up @@ -305,7 +305,7 @@ def test_render_scale2() -> None:

@pytest.mark.skipif(not HAS_GHOSTSCRIPT, reason="Ghostscript not available")
@pytest.mark.parametrize("filename", (FILE1, FILE2, "Tests/images/illu10_preview.eps"))
def test_resize(filename) -> None:
def test_resize(filename: str) -> None:
with Image.open(filename) as im:
new_size = (100, 100)
im = im.resize(new_size)
Expand All @@ -314,7 +314,7 @@ def test_resize(filename) -> None:

@pytest.mark.skipif(not HAS_GHOSTSCRIPT, reason="Ghostscript not available")
@pytest.mark.parametrize("filename", (FILE1, FILE2))
def test_thumbnail(filename) -> None:
def test_thumbnail(filename: str) -> None:
# Issue #619
with Image.open(filename) as im:
new_size = (100, 100)
Expand All @@ -335,7 +335,7 @@ def test_readline_psfile(tmp_path: Path) -> None:
line_endings = ["\r\n", "\n", "\n\r", "\r"]
strings = ["something", "else", "baz", "bif"]

def _test_readline(t, ending) -> None:
def _test_readline(t: EpsImagePlugin.PSFile, ending: str) -> None:
ending = "Failure with line ending: %s" % (
"".join("%s" % ord(s) for s in ending)
)
Expand All @@ -344,13 +344,13 @@ def _test_readline(t, ending) -> None:
assert t.readline().strip("\r\n") == "baz", ending
assert t.readline().strip("\r\n") == "bif", ending

def _test_readline_io_psfile(test_string, ending) -> None:
def _test_readline_io_psfile(test_string: str, ending: str) -> None:
f = io.BytesIO(test_string.encode("latin-1"))
with pytest.warns(DeprecationWarning):
t = EpsImagePlugin.PSFile(f)
_test_readline(t, ending)

def _test_readline_file_psfile(test_string, ending) -> None:
def _test_readline_file_psfile(test_string: str, ending: str) -> None:
f = str(tmp_path / "temp.txt")
with open(f, "wb") as w:
w.write(test_string.encode("latin-1"))
Expand All @@ -376,7 +376,7 @@ def test_psfile_deprecation() -> None:
"line_ending",
(b"\r\n", b"\n", b"\n\r", b"\r"),
)
def test_readline(prefix, line_ending) -> None:
def test_readline(prefix: bytes, line_ending: bytes) -> None:
simple_file = prefix + line_ending.join(simple_eps_file_with_comments)
data = io.BytesIO(simple_file)
test_file = EpsImagePlugin.EpsImageFile(data)
Expand All @@ -394,7 +394,7 @@ def test_readline(prefix, line_ending) -> None:
"Tests/images/illuCS6_preview.eps",
),
)
def test_open_eps(filename) -> None:
def test_open_eps(filename: str) -> None:
# https://github.com/python-pillow/Pillow/issues/1104
with Image.open(filename) as img:
assert img.mode == "RGB"
Expand All @@ -417,7 +417,7 @@ def test_emptyline() -> None:
"test_file",
["Tests/images/timeout-d675703545fee17acab56e5fec644c19979175de.eps"],
)
def test_timeout(test_file) -> None:
def test_timeout(test_file: str) -> None:
with open(test_file, "rb") as f:
with pytest.raises(Image.UnidentifiedImageError):
with Image.open(f):
Expand Down
35 changes: 17 additions & 18 deletions Tests/test_file_jpeg.py
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@
import warnings
from io import BytesIO
from pathlib import Path
from typing import Any

import pytest

Expand Down Expand Up @@ -42,7 +43,7 @@

@skip_unless_feature("jpg")
class TestFileJpeg:
def roundtrip(self, im, **options):
def roundtrip(self, im: Image.Image, **options: Any) -> Image.Image:
out = BytesIO()
im.save(out, "JPEG", **options)
test_bytes = out.tell()
Expand All @@ -51,7 +52,7 @@ def roundtrip(self, im, **options):
im.bytes = test_bytes # for testing only
return im

def gen_random_image(self, size, mode: str = "RGB"):
def gen_random_image(self, size: tuple[int, int], mode: str = "RGB") -> Image.Image:
"""Generates a very hard to compress file
:param size: tuple
:param mode: optional image mode
Expand All @@ -71,7 +72,7 @@ def test_sanity(self) -> None:
assert im.get_format_mimetype() == "image/jpeg"

@pytest.mark.parametrize("size", ((1, 0), (0, 1), (0, 0)))
def test_zero(self, size, tmp_path: Path) -> None:
def test_zero(self, size: tuple[int, int], tmp_path: Path) -> None:
f = str(tmp_path / "temp.jpg")
im = Image.new("RGB", size)
with pytest.raises(ValueError):
Expand Down Expand Up @@ -108,13 +109,11 @@ def test_comment_write(self) -> None:
assert "comment" not in reloaded.info

# Test that a comment argument overrides the default comment
for comment in ("Test comment text", b"Text comment text"):
for comment in ("Test comment text", b"Test comment text"):
out = BytesIO()
im.save(out, format="JPEG", comment=comment)
with Image.open(out) as reloaded:
if not isinstance(comment, bytes):
comment = comment.encode()
assert reloaded.info["comment"] == comment
assert reloaded.info["comment"] == b"Test comment text"

def test_cmyk(self) -> None:
# Test CMYK handling. Thanks to Tim and Charlie for test data,
Expand Down Expand Up @@ -145,7 +144,7 @@ def test_cmyk(self) -> None:
assert k > 0.9

def test_rgb(self) -> None:
def getchannels(im):
def getchannels(im: Image.Image) -> tuple[int, int, int]:
return tuple(v[0] for v in im.layer)

im = hopper()
Expand All @@ -161,8 +160,8 @@ def getchannels(im):
"test_image_path",
[TEST_FILE, "Tests/images/pil_sample_cmyk.jpg"],
)
def test_dpi(self, test_image_path) -> None:
def test(xdpi, ydpi=None):
def test_dpi(self, test_image_path: str) -> None:
def test(xdpi: int, ydpi: int | None = None):
with Image.open(test_image_path) as im:
im = self.roundtrip(im, dpi=(xdpi, ydpi or xdpi))
return im.info.get("dpi")
Expand Down Expand Up @@ -207,7 +206,7 @@ def test_icc(self, tmp_path: Path) -> None:
ImageFile.MAXBLOCK * 4 + 3, # large block
),
)
def test_icc_big(self, n) -> None:
def test_icc_big(self, n: int) -> None:
# Make sure that the "extra" support handles large blocks
# The ICC APP marker can store 65519 bytes per marker, so
# using a 4-byte test code should allow us to detect out of
Expand Down Expand Up @@ -433,7 +432,7 @@ def test_smooth(self) -> None:
assert_image(im1, im2.mode, im2.size)

def test_subsampling(self) -> None:
def getsampling(im):
def getsampling(im: Image.Image):
layer = im.layer
return layer[0][1:3] + layer[1][1:3] + layer[2][1:3]

Expand Down Expand Up @@ -530,7 +529,7 @@ def test_truncated_jpeg_throws_oserror(self) -> None:
pytest.mark.valgrind_known_error, "libjpeg_turbo", "2.0", reason="Known Failing"
)
def test_qtables(self, tmp_path: Path) -> None:
def _n_qtables_helper(n, test_file) -> None:
def _n_qtables_helper(n: int, test_file: str) -> None:
with Image.open(test_file) as im:
f = str(tmp_path / "temp.jpg")
im.save(f, qtables=[[n] * 64] * n)
Expand Down Expand Up @@ -666,7 +665,7 @@ def test_save_low_quality_baseline_qtables(self) -> None:
"blocks, rows, markers",
((0, 0, 0), (1, 0, 15), (3, 0, 5), (8, 0, 1), (0, 1, 3), (0, 2, 1)),
)
def test_restart_markers(self, blocks, rows, markers) -> None:
def test_restart_markers(self, blocks: int, rows: int, markers: int) -> None:
im = Image.new("RGB", (32, 32)) # 16 MCUs
out = BytesIO()
im.save(
Expand Down Expand Up @@ -724,13 +723,13 @@ def test_bad_mpo_header(self) -> None:
assert im.format == "JPEG"

@pytest.mark.parametrize("mode", ("1", "L", "RGB", "RGBX", "CMYK", "YCbCr"))
def test_save_correct_modes(self, mode) -> None:
def test_save_correct_modes(self, mode: str) -> None:
out = BytesIO()
img = Image.new(mode, (20, 20))
img.save(out, "JPEG")

@pytest.mark.parametrize("mode", ("LA", "La", "RGBA", "RGBa", "P"))
def test_save_wrong_modes(self, mode) -> None:
def test_save_wrong_modes(self, mode: str) -> None:
# ref https://github.com/python-pillow/Pillow/issues/2005
out = BytesIO()
img = Image.new(mode, (20, 20))
Expand Down Expand Up @@ -982,12 +981,12 @@ def test_eof(self) -> None:
# Even though this decoder never says that it is finished
# the image should still end when there is no new data
class InfiniteMockPyDecoder(ImageFile.PyDecoder):
def decode(self, buffer):
def decode(self, buffer: bytes) -> tuple[int, int]:
return 0, 0

decoder = InfiniteMockPyDecoder(None)

def closure(mode, *args):
def closure(mode: str, *args) -> InfiniteMockPyDecoder:
decoder.__init__(mode, *args)
return decoder

Expand Down
21 changes: 11 additions & 10 deletions Tests/test_file_jpeg2k.py
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@
import re
from io import BytesIO
from pathlib import Path
from typing import Any

import pytest

Expand Down Expand Up @@ -36,7 +37,7 @@
# 'Not enough memory to handle tile data'


def roundtrip(im, **options):
def roundtrip(im: Image.Image, **options: Any) -> Image.Image:
out = BytesIO()
im.save(out, "JPEG2000", **options)
test_bytes = out.tell()
Expand Down Expand Up @@ -138,7 +139,7 @@ def test_prog_res_rt() -> None:


@pytest.mark.parametrize("num_resolutions", range(2, 6))
def test_default_num_resolutions(num_resolutions) -> None:
def test_default_num_resolutions(num_resolutions: int) -> None:
d = 1 << (num_resolutions - 1)
im = test_card.resize((d - 1, d - 1))
with pytest.raises(OSError):
Expand Down Expand Up @@ -198,9 +199,9 @@ def test_layers_type(tmp_path: Path) -> None:
for quality_layers in [[100, 50, 10], (100, 50, 10), None]:
test_card.save(outfile, quality_layers=quality_layers)

for quality_layers in ["quality_layers", ("100", "50", "10")]:
for quality_layers_str in ["quality_layers", ("100", "50", "10")]:
with pytest.raises(ValueError):
test_card.save(outfile, quality_layers=quality_layers)
test_card.save(outfile, quality_layers=quality_layers_str)


def test_layers() -> None:
Expand Down Expand Up @@ -233,7 +234,7 @@ def test_layers() -> None:
("foo.jp2", {"no_jp2": False}, 4, b"jP"),
),
)
def test_no_jp2(name, args, offset, data) -> None:
def test_no_jp2(name: str, args: dict[str, bool], offset: int, data: bytes) -> None:
out = BytesIO()
if name:
out.name = name
Expand Down Expand Up @@ -278,7 +279,7 @@ def test_sgnd(tmp_path: Path) -> None:


@pytest.mark.parametrize("ext", (".j2k", ".jp2"))
def test_rgba(ext) -> None:
def test_rgba(ext: str) -> None:
# Arrange
with Image.open("Tests/images/rgb_trns_ycbc" + ext) as im:
# Act
Expand All @@ -289,7 +290,7 @@ def test_rgba(ext) -> None:


@pytest.mark.parametrize("ext", (".j2k", ".jp2"))
def test_16bit_monochrome_has_correct_mode(ext) -> None:
def test_16bit_monochrome_has_correct_mode(ext: str) -> None:
with Image.open("Tests/images/16bit.cropped" + ext) as im:
im.load()
assert im.mode == "I;16"
Expand Down Expand Up @@ -346,12 +347,12 @@ def test_parser_feed() -> None:
not os.path.exists(EXTRA_DIR), reason="Extra image files not installed"
)
@pytest.mark.parametrize("name", ("subsampling_1", "subsampling_2", "zoo1", "zoo2"))
def test_subsampling_decode(name) -> None:
def test_subsampling_decode(name: str) -> None:
test = f"{EXTRA_DIR}/{name}.jp2"
reference = f"{EXTRA_DIR}/{name}.ppm"

with Image.open(test) as im:
epsilon = 3 # for YCbCr images
epsilon = 3.0 # for YCbCr images
with Image.open(reference) as im2:
width, height = im2.size
if name[-1] == "2":
Expand Down Expand Up @@ -400,7 +401,7 @@ def test_save_comment() -> None:
"Tests/images/crash-d2c93af851d3ab9a19e34503626368b2ecde9c03.j2k",
],
)
def test_crashes(test_file) -> None:
def test_crashes(test_file: str) -> None:
with open(test_file, "rb") as f:
with Image.open(f) as im:
# Valgrind should not complain here
Expand Down