mirror of
https://github.com/python-pillow/Pillow.git
synced 2025-01-12 02:06:18 +03:00
Merge pull request #7793 from radarhere/type_hints_test_image
Added remaining type hints to Tests/test_image_*.py
This commit is contained in:
commit
cdecb3da91
|
@ -244,7 +244,7 @@ def fromstring(data: bytes) -> Image.Image:
|
|||
return Image.open(BytesIO(data))
|
||||
|
||||
|
||||
def tostring(im: Image.Image, string_format: str, **options: dict[str, Any]) -> bytes:
|
||||
def tostring(im: Image.Image, string_format: str, **options: Any) -> bytes:
|
||||
out = BytesIO()
|
||||
im.save(out, string_format, **options)
|
||||
return out.getvalue()
|
||||
|
|
|
@ -4,6 +4,7 @@ import os
|
|||
import subprocess
|
||||
import sys
|
||||
import sysconfig
|
||||
from types import ModuleType
|
||||
|
||||
import pytest
|
||||
|
||||
|
@ -23,6 +24,7 @@ else:
|
|||
except ImportError:
|
||||
cffi = None
|
||||
|
||||
numpy: ModuleType | None
|
||||
try:
|
||||
import numpy
|
||||
except ImportError:
|
||||
|
@ -71,9 +73,10 @@ class TestImagePutPixel(AccessTest):
|
|||
pix1 = im1.load()
|
||||
pix2 = im2.load()
|
||||
|
||||
for x, y in ((0, "0"), ("0", 0)):
|
||||
with pytest.raises(TypeError):
|
||||
pix1[x, y]
|
||||
with pytest.raises(TypeError):
|
||||
pix1[0, "0"]
|
||||
with pytest.raises(TypeError):
|
||||
pix1["0", 0]
|
||||
|
||||
for y in range(im1.size[1]):
|
||||
for x in range(im1.size[0]):
|
||||
|
@ -123,12 +126,13 @@ class TestImagePutPixel(AccessTest):
|
|||
im = hopper()
|
||||
pix = im.load()
|
||||
|
||||
assert numpy is not None
|
||||
assert pix[numpy.int32(1), numpy.int32(2)] == (18, 20, 59)
|
||||
|
||||
|
||||
class TestImageGetPixel(AccessTest):
|
||||
@staticmethod
|
||||
def color(mode):
|
||||
def color(mode: str) -> int | tuple[int, ...]:
|
||||
bands = Image.getmodebands(mode)
|
||||
if bands == 1:
|
||||
return 1
|
||||
|
@ -138,12 +142,13 @@ class TestImageGetPixel(AccessTest):
|
|||
return (16, 32, 49)
|
||||
return tuple(range(1, bands + 1))
|
||||
|
||||
def check(self, mode, expected_color=None) -> None:
|
||||
def check(self, mode: str, expected_color_int: int | None = None) -> None:
|
||||
if self._need_cffi_access and mode.startswith("BGR;"):
|
||||
pytest.skip("Support not added to deprecated module for BGR;* modes")
|
||||
|
||||
if not expected_color:
|
||||
expected_color = self.color(mode)
|
||||
expected_color = (
|
||||
self.color(mode) if expected_color_int is None else expected_color_int
|
||||
)
|
||||
|
||||
# check putpixel
|
||||
im = Image.new(mode, (1, 1), None)
|
||||
|
@ -222,7 +227,7 @@ class TestImageGetPixel(AccessTest):
|
|||
"YCbCr",
|
||||
),
|
||||
)
|
||||
def test_basic(self, mode) -> None:
|
||||
def test_basic(self, mode: str) -> None:
|
||||
self.check(mode)
|
||||
|
||||
def test_list(self) -> None:
|
||||
|
@ -231,14 +236,14 @@ class TestImageGetPixel(AccessTest):
|
|||
|
||||
@pytest.mark.parametrize("mode", ("I;16", "I;16B"))
|
||||
@pytest.mark.parametrize("expected_color", (2**15 - 1, 2**15, 2**15 + 1, 2**16 - 1))
|
||||
def test_signedness(self, mode, expected_color) -> None:
|
||||
def test_signedness(self, mode: str, expected_color: int) -> None:
|
||||
# see https://github.com/python-pillow/Pillow/issues/452
|
||||
# pixelaccess is using signed int* instead of uint*
|
||||
self.check(mode, expected_color)
|
||||
|
||||
@pytest.mark.parametrize("mode", ("P", "PA"))
|
||||
@pytest.mark.parametrize("color", ((255, 0, 0), (255, 0, 0, 255)))
|
||||
def test_p_putpixel_rgb_rgba(self, mode, color) -> None:
|
||||
def test_p_putpixel_rgb_rgba(self, mode: str, color: tuple[int, ...]) -> None:
|
||||
im = Image.new(mode, (1, 1))
|
||||
im.putpixel((0, 0), color)
|
||||
|
||||
|
@ -262,7 +267,7 @@ class TestCffiGetPixel(TestImageGetPixel):
|
|||
class TestCffi(AccessTest):
|
||||
_need_cffi_access = True
|
||||
|
||||
def _test_get_access(self, im) -> None:
|
||||
def _test_get_access(self, im: Image.Image) -> None:
|
||||
"""Do we get the same thing as the old pixel access
|
||||
|
||||
Using private interfaces, forcing a capi access and
|
||||
|
@ -299,7 +304,7 @@ class TestCffi(AccessTest):
|
|||
# im = Image.new('I;32B', (10, 10), 2**10)
|
||||
# self._test_get_access(im)
|
||||
|
||||
def _test_set_access(self, im, color) -> None:
|
||||
def _test_set_access(self, im: Image.Image, color: tuple[int, ...] | float) -> None:
|
||||
"""Are we writing the correct bits into the image?
|
||||
|
||||
Using private interfaces, forcing a capi access and
|
||||
|
@ -359,7 +364,7 @@ class TestCffi(AccessTest):
|
|||
assert px[i, 0] == 0
|
||||
|
||||
@pytest.mark.parametrize("mode", ("P", "PA"))
|
||||
def test_p_putpixel_rgb_rgba(self, mode) -> None:
|
||||
def test_p_putpixel_rgb_rgba(self, mode: str) -> None:
|
||||
for color in ((255, 0, 0), (255, 0, 0, 127 if mode == "PA" else 255)):
|
||||
im = Image.new(mode, (1, 1))
|
||||
with pytest.warns(DeprecationWarning):
|
||||
|
@ -377,7 +382,7 @@ class TestImagePutPixelError(AccessTest):
|
|||
INVALID_TYPES = ["foo", 1.0, None]
|
||||
|
||||
@pytest.mark.parametrize("mode", IMAGE_MODES1)
|
||||
def test_putpixel_type_error1(self, mode) -> None:
|
||||
def test_putpixel_type_error1(self, mode: str) -> None:
|
||||
im = hopper(mode)
|
||||
for v in self.INVALID_TYPES:
|
||||
with pytest.raises(TypeError, match="color must be int or tuple"):
|
||||
|
@ -400,14 +405,16 @@ class TestImagePutPixelError(AccessTest):
|
|||
),
|
||||
),
|
||||
)
|
||||
def test_putpixel_invalid_number_of_bands(self, mode, band_numbers, match) -> None:
|
||||
def test_putpixel_invalid_number_of_bands(
|
||||
self, mode: str, band_numbers: tuple[int, ...], match: str
|
||||
) -> None:
|
||||
im = hopper(mode)
|
||||
for band_number in band_numbers:
|
||||
with pytest.raises(TypeError, match=match):
|
||||
im.putpixel((0, 0), (0,) * band_number)
|
||||
|
||||
@pytest.mark.parametrize("mode", IMAGE_MODES2)
|
||||
def test_putpixel_type_error2(self, mode) -> None:
|
||||
def test_putpixel_type_error2(self, mode: str) -> None:
|
||||
im = hopper(mode)
|
||||
for v in self.INVALID_TYPES:
|
||||
with pytest.raises(
|
||||
|
@ -416,7 +423,7 @@ class TestImagePutPixelError(AccessTest):
|
|||
im.putpixel((0, 0), v)
|
||||
|
||||
@pytest.mark.parametrize("mode", IMAGE_MODES1 + IMAGE_MODES2)
|
||||
def test_putpixel_overflow_error(self, mode) -> None:
|
||||
def test_putpixel_overflow_error(self, mode: str) -> None:
|
||||
im = hopper(mode)
|
||||
with pytest.raises(OverflowError):
|
||||
im.putpixel((0, 0), 2**80)
|
||||
|
@ -428,7 +435,7 @@ class TestEmbeddable:
|
|||
def test_embeddable(self) -> None:
|
||||
import ctypes
|
||||
|
||||
from setuptools.command.build_ext import new_compiler
|
||||
from setuptools.command import build_ext
|
||||
|
||||
with open("embed_pil.c", "w", encoding="utf-8") as fh:
|
||||
fh.write(
|
||||
|
@ -457,7 +464,7 @@ int main(int argc, char* argv[])
|
|||
% sys.prefix.replace("\\", "\\\\")
|
||||
)
|
||||
|
||||
compiler = new_compiler()
|
||||
compiler = getattr(build_ext, "new_compiler")()
|
||||
compiler.add_include_dir(sysconfig.get_config_var("INCLUDEPY"))
|
||||
|
||||
libdir = sysconfig.get_config_var("LIBDIR") or sysconfig.get_config_var(
|
||||
|
@ -471,7 +478,7 @@ int main(int argc, char* argv[])
|
|||
env["PATH"] = sys.prefix + ";" + env["PATH"]
|
||||
|
||||
# do not display the Windows Error Reporting dialog
|
||||
ctypes.windll.kernel32.SetErrorMode(0x0002)
|
||||
getattr(ctypes, "windll").kernel32.SetErrorMode(0x0002)
|
||||
|
||||
process = subprocess.Popen(["embed_pil.exe"], env=env)
|
||||
process.communicate()
|
||||
|
|
|
@ -1,5 +1,7 @@
|
|||
from __future__ import annotations
|
||||
|
||||
from typing import Any
|
||||
|
||||
import pytest
|
||||
from packaging.version import parse as parse_version
|
||||
|
||||
|
@ -13,7 +15,7 @@ im = hopper().resize((128, 100))
|
|||
|
||||
|
||||
def test_toarray() -> None:
|
||||
def test(mode):
|
||||
def test(mode: str) -> tuple[tuple[int, ...], str, int]:
|
||||
ai = numpy.array(im.convert(mode))
|
||||
return ai.shape, ai.dtype.str, ai.nbytes
|
||||
|
||||
|
@ -50,14 +52,14 @@ def test_fromarray() -> None:
|
|||
class Wrapper:
|
||||
"""Class with API matching Image.fromarray"""
|
||||
|
||||
def __init__(self, img, arr_params) -> None:
|
||||
def __init__(self, img: Image.Image, arr_params: dict[str, Any]) -> None:
|
||||
self.img = img
|
||||
self.__array_interface__ = arr_params
|
||||
|
||||
def tobytes(self):
|
||||
def tobytes(self) -> bytes:
|
||||
return self.img.tobytes()
|
||||
|
||||
def test(mode):
|
||||
def test(mode: str) -> tuple[str, tuple[int, int], bool]:
|
||||
i = im.convert(mode)
|
||||
a = numpy.array(i)
|
||||
# Make wrapper instance for image, new array interface
|
||||
|
|
|
@ -7,7 +7,12 @@ from .helper import fromstring, skip_unless_feature, tostring
|
|||
pytestmark = skip_unless_feature("jpg")
|
||||
|
||||
|
||||
def draft_roundtrip(in_mode, in_size, req_mode, req_size):
|
||||
def draft_roundtrip(
|
||||
in_mode: str,
|
||||
in_size: tuple[int, int],
|
||||
req_mode: str | None,
|
||||
req_size: tuple[int, int] | None,
|
||||
) -> Image.Image:
|
||||
im = Image.new(in_mode, in_size)
|
||||
data = tostring(im, "JPEG")
|
||||
im = fromstring(data)
|
||||
|
|
|
@ -4,7 +4,7 @@ from .helper import hopper
|
|||
|
||||
|
||||
def test_entropy() -> None:
|
||||
def entropy(mode):
|
||||
def entropy(mode: str) -> float:
|
||||
return hopper(mode).entropy()
|
||||
|
||||
assert round(abs(entropy("1") - 0.9138803254693582), 7) == 0
|
||||
|
|
|
@ -36,7 +36,7 @@ from .helper import assert_image_equal, hopper
|
|||
),
|
||||
)
|
||||
@pytest.mark.parametrize("mode", ("L", "I", "RGB", "CMYK"))
|
||||
def test_sanity(filter_to_apply, mode) -> None:
|
||||
def test_sanity(filter_to_apply: ImageFilter.Filter, mode: str) -> None:
|
||||
im = hopper(mode)
|
||||
if mode != "I" or isinstance(filter_to_apply, ImageFilter.BuiltinFilter):
|
||||
out = im.filter(filter_to_apply)
|
||||
|
@ -45,7 +45,7 @@ def test_sanity(filter_to_apply, mode) -> None:
|
|||
|
||||
|
||||
@pytest.mark.parametrize("mode", ("L", "I", "RGB", "CMYK"))
|
||||
def test_sanity_error(mode) -> None:
|
||||
def test_sanity_error(mode: str) -> None:
|
||||
with pytest.raises(TypeError):
|
||||
im = hopper(mode)
|
||||
im.filter("hello")
|
||||
|
@ -53,7 +53,7 @@ def test_sanity_error(mode) -> None:
|
|||
|
||||
# crashes on small images
|
||||
@pytest.mark.parametrize("size", ((1, 1), (2, 2), (3, 3)))
|
||||
def test_crash(size) -> None:
|
||||
def test_crash(size: tuple[int, int]) -> None:
|
||||
im = Image.new("RGB", size)
|
||||
im.filter(ImageFilter.SMOOTH)
|
||||
|
||||
|
@ -67,7 +67,10 @@ def test_crash(size) -> None:
|
|||
("RGB", ((4, 0, 0), (0, 0, 0))),
|
||||
),
|
||||
)
|
||||
def test_modefilter(mode, expected) -> None:
|
||||
def test_modefilter(
|
||||
mode: str,
|
||||
expected: tuple[int, int] | tuple[tuple[int, int, int], tuple[int, int, int]],
|
||||
) -> None:
|
||||
im = Image.new(mode, (3, 3), None)
|
||||
im.putdata(list(range(9)))
|
||||
# image is:
|
||||
|
@ -90,7 +93,13 @@ def test_modefilter(mode, expected) -> None:
|
|||
("F", (0.0, 4.0, 8.0)),
|
||||
),
|
||||
)
|
||||
def test_rankfilter(mode, expected) -> None:
|
||||
def test_rankfilter(
|
||||
mode: str,
|
||||
expected: (
|
||||
tuple[float, float, float]
|
||||
| tuple[tuple[int, int, int], tuple[int, int, int], tuple[int, int, int]]
|
||||
),
|
||||
) -> None:
|
||||
im = Image.new(mode, (3, 3), None)
|
||||
im.putdata(list(range(9)))
|
||||
# image is:
|
||||
|
@ -106,7 +115,7 @@ def test_rankfilter(mode, expected) -> None:
|
|||
@pytest.mark.parametrize(
|
||||
"filter", (ImageFilter.MinFilter, ImageFilter.MedianFilter, ImageFilter.MaxFilter)
|
||||
)
|
||||
def test_rankfilter_error(filter) -> None:
|
||||
def test_rankfilter_error(filter: ImageFilter.RankFilter) -> None:
|
||||
with pytest.raises(ValueError):
|
||||
im = Image.new("P", (3, 3), None)
|
||||
im.putdata(list(range(9)))
|
||||
|
@ -137,7 +146,7 @@ def test_kernel_not_enough_coefficients() -> None:
|
|||
|
||||
|
||||
@pytest.mark.parametrize("mode", ("L", "LA", "I", "RGB", "CMYK"))
|
||||
def test_consistency_3x3(mode) -> None:
|
||||
def test_consistency_3x3(mode: str) -> None:
|
||||
with Image.open("Tests/images/hopper.bmp") as source:
|
||||
reference_name = "hopper_emboss"
|
||||
reference_name += "_I.png" if mode == "I" else ".bmp"
|
||||
|
@ -163,7 +172,7 @@ def test_consistency_3x3(mode) -> None:
|
|||
|
||||
|
||||
@pytest.mark.parametrize("mode", ("L", "LA", "I", "RGB", "CMYK"))
|
||||
def test_consistency_5x5(mode) -> None:
|
||||
def test_consistency_5x5(mode: str) -> None:
|
||||
with Image.open("Tests/images/hopper.bmp") as source:
|
||||
reference_name = "hopper_emboss_more"
|
||||
reference_name += "_I.png" if mode == "I" else ".bmp"
|
||||
|
@ -199,7 +208,7 @@ def test_consistency_5x5(mode) -> None:
|
|||
(2, -2),
|
||||
),
|
||||
)
|
||||
def test_invalid_box_blur_filter(radius) -> None:
|
||||
def test_invalid_box_blur_filter(radius: int | tuple[int, int]) -> None:
|
||||
with pytest.raises(ValueError):
|
||||
ImageFilter.BoxBlur(radius)
|
||||
|
||||
|
|
|
@ -6,7 +6,7 @@ from .helper import hopper
|
|||
|
||||
|
||||
def test_extrema() -> None:
|
||||
def extrema(mode):
|
||||
def extrema(mode: str) -> tuple[int, int] | tuple[tuple[int, int], ...]:
|
||||
return hopper(mode).getextrema()
|
||||
|
||||
assert extrema("1") == (0, 255)
|
||||
|
|
|
@ -6,7 +6,7 @@ from .helper import hopper
|
|||
|
||||
|
||||
def test_palette() -> None:
|
||||
def palette(mode):
|
||||
def palette(mode: str) -> list[int] | None:
|
||||
p = hopper(mode).getpalette()
|
||||
if p:
|
||||
return p[:10]
|
||||
|
|
|
@ -46,7 +46,7 @@ class TestImagingPaste:
|
|||
self.assert_9points_image(im, expected)
|
||||
|
||||
@CachedProperty
|
||||
def mask_1(self):
|
||||
def mask_1(self) -> Image.Image:
|
||||
mask = Image.new("1", (self.size, self.size))
|
||||
px = mask.load()
|
||||
for y in range(mask.height):
|
||||
|
@ -55,11 +55,11 @@ class TestImagingPaste:
|
|||
return mask
|
||||
|
||||
@CachedProperty
|
||||
def mask_L(self):
|
||||
def mask_L(self) -> Image.Image:
|
||||
return self.gradient_L.transpose(Image.Transpose.ROTATE_270)
|
||||
|
||||
@CachedProperty
|
||||
def gradient_L(self):
|
||||
def gradient_L(self) -> Image.Image:
|
||||
gradient = Image.new("L", (self.size, self.size))
|
||||
px = gradient.load()
|
||||
for y in range(gradient.height):
|
||||
|
@ -68,7 +68,7 @@ class TestImagingPaste:
|
|||
return gradient
|
||||
|
||||
@CachedProperty
|
||||
def gradient_RGB(self):
|
||||
def gradient_RGB(self) -> Image.Image:
|
||||
return Image.merge(
|
||||
"RGB",
|
||||
[
|
||||
|
@ -79,7 +79,7 @@ class TestImagingPaste:
|
|||
)
|
||||
|
||||
@CachedProperty
|
||||
def gradient_LA(self):
|
||||
def gradient_LA(self) -> Image.Image:
|
||||
return Image.merge(
|
||||
"LA",
|
||||
[
|
||||
|
@ -89,7 +89,7 @@ class TestImagingPaste:
|
|||
)
|
||||
|
||||
@CachedProperty
|
||||
def gradient_RGBA(self):
|
||||
def gradient_RGBA(self) -> Image.Image:
|
||||
return Image.merge(
|
||||
"RGBA",
|
||||
[
|
||||
|
@ -101,7 +101,7 @@ class TestImagingPaste:
|
|||
)
|
||||
|
||||
@CachedProperty
|
||||
def gradient_RGBa(self):
|
||||
def gradient_RGBa(self) -> Image.Image:
|
||||
return Image.merge(
|
||||
"RGBa",
|
||||
[
|
||||
|
|
|
@ -31,7 +31,7 @@ def test_sanity() -> None:
|
|||
|
||||
def test_long_integers() -> None:
|
||||
# see bug-200802-systemerror
|
||||
def put(value):
|
||||
def put(value: int) -> tuple[int, int, int, int]:
|
||||
im = Image.new("RGBA", (1, 1))
|
||||
im.putdata([value])
|
||||
return im.getpixel((0, 0))
|
||||
|
@ -58,7 +58,7 @@ def test_mode_with_L_with_float() -> None:
|
|||
|
||||
|
||||
@pytest.mark.parametrize("mode", ("I", "I;16", "I;16L", "I;16B"))
|
||||
def test_mode_i(mode) -> None:
|
||||
def test_mode_i(mode: str) -> None:
|
||||
src = hopper("L")
|
||||
data = list(src.getdata())
|
||||
im = Image.new(mode, src.size, 0)
|
||||
|
@ -79,7 +79,7 @@ def test_mode_F() -> None:
|
|||
|
||||
|
||||
@pytest.mark.parametrize("mode", ("BGR;15", "BGR;16", "BGR;24"))
|
||||
def test_mode_BGR(mode) -> None:
|
||||
def test_mode_BGR(mode: str) -> None:
|
||||
data = [(16, 32, 49), (32, 32, 98)]
|
||||
im = Image.new(mode, (1, 2))
|
||||
im.putdata(data)
|
||||
|
|
|
@ -8,7 +8,7 @@ from .helper import assert_image_equal, assert_image_equal_tofile, hopper
|
|||
|
||||
|
||||
def test_putpalette() -> None:
|
||||
def palette(mode):
|
||||
def palette(mode: str) -> str | tuple[str, list[int]]:
|
||||
im = hopper(mode).copy()
|
||||
im.putpalette(list(range(256)) * 3)
|
||||
p = im.getpalette()
|
||||
|
@ -81,7 +81,7 @@ def test_putpalette_with_alpha_values() -> None:
|
|||
("RGBAX", (1, 2, 3, 4, 0)),
|
||||
),
|
||||
)
|
||||
def test_rgba_palette(mode, palette) -> None:
|
||||
def test_rgba_palette(mode: str, palette: tuple[int, ...]) -> None:
|
||||
im = Image.new("P", (1, 1))
|
||||
im.putpalette(palette, mode)
|
||||
assert im.getpalette() == [1, 2, 3]
|
||||
|
|
|
@ -231,11 +231,13 @@ class TestImagingCoreResampleAccuracy:
|
|||
|
||||
|
||||
class TestCoreResampleConsistency:
|
||||
def make_case(self, mode: str, fill: tuple[int, int, int] | float):
|
||||
def make_case(
|
||||
self, mode: str, fill: tuple[int, int, int] | float
|
||||
) -> tuple[Image.Image, tuple[int, ...]]:
|
||||
im = Image.new(mode, (512, 9), fill)
|
||||
return im.resize((9, 512), Image.Resampling.LANCZOS), im.load()[0, 0]
|
||||
|
||||
def run_case(self, case) -> None:
|
||||
def run_case(self, case: tuple[Image.Image, Image.Image]) -> None:
|
||||
channel, color = case
|
||||
px = channel.load()
|
||||
for x in range(channel.size[0]):
|
||||
|
@ -353,7 +355,7 @@ class TestCoreResampleAlphaCorrect:
|
|||
|
||||
class TestCoreResamplePasses:
|
||||
@contextmanager
|
||||
def count(self, diff):
|
||||
def count(self, diff: int) -> Generator[None, None, None]:
|
||||
count = Image.core.get_stats()["new_count"]
|
||||
yield
|
||||
assert Image.core.get_stats()["new_count"] - count == diff
|
||||
|
|
|
@ -12,7 +12,13 @@ from .helper import (
|
|||
)
|
||||
|
||||
|
||||
def rotate(im, mode, angle, center=None, translate=None) -> None:
|
||||
def rotate(
|
||||
im: Image.Image,
|
||||
mode: str,
|
||||
angle: int,
|
||||
center: tuple[int, int] | None = None,
|
||||
translate: tuple[int, int] | None = None,
|
||||
) -> None:
|
||||
out = im.rotate(angle, center=center, translate=translate)
|
||||
assert out.mode == mode
|
||||
assert out.size == im.size # default rotate clips output
|
||||
|
@ -27,13 +33,13 @@ def rotate(im, mode, angle, center=None, translate=None) -> None:
|
|||
|
||||
|
||||
@pytest.mark.parametrize("mode", ("1", "P", "L", "RGB", "I", "F"))
|
||||
def test_mode(mode) -> None:
|
||||
def test_mode(mode: str) -> None:
|
||||
im = hopper(mode)
|
||||
rotate(im, mode, 45)
|
||||
|
||||
|
||||
@pytest.mark.parametrize("angle", (0, 90, 180, 270))
|
||||
def test_angle(angle) -> None:
|
||||
def test_angle(angle: int) -> None:
|
||||
with Image.open("Tests/images/test-card.png") as im:
|
||||
rotate(im, im.mode, angle)
|
||||
|
||||
|
@ -42,7 +48,7 @@ def test_angle(angle) -> None:
|
|||
|
||||
|
||||
@pytest.mark.parametrize("angle", (0, 45, 90, 180, 270))
|
||||
def test_zero(angle) -> None:
|
||||
def test_zero(angle: int) -> None:
|
||||
im = Image.new("RGB", (0, 0))
|
||||
rotate(im, im.mode, angle)
|
||||
|
||||
|
|
|
@ -111,7 +111,7 @@ def test_load_first_unless_jpeg() -> None:
|
|||
with Image.open("Tests/images/hopper.jpg") as im:
|
||||
draft = im.draft
|
||||
|
||||
def im_draft(mode, size):
|
||||
def im_draft(mode: str, size: tuple[int, int]):
|
||||
result = draft(mode, size)
|
||||
assert result is not None
|
||||
|
||||
|
|
|
@ -1,6 +1,7 @@
|
|||
from __future__ import annotations
|
||||
|
||||
import math
|
||||
from typing import Callable
|
||||
|
||||
import pytest
|
||||
|
||||
|
@ -91,7 +92,7 @@ class TestImageTransform:
|
|||
("LA", (76, 0)),
|
||||
),
|
||||
)
|
||||
def test_fill(self, mode, expected_pixel) -> None:
|
||||
def test_fill(self, mode: str, expected_pixel: tuple[int, ...]) -> None:
|
||||
im = hopper(mode)
|
||||
(w, h) = im.size
|
||||
transformed = im.transform(
|
||||
|
@ -142,7 +143,9 @@ class TestImageTransform:
|
|||
assert_image_equal(blank, transformed.crop((w // 2, 0, w, h // 2)))
|
||||
assert_image_equal(blank, transformed.crop((0, h // 2, w // 2, h)))
|
||||
|
||||
def _test_alpha_premult(self, op) -> None:
|
||||
def _test_alpha_premult(
|
||||
self, op: Callable[[Image.Image, tuple[int, int]], Image.Image]
|
||||
) -> None:
|
||||
# create image with half white, half black,
|
||||
# with the black half transparent.
|
||||
# do op,
|
||||
|
@ -159,13 +162,13 @@ class TestImageTransform:
|
|||
assert 40 * 10 == hist[-1]
|
||||
|
||||
def test_alpha_premult_resize(self) -> None:
|
||||
def op(im, sz):
|
||||
def op(im: Image.Image, sz: tuple[int, int]) -> Image.Image:
|
||||
return im.resize(sz, Image.Resampling.BILINEAR)
|
||||
|
||||
self._test_alpha_premult(op)
|
||||
|
||||
def test_alpha_premult_transform(self) -> None:
|
||||
def op(im, sz):
|
||||
def op(im: Image.Image, sz: tuple[int, int]) -> Image.Image:
|
||||
(w, h) = im.size
|
||||
return im.transform(
|
||||
sz, Image.Transform.EXTENT, (0, 0, w, h), Image.Resampling.BILINEAR
|
||||
|
@ -173,7 +176,9 @@ class TestImageTransform:
|
|||
|
||||
self._test_alpha_premult(op)
|
||||
|
||||
def _test_nearest(self, op, mode) -> None:
|
||||
def _test_nearest(
|
||||
self, op: Callable[[Image.Image, tuple[int, int]], Image.Image], mode: str
|
||||
) -> None:
|
||||
# create white image with half transparent,
|
||||
# do op,
|
||||
# the image should remain white with half transparent
|
||||
|
@ -196,15 +201,15 @@ class TestImageTransform:
|
|||
)
|
||||
|
||||
@pytest.mark.parametrize("mode", ("RGBA", "LA"))
|
||||
def test_nearest_resize(self, mode) -> None:
|
||||
def op(im, sz):
|
||||
def test_nearest_resize(self, mode: str) -> None:
|
||||
def op(im: Image.Image, sz: tuple[int, int]) -> Image.Image:
|
||||
return im.resize(sz, Image.Resampling.NEAREST)
|
||||
|
||||
self._test_nearest(op, mode)
|
||||
|
||||
@pytest.mark.parametrize("mode", ("RGBA", "LA"))
|
||||
def test_nearest_transform(self, mode) -> None:
|
||||
def op(im, sz):
|
||||
def test_nearest_transform(self, mode: str) -> None:
|
||||
def op(im: Image.Image, sz: tuple[int, int]) -> Image.Image:
|
||||
(w, h) = im.size
|
||||
return im.transform(
|
||||
sz, Image.Transform.EXTENT, (0, 0, w, h), Image.Resampling.NEAREST
|
||||
|
@ -227,7 +232,9 @@ class TestImageTransform:
|
|||
# Running by default, but I'd totally understand not doing it in
|
||||
# the future
|
||||
|
||||
pattern = [Image.new("RGBA", (1024, 1024), (a, a, a, a)) for a in range(1, 65)]
|
||||
pattern: list[Image.Image] | None = [
|
||||
Image.new("RGBA", (1024, 1024), (a, a, a, a)) for a in range(1, 65)
|
||||
]
|
||||
|
||||
# Yeah. Watch some JIT optimize this out.
|
||||
pattern = None # noqa: F841
|
||||
|
@ -240,7 +247,7 @@ class TestImageTransform:
|
|||
im.transform((100, 100), None)
|
||||
|
||||
@pytest.mark.parametrize("resample", (Image.Resampling.BOX, "unknown"))
|
||||
def test_unknown_resampling_filter(self, resample) -> None:
|
||||
def test_unknown_resampling_filter(self, resample: Image.Resampling | str) -> None:
|
||||
with hopper() as im:
|
||||
(w, h) = im.size
|
||||
with pytest.raises(ValueError):
|
||||
|
@ -250,7 +257,7 @@ class TestImageTransform:
|
|||
class TestImageTransformAffine:
|
||||
transform = Image.Transform.AFFINE
|
||||
|
||||
def _test_image(self):
|
||||
def _test_image(self) -> Image.Image:
|
||||
im = hopper("RGB")
|
||||
return im.crop((10, 20, im.width - 10, im.height - 20))
|
||||
|
||||
|
@ -263,7 +270,7 @@ class TestImageTransformAffine:
|
|||
(270, Image.Transpose.ROTATE_270),
|
||||
),
|
||||
)
|
||||
def test_rotate(self, deg, transpose) -> None:
|
||||
def test_rotate(self, deg: int, transpose: Image.Transpose | None) -> None:
|
||||
im = self._test_image()
|
||||
|
||||
angle = -math.radians(deg)
|
||||
|
@ -313,7 +320,13 @@ class TestImageTransformAffine:
|
|||
(Image.Resampling.BICUBIC, 1),
|
||||
),
|
||||
)
|
||||
def test_resize(self, scale, epsilon_scale, resample, epsilon) -> None:
|
||||
def test_resize(
|
||||
self,
|
||||
scale: float,
|
||||
epsilon_scale: float,
|
||||
resample: Image.Resampling,
|
||||
epsilon: int,
|
||||
) -> None:
|
||||
im = self._test_image()
|
||||
|
||||
size_up = int(round(im.width * scale)), int(round(im.height * scale))
|
||||
|
@ -342,7 +355,14 @@ class TestImageTransformAffine:
|
|||
(Image.Resampling.BICUBIC, 1),
|
||||
),
|
||||
)
|
||||
def test_translate(self, x, y, epsilon_scale, resample, epsilon) -> None:
|
||||
def test_translate(
|
||||
self,
|
||||
x: float,
|
||||
y: float,
|
||||
epsilon_scale: float,
|
||||
resample: Image.Resampling,
|
||||
epsilon: float,
|
||||
) -> None:
|
||||
im = self._test_image()
|
||||
|
||||
size_up = int(round(im.width + x)), int(round(im.height + y))
|
||||
|
|
Loading…
Reference in New Issue
Block a user