mirror of
https://github.com/python-pillow/Pillow.git
synced 2024-12-26 01:46:18 +03:00
Added type hints to tests (#8203)
Co-authored-by: Andrew Murray <radarhere@users.noreply.github.com>
This commit is contained in:
parent
f3c3e52797
commit
4aa24f88d9
|
@ -60,9 +60,7 @@ def convert_to_comparable(
|
||||||
return new_a, new_b
|
return new_a, new_b
|
||||||
|
|
||||||
|
|
||||||
def assert_deep_equal(
|
def assert_deep_equal(a: Any, b: Any, msg: str | None = None) -> None:
|
||||||
a: Sequence[Any], b: Sequence[Any], msg: str | None = None
|
|
||||||
) -> None:
|
|
||||||
try:
|
try:
|
||||||
assert len(a) == len(b), msg or f"got length {len(a)}, expected {len(b)}"
|
assert len(a) == len(b), msg or f"got length {len(a)}, expected {len(b)}"
|
||||||
except Exception:
|
except Exception:
|
||||||
|
|
|
@ -1048,7 +1048,11 @@ class TestFileLibTiff(LibTiffTestCase):
|
||||||
],
|
],
|
||||||
)
|
)
|
||||||
def test_wrong_bits_per_sample(
|
def test_wrong_bits_per_sample(
|
||||||
self, file_name: str, mode: str, size: tuple[int, int], tile
|
self,
|
||||||
|
file_name: str,
|
||||||
|
mode: str,
|
||||||
|
size: tuple[int, int],
|
||||||
|
tile: list[tuple[str, tuple[int, int, int, int], int, tuple[Any, ...]]],
|
||||||
) -> None:
|
) -> None:
|
||||||
with Image.open("Tests/images/" + file_name) as im:
|
with Image.open("Tests/images/" + file_name) as im:
|
||||||
assert im.mode == mode
|
assert im.mode == mode
|
||||||
|
|
|
@ -1,5 +1,6 @@
|
||||||
from __future__ import annotations
|
from __future__ import annotations
|
||||||
|
|
||||||
|
from collections.abc import Generator
|
||||||
from pathlib import Path
|
from pathlib import Path
|
||||||
|
|
||||||
import pytest
|
import pytest
|
||||||
|
@ -96,7 +97,9 @@ def test_write_animation_RGB(tmp_path: Path) -> None:
|
||||||
check(temp_file1)
|
check(temp_file1)
|
||||||
|
|
||||||
# Tests appending using a generator
|
# Tests appending using a generator
|
||||||
def im_generator(ims):
|
def im_generator(
|
||||||
|
ims: list[Image.Image],
|
||||||
|
) -> Generator[Image.Image, None, None]:
|
||||||
yield from ims
|
yield from ims
|
||||||
|
|
||||||
temp_file2 = str(tmp_path / "temp_generator.webp")
|
temp_file2 = str(tmp_path / "temp_generator.webp")
|
||||||
|
|
|
@ -372,8 +372,9 @@ class TestImage:
|
||||||
img = Image.alpha_composite(dst, src)
|
img = Image.alpha_composite(dst, src)
|
||||||
|
|
||||||
# Assert
|
# Assert
|
||||||
img_colors = sorted(img.getcolors())
|
img_colors = img.getcolors()
|
||||||
assert img_colors == expected_colors
|
assert img_colors is not None
|
||||||
|
assert sorted(img_colors) == expected_colors
|
||||||
|
|
||||||
def test_alpha_inplace(self) -> None:
|
def test_alpha_inplace(self) -> None:
|
||||||
src = Image.new("RGBA", (128, 128), "blue")
|
src = Image.new("RGBA", (128, 128), "blue")
|
||||||
|
@ -670,7 +671,9 @@ class TestImage:
|
||||||
|
|
||||||
im_remapped = im.remap_palette([1, 0])
|
im_remapped = im.remap_palette([1, 0])
|
||||||
assert im_remapped.info["transparency"] == 1
|
assert im_remapped.info["transparency"] == 1
|
||||||
assert len(im_remapped.getpalette()) == 6
|
palette = im_remapped.getpalette()
|
||||||
|
assert palette is not None
|
||||||
|
assert len(palette) == 6
|
||||||
|
|
||||||
# Test unused transparency
|
# Test unused transparency
|
||||||
im.info["transparency"] = 2
|
im.info["transparency"] = 2
|
||||||
|
|
|
@ -27,7 +27,9 @@ class TestImagePutPixel:
|
||||||
for y in range(im1.size[1]):
|
for y in range(im1.size[1]):
|
||||||
for x in range(im1.size[0]):
|
for x in range(im1.size[0]):
|
||||||
pos = x, y
|
pos = x, y
|
||||||
im2.putpixel(pos, im1.getpixel(pos))
|
value = im1.getpixel(pos)
|
||||||
|
assert value is not None
|
||||||
|
im2.putpixel(pos, value)
|
||||||
|
|
||||||
assert_image_equal(im1, im2)
|
assert_image_equal(im1, im2)
|
||||||
|
|
||||||
|
@ -37,7 +39,9 @@ class TestImagePutPixel:
|
||||||
for y in range(im1.size[1]):
|
for y in range(im1.size[1]):
|
||||||
for x in range(im1.size[0]):
|
for x in range(im1.size[0]):
|
||||||
pos = x, y
|
pos = x, y
|
||||||
im2.putpixel(pos, im1.getpixel(pos))
|
value = im1.getpixel(pos)
|
||||||
|
assert value is not None
|
||||||
|
im2.putpixel(pos, value)
|
||||||
|
|
||||||
assert not im2.readonly
|
assert not im2.readonly
|
||||||
assert_image_equal(im1, im2)
|
assert_image_equal(im1, im2)
|
||||||
|
@ -50,9 +54,9 @@ class TestImagePutPixel:
|
||||||
assert pix1 is not None
|
assert pix1 is not None
|
||||||
assert pix2 is not None
|
assert pix2 is not None
|
||||||
with pytest.raises(TypeError):
|
with pytest.raises(TypeError):
|
||||||
pix1[0, "0"]
|
pix1[0, "0"] # type: ignore[index]
|
||||||
with pytest.raises(TypeError):
|
with pytest.raises(TypeError):
|
||||||
pix1["0", 0]
|
pix1["0", 0] # type: ignore[index]
|
||||||
|
|
||||||
for y in range(im1.size[1]):
|
for y in range(im1.size[1]):
|
||||||
for x in range(im1.size[0]):
|
for x in range(im1.size[0]):
|
||||||
|
@ -71,7 +75,9 @@ class TestImagePutPixel:
|
||||||
for y in range(-1, -im1.size[1] - 1, -1):
|
for y in range(-1, -im1.size[1] - 1, -1):
|
||||||
for x in range(-1, -im1.size[0] - 1, -1):
|
for x in range(-1, -im1.size[0] - 1, -1):
|
||||||
pos = x, y
|
pos = x, y
|
||||||
im2.putpixel(pos, im1.getpixel(pos))
|
value = im1.getpixel(pos)
|
||||||
|
assert value is not None
|
||||||
|
im2.putpixel(pos, value)
|
||||||
|
|
||||||
assert_image_equal(im1, im2)
|
assert_image_equal(im1, im2)
|
||||||
|
|
||||||
|
@ -81,7 +87,9 @@ class TestImagePutPixel:
|
||||||
for y in range(-1, -im1.size[1] - 1, -1):
|
for y in range(-1, -im1.size[1] - 1, -1):
|
||||||
for x in range(-1, -im1.size[0] - 1, -1):
|
for x in range(-1, -im1.size[0] - 1, -1):
|
||||||
pos = x, y
|
pos = x, y
|
||||||
im2.putpixel(pos, im1.getpixel(pos))
|
value = im1.getpixel(pos)
|
||||||
|
assert value is not None
|
||||||
|
im2.putpixel(pos, value)
|
||||||
|
|
||||||
assert not im2.readonly
|
assert not im2.readonly
|
||||||
assert_image_equal(im1, im2)
|
assert_image_equal(im1, im2)
|
||||||
|
@ -219,7 +227,7 @@ class TestImagePutPixelError:
|
||||||
im = hopper(mode)
|
im = hopper(mode)
|
||||||
for v in self.INVALID_TYPES:
|
for v in self.INVALID_TYPES:
|
||||||
with pytest.raises(TypeError, match="color must be int or tuple"):
|
with pytest.raises(TypeError, match="color must be int or tuple"):
|
||||||
im.putpixel((0, 0), v)
|
im.putpixel((0, 0), v) # type: ignore[arg-type]
|
||||||
|
|
||||||
@pytest.mark.parametrize(
|
@pytest.mark.parametrize(
|
||||||
("mode", "band_numbers", "match"),
|
("mode", "band_numbers", "match"),
|
||||||
|
@ -253,7 +261,7 @@ class TestImagePutPixelError:
|
||||||
with pytest.raises(
|
with pytest.raises(
|
||||||
TypeError, match="color must be int or single-element tuple"
|
TypeError, match="color must be int or single-element tuple"
|
||||||
):
|
):
|
||||||
im.putpixel((0, 0), v)
|
im.putpixel((0, 0), v) # type: ignore[arg-type]
|
||||||
|
|
||||||
@pytest.mark.parametrize("mode", IMAGE_MODES1 + IMAGE_MODES2)
|
@pytest.mark.parametrize("mode", IMAGE_MODES1 + IMAGE_MODES2)
|
||||||
def test_putpixel_overflow_error(self, mode: str) -> None:
|
def test_putpixel_overflow_error(self, mode: str) -> None:
|
||||||
|
|
|
@ -225,7 +225,7 @@ def test_l_macro_rounding(convert_mode: str) -> None:
|
||||||
assert px is not None
|
assert px is not None
|
||||||
converted_color = px[0, 0]
|
converted_color = px[0, 0]
|
||||||
if convert_mode == "LA":
|
if convert_mode == "LA":
|
||||||
assert converted_color is not None
|
assert isinstance(converted_color, tuple)
|
||||||
converted_color = converted_color[0]
|
converted_color = converted_color[0]
|
||||||
assert converted_color == 1
|
assert converted_color == 1
|
||||||
|
|
||||||
|
|
|
@ -54,17 +54,21 @@ def test_pack() -> None:
|
||||||
assert A is None
|
assert A is None
|
||||||
|
|
||||||
A = im.getcolors(maxcolors=3)
|
A = im.getcolors(maxcolors=3)
|
||||||
|
assert A is not None
|
||||||
A.sort()
|
A.sort()
|
||||||
assert A == expected
|
assert A == expected
|
||||||
|
|
||||||
A = im.getcolors(maxcolors=4)
|
A = im.getcolors(maxcolors=4)
|
||||||
|
assert A is not None
|
||||||
A.sort()
|
A.sort()
|
||||||
assert A == expected
|
assert A == expected
|
||||||
|
|
||||||
A = im.getcolors(maxcolors=8)
|
A = im.getcolors(maxcolors=8)
|
||||||
|
assert A is not None
|
||||||
A.sort()
|
A.sort()
|
||||||
assert A == expected
|
assert A == expected
|
||||||
|
|
||||||
A = im.getcolors(maxcolors=16)
|
A = im.getcolors(maxcolors=16)
|
||||||
|
assert A is not None
|
||||||
A.sort()
|
A.sort()
|
||||||
assert A == expected
|
assert A == expected
|
||||||
|
|
|
@ -31,7 +31,7 @@ def test_sanity() -> None:
|
||||||
|
|
||||||
def test_long_integers() -> None:
|
def test_long_integers() -> None:
|
||||||
# see bug-200802-systemerror
|
# see bug-200802-systemerror
|
||||||
def put(value: int) -> tuple[int, int, int, int]:
|
def put(value: int) -> float | tuple[int, ...] | None:
|
||||||
im = Image.new("RGBA", (1, 1))
|
im = Image.new("RGBA", (1, 1))
|
||||||
im.putdata([value])
|
im.putdata([value])
|
||||||
return im.getpixel((0, 0))
|
return im.getpixel((0, 0))
|
||||||
|
|
|
@ -31,7 +31,9 @@ def test_libimagequant_quantize() -> None:
|
||||||
converted = image.quantize(100, Image.Quantize.LIBIMAGEQUANT)
|
converted = image.quantize(100, Image.Quantize.LIBIMAGEQUANT)
|
||||||
assert converted.mode == "P"
|
assert converted.mode == "P"
|
||||||
assert_image_similar(converted.convert("RGB"), image, 15)
|
assert_image_similar(converted.convert("RGB"), image, 15)
|
||||||
assert len(converted.getcolors()) == 100
|
colors = converted.getcolors()
|
||||||
|
assert colors is not None
|
||||||
|
assert len(colors) == 100
|
||||||
|
|
||||||
|
|
||||||
def test_octree_quantize() -> None:
|
def test_octree_quantize() -> None:
|
||||||
|
@ -39,7 +41,9 @@ def test_octree_quantize() -> None:
|
||||||
converted = image.quantize(100, Image.Quantize.FASTOCTREE)
|
converted = image.quantize(100, Image.Quantize.FASTOCTREE)
|
||||||
assert converted.mode == "P"
|
assert converted.mode == "P"
|
||||||
assert_image_similar(converted.convert("RGB"), image, 20)
|
assert_image_similar(converted.convert("RGB"), image, 20)
|
||||||
assert len(converted.getcolors()) == 100
|
colors = converted.getcolors()
|
||||||
|
assert colors is not None
|
||||||
|
assert len(colors) == 100
|
||||||
|
|
||||||
|
|
||||||
def test_rgba_quantize() -> None:
|
def test_rgba_quantize() -> None:
|
||||||
|
@ -158,4 +162,6 @@ def test_small_palette() -> None:
|
||||||
im = im.quantize(palette=p)
|
im = im.quantize(palette=p)
|
||||||
|
|
||||||
# Assert
|
# Assert
|
||||||
assert len(im.getcolors()) == 2
|
quantized_colors = im.getcolors()
|
||||||
|
assert quantized_colors is not None
|
||||||
|
assert len(quantized_colors) == 2
|
||||||
|
|
|
@ -237,13 +237,13 @@ class TestImagingCoreResampleAccuracy:
|
||||||
class TestCoreResampleConsistency:
|
class TestCoreResampleConsistency:
|
||||||
def make_case(
|
def make_case(
|
||||||
self, mode: str, fill: tuple[int, int, int] | float
|
self, mode: str, fill: tuple[int, int, int] | float
|
||||||
) -> tuple[Image.Image, tuple[int, ...]]:
|
) -> tuple[Image.Image, float | tuple[int, ...]]:
|
||||||
im = Image.new(mode, (512, 9), fill)
|
im = Image.new(mode, (512, 9), fill)
|
||||||
px = im.load()
|
px = im.load()
|
||||||
assert px is not None
|
assert px is not None
|
||||||
return im.resize((9, 512), Image.Resampling.LANCZOS), px[0, 0]
|
return im.resize((9, 512), Image.Resampling.LANCZOS), px[0, 0]
|
||||||
|
|
||||||
def run_case(self, case: tuple[Image.Image, int | tuple[int, ...]]) -> None:
|
def run_case(self, case: tuple[Image.Image, float | tuple[int, ...]]) -> None:
|
||||||
channel, color = case
|
channel, color = case
|
||||||
px = channel.load()
|
px = channel.load()
|
||||||
assert px is not None
|
assert px is not None
|
||||||
|
@ -256,6 +256,7 @@ class TestCoreResampleConsistency:
|
||||||
def test_8u(self) -> None:
|
def test_8u(self) -> None:
|
||||||
im, color = self.make_case("RGB", (0, 64, 255))
|
im, color = self.make_case("RGB", (0, 64, 255))
|
||||||
r, g, b = im.split()
|
r, g, b = im.split()
|
||||||
|
assert isinstance(color, tuple)
|
||||||
self.run_case((r, color[0]))
|
self.run_case((r, color[0]))
|
||||||
self.run_case((g, color[1]))
|
self.run_case((g, color[1]))
|
||||||
self.run_case((b, color[2]))
|
self.run_case((b, color[2]))
|
||||||
|
@ -290,7 +291,11 @@ class TestCoreResampleAlphaCorrect:
|
||||||
px = i.load()
|
px = i.load()
|
||||||
assert px is not None
|
assert px is not None
|
||||||
for y in range(i.size[1]):
|
for y in range(i.size[1]):
|
||||||
used_colors = {px[x, y][0] for x in range(i.size[0])}
|
used_colors = set()
|
||||||
|
for x in range(i.size[0]):
|
||||||
|
value = px[x, y]
|
||||||
|
assert isinstance(value, tuple)
|
||||||
|
used_colors.add(value[0])
|
||||||
assert 256 == len(used_colors), (
|
assert 256 == len(used_colors), (
|
||||||
"All colors should be present in resized image. "
|
"All colors should be present in resized image. "
|
||||||
f"Only {len(used_colors)} on line {y}."
|
f"Only {len(used_colors)} on line {y}."
|
||||||
|
@ -332,12 +337,13 @@ class TestCoreResampleAlphaCorrect:
|
||||||
assert px is not None
|
assert px is not None
|
||||||
for y in range(i.size[1]):
|
for y in range(i.size[1]):
|
||||||
for x in range(i.size[0]):
|
for x in range(i.size[0]):
|
||||||
if px[x, y][-1] != 0 and px[x, y][:-1] != clean_pixel:
|
value = px[x, y]
|
||||||
|
assert isinstance(value, tuple)
|
||||||
|
if value[-1] != 0 and value[:-1] != clean_pixel:
|
||||||
message = (
|
message = (
|
||||||
f"pixel at ({x}, {y}) is different:\n"
|
f"pixel at ({x}, {y}) is different:\n{value}\n{clean_pixel}"
|
||||||
f"{px[x, y]}\n{clean_pixel}"
|
|
||||||
)
|
)
|
||||||
assert px[x, y][:3] == clean_pixel, message
|
assert value[:3] == clean_pixel, message
|
||||||
|
|
||||||
def test_dirty_pixels_rgba(self) -> None:
|
def test_dirty_pixels_rgba(self) -> None:
|
||||||
case = self.make_dirty_case("RGBA", (255, 255, 0, 128), (0, 0, 255, 0))
|
case = self.make_dirty_case("RGBA", (255, 255, 0, 128), (0, 0, 255, 0))
|
||||||
|
|
|
@ -192,8 +192,9 @@ class TestImageTransform:
|
||||||
|
|
||||||
im = op(im, (40, 10))
|
im = op(im, (40, 10))
|
||||||
|
|
||||||
colors = sorted(im.getcolors())
|
colors = im.getcolors()
|
||||||
assert colors == sorted(
|
assert colors is not None
|
||||||
|
assert sorted(colors) == sorted(
|
||||||
(
|
(
|
||||||
(20 * 10, opaque),
|
(20 * 10, opaque),
|
||||||
(20 * 10, transparent),
|
(20 * 10, transparent),
|
||||||
|
|
|
@ -391,23 +391,25 @@ def test_overlay() -> None:
|
||||||
def test_logical() -> None:
|
def test_logical() -> None:
|
||||||
def table(
|
def table(
|
||||||
op: Callable[[Image.Image, Image.Image], Image.Image], a: int, b: int
|
op: Callable[[Image.Image, Image.Image], Image.Image], a: int, b: int
|
||||||
) -> tuple[int, int, int, int]:
|
) -> list[float]:
|
||||||
out = []
|
out = []
|
||||||
for x in (a, b):
|
for x in (a, b):
|
||||||
imx = Image.new("1", (1, 1), x)
|
imx = Image.new("1", (1, 1), x)
|
||||||
for y in (a, b):
|
for y in (a, b):
|
||||||
imy = Image.new("1", (1, 1), y)
|
imy = Image.new("1", (1, 1), y)
|
||||||
out.append(op(imx, imy).getpixel((0, 0)))
|
value = op(imx, imy).getpixel((0, 0))
|
||||||
return tuple(out)
|
assert not isinstance(value, tuple) and value is not None
|
||||||
|
out.append(value)
|
||||||
|
return out
|
||||||
|
|
||||||
assert table(ImageChops.logical_and, 0, 1) == (0, 0, 0, 255)
|
assert table(ImageChops.logical_and, 0, 1) == [0, 0, 0, 255]
|
||||||
assert table(ImageChops.logical_or, 0, 1) == (0, 255, 255, 255)
|
assert table(ImageChops.logical_or, 0, 1) == [0, 255, 255, 255]
|
||||||
assert table(ImageChops.logical_xor, 0, 1) == (0, 255, 255, 0)
|
assert table(ImageChops.logical_xor, 0, 1) == [0, 255, 255, 0]
|
||||||
|
|
||||||
assert table(ImageChops.logical_and, 0, 128) == (0, 0, 0, 255)
|
assert table(ImageChops.logical_and, 0, 128) == [0, 0, 0, 255]
|
||||||
assert table(ImageChops.logical_or, 0, 128) == (0, 255, 255, 255)
|
assert table(ImageChops.logical_or, 0, 128) == [0, 255, 255, 255]
|
||||||
assert table(ImageChops.logical_xor, 0, 128) == (0, 255, 255, 0)
|
assert table(ImageChops.logical_xor, 0, 128) == [0, 255, 255, 0]
|
||||||
|
|
||||||
assert table(ImageChops.logical_and, 0, 255) == (0, 0, 0, 255)
|
assert table(ImageChops.logical_and, 0, 255) == [0, 0, 0, 255]
|
||||||
assert table(ImageChops.logical_or, 0, 255) == (0, 255, 255, 255)
|
assert table(ImageChops.logical_or, 0, 255) == [0, 255, 255, 255]
|
||||||
assert table(ImageChops.logical_xor, 0, 255) == (0, 255, 255, 0)
|
assert table(ImageChops.logical_xor, 0, 255) == [0, 255, 255, 0]
|
||||||
|
|
|
@ -691,7 +691,9 @@ def test_rgb_lab(mode: str) -> None:
|
||||||
|
|
||||||
im = Image.new("LAB", (1, 1), (255, 0, 0))
|
im = Image.new("LAB", (1, 1), (255, 0, 0))
|
||||||
converted_im = im.convert(mode)
|
converted_im = im.convert(mode)
|
||||||
assert converted_im.getpixel((0, 0))[:3] == (0, 255, 255)
|
value = converted_im.getpixel((0, 0))
|
||||||
|
assert isinstance(value, tuple)
|
||||||
|
assert value[:3] == (0, 255, 255)
|
||||||
|
|
||||||
|
|
||||||
def test_deprecation() -> None:
|
def test_deprecation() -> None:
|
||||||
|
|
|
@ -1,8 +1,8 @@
|
||||||
from __future__ import annotations
|
from __future__ import annotations
|
||||||
|
|
||||||
import contextlib
|
|
||||||
import os.path
|
import os.path
|
||||||
from collections.abc import Sequence
|
from collections.abc import Sequence
|
||||||
|
from typing import Callable
|
||||||
|
|
||||||
import pytest
|
import pytest
|
||||||
|
|
||||||
|
@ -1422,25 +1422,44 @@ def test_default_font_size() -> None:
|
||||||
|
|
||||||
im = Image.new("RGB", (220, 25))
|
im = Image.new("RGB", (220, 25))
|
||||||
draw = ImageDraw.Draw(im)
|
draw = ImageDraw.Draw(im)
|
||||||
with contextlib.nullcontext() if freetype_support else pytest.raises(ImportError):
|
|
||||||
|
def check(func: Callable[[], None]) -> None:
|
||||||
|
if freetype_support:
|
||||||
|
func()
|
||||||
|
else:
|
||||||
|
with pytest.raises(ImportError):
|
||||||
|
func()
|
||||||
|
|
||||||
|
def draw_text() -> None:
|
||||||
draw.text((0, 0), text, font_size=16)
|
draw.text((0, 0), text, font_size=16)
|
||||||
assert_image_equal_tofile(im, "Tests/images/imagedraw_default_font_size.png")
|
assert_image_equal_tofile(im, "Tests/images/imagedraw_default_font_size.png")
|
||||||
|
|
||||||
with contextlib.nullcontext() if freetype_support else pytest.raises(ImportError):
|
check(draw_text)
|
||||||
|
|
||||||
|
def draw_textlength() -> None:
|
||||||
assert draw.textlength(text, font_size=16) == 216
|
assert draw.textlength(text, font_size=16) == 216
|
||||||
|
|
||||||
with contextlib.nullcontext() if freetype_support else pytest.raises(ImportError):
|
check(draw_textlength)
|
||||||
|
|
||||||
|
def draw_textbbox() -> None:
|
||||||
assert draw.textbbox((0, 0), text, font_size=16) == (0, 3, 216, 19)
|
assert draw.textbbox((0, 0), text, font_size=16) == (0, 3, 216, 19)
|
||||||
|
|
||||||
|
check(draw_textbbox)
|
||||||
|
|
||||||
im = Image.new("RGB", (220, 25))
|
im = Image.new("RGB", (220, 25))
|
||||||
draw = ImageDraw.Draw(im)
|
draw = ImageDraw.Draw(im)
|
||||||
with contextlib.nullcontext() if freetype_support else pytest.raises(ImportError):
|
|
||||||
|
def draw_multiline_text() -> None:
|
||||||
draw.multiline_text((0, 0), text, font_size=16)
|
draw.multiline_text((0, 0), text, font_size=16)
|
||||||
assert_image_equal_tofile(im, "Tests/images/imagedraw_default_font_size.png")
|
assert_image_equal_tofile(im, "Tests/images/imagedraw_default_font_size.png")
|
||||||
|
|
||||||
with contextlib.nullcontext() if freetype_support else pytest.raises(ImportError):
|
check(draw_multiline_text)
|
||||||
|
|
||||||
|
def draw_multiline_textbbox() -> None:
|
||||||
assert draw.multiline_textbbox((0, 0), text, font_size=16) == (0, 3, 216, 19)
|
assert draw.multiline_textbbox((0, 0), text, font_size=16) == (0, 3, 216, 19)
|
||||||
|
|
||||||
|
check(draw_multiline_textbbox)
|
||||||
|
|
||||||
|
|
||||||
@pytest.mark.parametrize("bbox", BBOX)
|
@pytest.mark.parametrize("bbox", BBOX)
|
||||||
def test_same_color_outline(bbox: Coords) -> None:
|
def test_same_color_outline(bbox: Coords) -> None:
|
||||||
|
|
|
@ -305,7 +305,7 @@ class TestPyDecoder(CodecsTest):
|
||||||
def test_decode(self) -> None:
|
def test_decode(self) -> None:
|
||||||
decoder = ImageFile.PyDecoder(None)
|
decoder = ImageFile.PyDecoder(None)
|
||||||
with pytest.raises(NotImplementedError):
|
with pytest.raises(NotImplementedError):
|
||||||
decoder.decode(None)
|
decoder.decode(b"")
|
||||||
|
|
||||||
|
|
||||||
class TestPyEncoder(CodecsTest):
|
class TestPyEncoder(CodecsTest):
|
||||||
|
|
|
@ -41,11 +41,15 @@ A = string_to_img(
|
||||||
def img_to_string(im: Image.Image) -> str:
|
def img_to_string(im: Image.Image) -> str:
|
||||||
"""Turn a (small) binary image into a string representation"""
|
"""Turn a (small) binary image into a string representation"""
|
||||||
chars = ".1"
|
chars = ".1"
|
||||||
width, height = im.size
|
result = []
|
||||||
return "\n".join(
|
for r in range(im.height):
|
||||||
"".join(chars[im.getpixel((c, r)) > 0] for c in range(width))
|
line = ""
|
||||||
for r in range(height)
|
for c in range(im.width):
|
||||||
)
|
value = im.getpixel((c, r))
|
||||||
|
assert not isinstance(value, tuple) and value is not None
|
||||||
|
line += chars[value > 0]
|
||||||
|
result.append(line)
|
||||||
|
return "\n".join(result)
|
||||||
|
|
||||||
|
|
||||||
def img_string_normalize(im: str) -> str:
|
def img_string_normalize(im: str) -> str:
|
||||||
|
|
|
@ -259,20 +259,26 @@ def test_colorize_2color() -> None:
|
||||||
left = (0, 1)
|
left = (0, 1)
|
||||||
middle = (127, 1)
|
middle = (127, 1)
|
||||||
right = (255, 1)
|
right = (255, 1)
|
||||||
|
value = im_test.getpixel(left)
|
||||||
|
assert isinstance(value, tuple)
|
||||||
assert_tuple_approx_equal(
|
assert_tuple_approx_equal(
|
||||||
im_test.getpixel(left),
|
value,
|
||||||
(255, 0, 0),
|
(255, 0, 0),
|
||||||
threshold=1,
|
threshold=1,
|
||||||
msg="black test pixel incorrect",
|
msg="black test pixel incorrect",
|
||||||
)
|
)
|
||||||
|
value = im_test.getpixel(middle)
|
||||||
|
assert isinstance(value, tuple)
|
||||||
assert_tuple_approx_equal(
|
assert_tuple_approx_equal(
|
||||||
im_test.getpixel(middle),
|
value,
|
||||||
(127, 63, 0),
|
(127, 63, 0),
|
||||||
threshold=1,
|
threshold=1,
|
||||||
msg="mid test pixel incorrect",
|
msg="mid test pixel incorrect",
|
||||||
)
|
)
|
||||||
|
value = im_test.getpixel(right)
|
||||||
|
assert isinstance(value, tuple)
|
||||||
assert_tuple_approx_equal(
|
assert_tuple_approx_equal(
|
||||||
im_test.getpixel(right),
|
value,
|
||||||
(0, 127, 0),
|
(0, 127, 0),
|
||||||
threshold=1,
|
threshold=1,
|
||||||
msg="white test pixel incorrect",
|
msg="white test pixel incorrect",
|
||||||
|
@ -295,20 +301,26 @@ def test_colorize_2color_offset() -> None:
|
||||||
left = (25, 1)
|
left = (25, 1)
|
||||||
middle = (75, 1)
|
middle = (75, 1)
|
||||||
right = (125, 1)
|
right = (125, 1)
|
||||||
|
value = im_test.getpixel(left)
|
||||||
|
assert isinstance(value, tuple)
|
||||||
assert_tuple_approx_equal(
|
assert_tuple_approx_equal(
|
||||||
im_test.getpixel(left),
|
value,
|
||||||
(255, 0, 0),
|
(255, 0, 0),
|
||||||
threshold=1,
|
threshold=1,
|
||||||
msg="black test pixel incorrect",
|
msg="black test pixel incorrect",
|
||||||
)
|
)
|
||||||
|
value = im_test.getpixel(middle)
|
||||||
|
assert isinstance(value, tuple)
|
||||||
assert_tuple_approx_equal(
|
assert_tuple_approx_equal(
|
||||||
im_test.getpixel(middle),
|
value,
|
||||||
(127, 63, 0),
|
(127, 63, 0),
|
||||||
threshold=1,
|
threshold=1,
|
||||||
msg="mid test pixel incorrect",
|
msg="mid test pixel incorrect",
|
||||||
)
|
)
|
||||||
|
value = im_test.getpixel(right)
|
||||||
|
assert isinstance(value, tuple)
|
||||||
assert_tuple_approx_equal(
|
assert_tuple_approx_equal(
|
||||||
im_test.getpixel(right),
|
value,
|
||||||
(0, 127, 0),
|
(0, 127, 0),
|
||||||
threshold=1,
|
threshold=1,
|
||||||
msg="white test pixel incorrect",
|
msg="white test pixel incorrect",
|
||||||
|
@ -339,29 +351,37 @@ def test_colorize_3color_offset() -> None:
|
||||||
middle = (100, 1)
|
middle = (100, 1)
|
||||||
right_middle = (150, 1)
|
right_middle = (150, 1)
|
||||||
right = (225, 1)
|
right = (225, 1)
|
||||||
|
value = im_test.getpixel(left)
|
||||||
|
assert isinstance(value, tuple)
|
||||||
assert_tuple_approx_equal(
|
assert_tuple_approx_equal(
|
||||||
im_test.getpixel(left),
|
value,
|
||||||
(255, 0, 0),
|
(255, 0, 0),
|
||||||
threshold=1,
|
threshold=1,
|
||||||
msg="black test pixel incorrect",
|
msg="black test pixel incorrect",
|
||||||
)
|
)
|
||||||
|
value = im_test.getpixel(left_middle)
|
||||||
|
assert isinstance(value, tuple)
|
||||||
assert_tuple_approx_equal(
|
assert_tuple_approx_equal(
|
||||||
im_test.getpixel(left_middle),
|
value,
|
||||||
(127, 0, 127),
|
(127, 0, 127),
|
||||||
threshold=1,
|
threshold=1,
|
||||||
msg="low-mid test pixel incorrect",
|
msg="low-mid test pixel incorrect",
|
||||||
)
|
)
|
||||||
|
value = im_test.getpixel(middle)
|
||||||
|
assert isinstance(value, tuple)
|
||||||
|
assert_tuple_approx_equal(value, (0, 0, 255), threshold=1, msg="mid incorrect")
|
||||||
|
value = im_test.getpixel(right_middle)
|
||||||
|
assert isinstance(value, tuple)
|
||||||
assert_tuple_approx_equal(
|
assert_tuple_approx_equal(
|
||||||
im_test.getpixel(middle), (0, 0, 255), threshold=1, msg="mid incorrect"
|
value,
|
||||||
)
|
|
||||||
assert_tuple_approx_equal(
|
|
||||||
im_test.getpixel(right_middle),
|
|
||||||
(0, 63, 127),
|
(0, 63, 127),
|
||||||
threshold=1,
|
threshold=1,
|
||||||
msg="high-mid test pixel incorrect",
|
msg="high-mid test pixel incorrect",
|
||||||
)
|
)
|
||||||
|
value = im_test.getpixel(right)
|
||||||
|
assert isinstance(value, tuple)
|
||||||
assert_tuple_approx_equal(
|
assert_tuple_approx_equal(
|
||||||
im_test.getpixel(right),
|
value,
|
||||||
(0, 127, 0),
|
(0, 127, 0),
|
||||||
threshold=1,
|
threshold=1,
|
||||||
msg="white test pixel incorrect",
|
msg="white test pixel incorrect",
|
||||||
|
@ -444,6 +464,7 @@ def test_exif_transpose_xml_without_xmp() -> None:
|
||||||
|
|
||||||
del im.info["xmp"]
|
del im.info["xmp"]
|
||||||
transposed_im = ImageOps.exif_transpose(im)
|
transposed_im = ImageOps.exif_transpose(im)
|
||||||
|
assert transposed_im is not None
|
||||||
assert 0x0112 not in transposed_im.getexif()
|
assert 0x0112 not in transposed_im.getexif()
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -45,10 +45,12 @@ def test_kw() -> None:
|
||||||
|
|
||||||
# Test "file"
|
# Test "file"
|
||||||
im = ImageTk._get_image_from_kw(kw)
|
im = ImageTk._get_image_from_kw(kw)
|
||||||
|
assert im is not None
|
||||||
assert_image_equal(im, im1)
|
assert_image_equal(im, im1)
|
||||||
|
|
||||||
# Test "data"
|
# Test "data"
|
||||||
im = ImageTk._get_image_from_kw(kw)
|
im = ImageTk._get_image_from_kw(kw)
|
||||||
|
assert im is not None
|
||||||
assert_image_equal(im, im2)
|
assert_image_equal(im, im2)
|
||||||
|
|
||||||
# Test no relevant entry
|
# Test no relevant entry
|
||||||
|
|
|
@ -11,7 +11,11 @@ from PIL.TiffImagePlugin import IFDRational
|
||||||
from .helper import hopper, skip_unless_feature
|
from .helper import hopper, skip_unless_feature
|
||||||
|
|
||||||
|
|
||||||
def _test_equal(num, denom, target) -> None:
|
def _test_equal(
|
||||||
|
num: float | Fraction | IFDRational,
|
||||||
|
denom: int,
|
||||||
|
target: float | Fraction | IFDRational,
|
||||||
|
) -> None:
|
||||||
t = IFDRational(num, denom)
|
t = IFDRational(num, denom)
|
||||||
|
|
||||||
assert target == t
|
assert target == t
|
||||||
|
|
Loading…
Reference in New Issue
Block a user