Skip to content
Merged
Show file tree
Hide file tree
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion Tests/helper.py
Original file line number Diff line number Diff line change
Expand Up @@ -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()
Expand Down
47 changes: 27 additions & 20 deletions Tests/test_image_access.py
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@
import subprocess
import sys
import sysconfig
from types import ModuleType

import pytest

Expand All @@ -23,6 +24,7 @@
except ImportError:
cffi = None

numpy: ModuleType | None
try:
import numpy
except ImportError:
Expand Down Expand Up @@ -71,9 +73,10 @@ def test_sanity(self) -> None:
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]):
Expand Down Expand Up @@ -123,12 +126,13 @@ def test_numpy(self) -> None:
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
Expand All @@ -138,12 +142,13 @@ def color(mode):
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 = (
expected_color_int if expected_color_int is not None else self.color(mode)
)

# check putpixel
im = Image.new(mode, (1, 1), None)
Expand Down Expand Up @@ -222,7 +227,7 @@ def check(self, mode, expected_color=None) -> None:
"YCbCr",
),
)
def test_basic(self, mode) -> None:
def test_basic(self, mode: str) -> None:
self.check(mode)

def test_list(self) -> None:
Expand All @@ -231,14 +236,14 @@ def test_list(self) -> None:

@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)

Expand All @@ -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
Expand Down Expand Up @@ -299,7 +304,7 @@ def test_get_vs_c(self) -> None:
# 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
Expand Down Expand Up @@ -359,7 +364,7 @@ def test_reference_counting(self) -> None:
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):
Expand All @@ -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"):
Expand All @@ -400,14 +405,16 @@ def test_putpixel_type_error1(self, mode) -> None:
),
),
)
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(
Expand All @@ -416,7 +423,7 @@ def test_putpixel_type_error2(self, mode) -> None:
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)
Expand All @@ -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(
Expand Down Expand Up @@ -457,7 +464,7 @@ def test_embeddable(self) -> None:
% 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(
Expand All @@ -471,7 +478,7 @@ def test_embeddable(self) -> None:
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()
Expand Down
10 changes: 6 additions & 4 deletions Tests/test_image_array.py
Original file line number Diff line number Diff line change
@@ -1,5 +1,7 @@
from __future__ import annotations

from typing import Any

import pytest
from packaging.version import parse as parse_version

Expand All @@ -13,7 +15,7 @@


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

Expand Down Expand Up @@ -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
Expand Down
7 changes: 6 additions & 1 deletion Tests/test_image_draft.py
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,12 @@
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)
Expand Down
2 changes: 1 addition & 1 deletion Tests/test_image_entropy.py
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@


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
Expand Down
27 changes: 18 additions & 9 deletions Tests/test_image_filter.py
Original file line number Diff line number Diff line change
Expand Up @@ -36,7 +36,7 @@
),
)
@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)
Expand All @@ -45,15 +45,15 @@ 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")


# 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)

Expand All @@ -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:
Expand All @@ -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:
Expand All @@ -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)))
Expand Down Expand Up @@ -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"
Expand All @@ -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"
Expand Down Expand Up @@ -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)

Expand Down
2 changes: 1 addition & 1 deletion Tests/test_image_getextrema.py
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@


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)
Expand Down
2 changes: 1 addition & 1 deletion Tests/test_image_getpalette.py
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@


def test_palette() -> None:
def palette(mode):
def palette(mode: str) -> list[int] | None:
p = hopper(mode).getpalette()
if p:
return p[:10]
Expand Down
Loading