mirror of
https://github.com/python-pillow/Pillow.git
synced 2025-09-10 06:12:27 +03:00
Add has_feature_version helper (#9172)
This commit is contained in:
commit
f9db7a3d08
|
@ -175,6 +175,14 @@ def skip_unless_feature(feature: str) -> pytest.MarkDecorator:
|
||||||
return pytest.mark.skipif(not features.check(feature), reason=reason)
|
return pytest.mark.skipif(not features.check(feature), reason=reason)
|
||||||
|
|
||||||
|
|
||||||
|
def has_feature_version(feature: str, required: str) -> bool:
|
||||||
|
version = features.version(feature)
|
||||||
|
assert version is not None
|
||||||
|
version_required = parse_version(required)
|
||||||
|
version_available = parse_version(version)
|
||||||
|
return version_available >= version_required
|
||||||
|
|
||||||
|
|
||||||
def skip_unless_feature_version(
|
def skip_unless_feature_version(
|
||||||
feature: str, required: str, reason: str | None = None
|
feature: str, required: str, reason: str | None = None
|
||||||
) -> pytest.MarkDecorator:
|
) -> pytest.MarkDecorator:
|
||||||
|
|
|
@ -4,13 +4,13 @@ from collections.abc import Generator
|
||||||
from pathlib import Path
|
from pathlib import Path
|
||||||
|
|
||||||
import pytest
|
import pytest
|
||||||
from packaging.version import parse as parse_version
|
|
||||||
|
|
||||||
from PIL import GifImagePlugin, Image, WebPImagePlugin, features
|
from PIL import GifImagePlugin, Image, WebPImagePlugin
|
||||||
|
|
||||||
from .helper import (
|
from .helper import (
|
||||||
assert_image_equal,
|
assert_image_equal,
|
||||||
assert_image_similar,
|
assert_image_similar,
|
||||||
|
has_feature_version,
|
||||||
is_big_endian,
|
is_big_endian,
|
||||||
skip_unless_feature,
|
skip_unless_feature,
|
||||||
)
|
)
|
||||||
|
@ -53,11 +53,8 @@ def test_write_animation_L(tmp_path: Path) -> None:
|
||||||
im.load()
|
im.load()
|
||||||
assert_image_similar(im, orig.convert("RGBA"), 32.9)
|
assert_image_similar(im, orig.convert("RGBA"), 32.9)
|
||||||
|
|
||||||
if is_big_endian():
|
if is_big_endian() and not has_feature_version("webp", "1.2.2"):
|
||||||
version = features.version_module("webp")
|
pytest.skip("Fails with libwebp earlier than 1.2.2")
|
||||||
assert version is not None
|
|
||||||
if parse_version(version) < parse_version("1.2.2"):
|
|
||||||
pytest.skip("Fails with libwebp earlier than 1.2.2")
|
|
||||||
orig.seek(orig.n_frames - 1)
|
orig.seek(orig.n_frames - 1)
|
||||||
im.seek(im.n_frames - 1)
|
im.seek(im.n_frames - 1)
|
||||||
orig.load()
|
orig.load()
|
||||||
|
@ -81,11 +78,8 @@ def test_write_animation_RGB(tmp_path: Path) -> None:
|
||||||
assert_image_equal(im, frame1.convert("RGBA"))
|
assert_image_equal(im, frame1.convert("RGBA"))
|
||||||
|
|
||||||
# Compare second frame to original
|
# Compare second frame to original
|
||||||
if is_big_endian():
|
if is_big_endian() and not has_feature_version("webp", "1.2.2"):
|
||||||
version = features.version_module("webp")
|
pytest.skip("Fails with libwebp earlier than 1.2.2")
|
||||||
assert version is not None
|
|
||||||
if parse_version(version) < parse_version("1.2.2"):
|
|
||||||
pytest.skip("Fails with libwebp earlier than 1.2.2")
|
|
||||||
im.seek(1)
|
im.seek(1)
|
||||||
im.load()
|
im.load()
|
||||||
assert_image_equal(im, frame2.convert("RGBA"))
|
assert_image_equal(im, frame2.convert("RGBA"))
|
||||||
|
|
|
@ -1,11 +1,16 @@
|
||||||
from __future__ import annotations
|
from __future__ import annotations
|
||||||
|
|
||||||
import pytest
|
import pytest
|
||||||
from packaging.version import parse as parse_version
|
|
||||||
|
|
||||||
from PIL import Image, features
|
from PIL import Image
|
||||||
|
|
||||||
from .helper import assert_image_similar, hopper, is_ppc64le, skip_unless_feature
|
from .helper import (
|
||||||
|
assert_image_similar,
|
||||||
|
has_feature_version,
|
||||||
|
hopper,
|
||||||
|
is_ppc64le,
|
||||||
|
skip_unless_feature,
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
def test_sanity() -> None:
|
def test_sanity() -> None:
|
||||||
|
@ -23,11 +28,8 @@ def test_sanity() -> None:
|
||||||
@skip_unless_feature("libimagequant")
|
@skip_unless_feature("libimagequant")
|
||||||
def test_libimagequant_quantize() -> None:
|
def test_libimagequant_quantize() -> None:
|
||||||
image = hopper()
|
image = hopper()
|
||||||
if is_ppc64le():
|
if is_ppc64le() and not has_feature_version("libimagequant", "4"):
|
||||||
version = features.version_feature("libimagequant")
|
pytest.skip("Fails with libimagequant earlier than 4.0.0 on ppc64le")
|
||||||
assert version is not None
|
|
||||||
if parse_version(version) < parse_version("4"):
|
|
||||||
pytest.skip("Fails with libimagequant earlier than 4.0.0 on ppc64le")
|
|
||||||
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)
|
||||||
|
|
|
@ -7,6 +7,7 @@ from PIL import Image, ImageDraw, ImageFont
|
||||||
from .helper import (
|
from .helper import (
|
||||||
assert_image_equal_tofile,
|
assert_image_equal_tofile,
|
||||||
assert_image_similar_tofile,
|
assert_image_similar_tofile,
|
||||||
|
has_feature_version,
|
||||||
skip_unless_feature,
|
skip_unless_feature,
|
||||||
)
|
)
|
||||||
|
|
||||||
|
@ -104,11 +105,9 @@ def test_text_direction_ttb() -> None:
|
||||||
|
|
||||||
im = Image.new(mode="RGB", size=(100, 300))
|
im = Image.new(mode="RGB", size=(100, 300))
|
||||||
draw = ImageDraw.Draw(im)
|
draw = ImageDraw.Draw(im)
|
||||||
try:
|
if not has_feature_version("raqm", "0.7"):
|
||||||
draw.text((0, 0), "English あい", font=ttf, fill=500, direction="ttb")
|
pytest.skip("libraqm 0.7 or greater not available")
|
||||||
except ValueError as ex:
|
draw.text((0, 0), "English あい", font=ttf, fill=500, direction="ttb")
|
||||||
if str(ex) == "libraqm 0.7 or greater required for 'ttb' direction":
|
|
||||||
pytest.skip("libraqm 0.7 or greater not available")
|
|
||||||
|
|
||||||
target = "Tests/images/test_direction_ttb.png"
|
target = "Tests/images/test_direction_ttb.png"
|
||||||
assert_image_similar_tofile(im, target, 2.8)
|
assert_image_similar_tofile(im, target, 2.8)
|
||||||
|
@ -119,19 +118,17 @@ def test_text_direction_ttb_stroke() -> None:
|
||||||
|
|
||||||
im = Image.new(mode="RGB", size=(100, 300))
|
im = Image.new(mode="RGB", size=(100, 300))
|
||||||
draw = ImageDraw.Draw(im)
|
draw = ImageDraw.Draw(im)
|
||||||
try:
|
if not has_feature_version("raqm", "0.7"):
|
||||||
draw.text(
|
pytest.skip("libraqm 0.7 or greater not available")
|
||||||
(27, 27),
|
draw.text(
|
||||||
"あい",
|
(27, 27),
|
||||||
font=ttf,
|
"あい",
|
||||||
fill=500,
|
font=ttf,
|
||||||
direction="ttb",
|
fill=500,
|
||||||
stroke_width=2,
|
direction="ttb",
|
||||||
stroke_fill="#0f0",
|
stroke_width=2,
|
||||||
)
|
stroke_fill="#0f0",
|
||||||
except ValueError as ex:
|
)
|
||||||
if str(ex) == "libraqm 0.7 or greater required for 'ttb' direction":
|
|
||||||
pytest.skip("libraqm 0.7 or greater not available")
|
|
||||||
|
|
||||||
target = "Tests/images/test_direction_ttb_stroke.png"
|
target = "Tests/images/test_direction_ttb_stroke.png"
|
||||||
assert_image_similar_tofile(im, target, 19.4)
|
assert_image_similar_tofile(im, target, 19.4)
|
||||||
|
@ -219,14 +216,9 @@ def test_getlength(
|
||||||
im = Image.new(mode, (1, 1), 0)
|
im = Image.new(mode, (1, 1), 0)
|
||||||
d = ImageDraw.Draw(im)
|
d = ImageDraw.Draw(im)
|
||||||
|
|
||||||
try:
|
if direction == "ttb" and not has_feature_version("raqm", "0.7"):
|
||||||
assert d.textlength(text, ttf, direction) == expected
|
pytest.skip("libraqm 0.7 or greater not available")
|
||||||
except ValueError as ex:
|
assert d.textlength(text, ttf, direction) == expected
|
||||||
if (
|
|
||||||
direction == "ttb"
|
|
||||||
and str(ex) == "libraqm 0.7 or greater required for 'ttb' direction"
|
|
||||||
):
|
|
||||||
pytest.skip("libraqm 0.7 or greater not available")
|
|
||||||
|
|
||||||
|
|
||||||
@pytest.mark.parametrize("mode", ("L", "1"))
|
@pytest.mark.parametrize("mode", ("L", "1"))
|
||||||
|
@ -242,17 +234,12 @@ def test_getlength_combine(mode: str, direction: str, text: str) -> None:
|
||||||
|
|
||||||
ttf = ImageFont.truetype("Tests/fonts/NotoSans-Regular.ttf", 48)
|
ttf = ImageFont.truetype("Tests/fonts/NotoSans-Regular.ttf", 48)
|
||||||
|
|
||||||
try:
|
if direction == "ttb" and not has_feature_version("raqm", "0.7"):
|
||||||
target = ttf.getlength("ii", mode, direction)
|
pytest.skip("libraqm 0.7 or greater not available")
|
||||||
actual = ttf.getlength(text, mode, direction)
|
target = ttf.getlength("ii", mode, direction)
|
||||||
|
actual = ttf.getlength(text, mode, direction)
|
||||||
|
|
||||||
assert actual == target
|
assert actual == target
|
||||||
except ValueError as ex:
|
|
||||||
if (
|
|
||||||
direction == "ttb"
|
|
||||||
and str(ex) == "libraqm 0.7 or greater required for 'ttb' direction"
|
|
||||||
):
|
|
||||||
pytest.skip("libraqm 0.7 or greater not available")
|
|
||||||
|
|
||||||
|
|
||||||
@pytest.mark.parametrize("anchor", ("lt", "mm", "rb", "sm"))
|
@pytest.mark.parametrize("anchor", ("lt", "mm", "rb", "sm"))
|
||||||
|
@ -265,11 +252,9 @@ def test_anchor_ttb(anchor: str) -> None:
|
||||||
d = ImageDraw.Draw(im)
|
d = ImageDraw.Draw(im)
|
||||||
d.line(((0, 200), (200, 200)), "gray")
|
d.line(((0, 200), (200, 200)), "gray")
|
||||||
d.line(((100, 0), (100, 400)), "gray")
|
d.line(((100, 0), (100, 400)), "gray")
|
||||||
try:
|
if not has_feature_version("raqm", "0.7"):
|
||||||
d.text((100, 200), text, fill="black", anchor=anchor, direction="ttb", font=f)
|
pytest.skip("libraqm 0.7 or greater not available")
|
||||||
except ValueError as ex:
|
d.text((100, 200), text, fill="black", anchor=anchor, direction="ttb", font=f)
|
||||||
if str(ex) == "libraqm 0.7 or greater required for 'ttb' direction":
|
|
||||||
pytest.skip("libraqm 0.7 or greater not available")
|
|
||||||
|
|
||||||
assert_image_similar_tofile(im, path, 1) # fails at 5
|
assert_image_similar_tofile(im, path, 1) # fails at 5
|
||||||
|
|
||||||
|
@ -310,10 +295,12 @@ combine_tests = (
|
||||||
|
|
||||||
# this tests various combining characters for anchor alignment and clipping
|
# this tests various combining characters for anchor alignment and clipping
|
||||||
@pytest.mark.parametrize(
|
@pytest.mark.parametrize(
|
||||||
"name, text, anchor, dir, epsilon", combine_tests, ids=[r[0] for r in combine_tests]
|
"name, text, anchor, direction, epsilon",
|
||||||
|
combine_tests,
|
||||||
|
ids=[r[0] for r in combine_tests],
|
||||||
)
|
)
|
||||||
def test_combine(
|
def test_combine(
|
||||||
name: str, text: str, dir: str | None, anchor: str | None, epsilon: float
|
name: str, text: str, direction: str | None, anchor: str | None, epsilon: float
|
||||||
) -> None:
|
) -> None:
|
||||||
path = f"Tests/images/test_combine_{name}.png"
|
path = f"Tests/images/test_combine_{name}.png"
|
||||||
f = ImageFont.truetype("Tests/fonts/NotoSans-Regular.ttf", 48)
|
f = ImageFont.truetype("Tests/fonts/NotoSans-Regular.ttf", 48)
|
||||||
|
@ -322,11 +309,9 @@ def test_combine(
|
||||||
d = ImageDraw.Draw(im)
|
d = ImageDraw.Draw(im)
|
||||||
d.line(((0, 200), (400, 200)), "gray")
|
d.line(((0, 200), (400, 200)), "gray")
|
||||||
d.line(((200, 0), (200, 400)), "gray")
|
d.line(((200, 0), (200, 400)), "gray")
|
||||||
try:
|
if direction == "ttb" and not has_feature_version("raqm", "0.7"):
|
||||||
d.text((200, 200), text, fill="black", anchor=anchor, direction=dir, font=f)
|
pytest.skip("libraqm 0.7 or greater not available")
|
||||||
except ValueError as ex:
|
d.text((200, 200), text, fill="black", anchor=anchor, direction=direction, font=f)
|
||||||
if str(ex) == "libraqm 0.7 or greater required for 'ttb' direction":
|
|
||||||
pytest.skip("libraqm 0.7 or greater not available")
|
|
||||||
|
|
||||||
assert_image_similar_tofile(im, path, epsilon)
|
assert_image_similar_tofile(im, path, epsilon)
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue
Block a user