1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161
|
from __future__ import annotations
import io
import re
import pytest
from PIL import features
from .helper import skip_unless_feature
TYPE_CHECKING = False
if TYPE_CHECKING:
from collections.abc import Callable
def test_check() -> None:
# Check the correctness of the convenience function
for module in features.modules:
assert features.check_module(module) == features.check(module)
for codec in features.codecs:
assert features.check_codec(codec) == features.check(codec)
for feature in features.features:
assert features.check_feature(feature) == features.check(feature)
def test_version() -> None:
# Check the correctness of the convenience function
# and the format of version numbers
def test(name: str, function: Callable[[str], str | None]) -> None:
version = features.version(name)
if not features.check(name):
assert version is None
else:
assert function(name) == version
if name != "PIL":
if version is not None:
if name == "zlib" and features.check_feature("zlib_ng"):
version = re.sub(".zlib-ng$", "", version)
elif name == "libtiff":
version = re.sub("t$", "", version)
assert version is None or re.search(r"\d+(\.\d+)*$", version)
for module in features.modules:
test(module, features.version_module)
for codec in features.codecs:
test(codec, features.version_codec)
for feature in features.features:
test(feature, features.version_feature)
@skip_unless_feature("libjpeg_turbo")
def test_libjpeg_turbo_version() -> None:
version = features.version("libjpeg_turbo")
assert version is not None
assert re.search(r"\d+\.\d+\.\d+$", version)
@skip_unless_feature("libimagequant")
def test_libimagequant_version() -> None:
version = features.version("libimagequant")
assert version is not None
assert re.search(r"\d+\.\d+\.\d+$", version)
@pytest.mark.parametrize("feature", features.modules)
def test_check_modules(feature: str) -> None:
assert features.check_module(feature) in [True, False]
@pytest.mark.parametrize("feature", features.codecs)
def test_check_codecs(feature: str) -> None:
assert features.check_codec(feature) in [True, False]
def test_check_warns_on_nonexistent() -> None:
with pytest.warns(UserWarning, match="Unknown feature 'typo'."):
has_feature = features.check("typo")
assert has_feature is False
def test_supported_modules() -> None:
assert isinstance(features.get_supported_modules(), list)
assert isinstance(features.get_supported_codecs(), list)
assert isinstance(features.get_supported_features(), list)
assert isinstance(features.get_supported(), list)
def test_unsupported_codec() -> None:
# Arrange
codec = "unsupported_codec"
# Act / Assert
with pytest.raises(ValueError):
features.check_codec(codec)
with pytest.raises(ValueError):
features.version_codec(codec)
def test_unsupported_module() -> None:
# Arrange
module = "unsupported_module"
# Act / Assert
with pytest.raises(ValueError):
features.check_module(module)
with pytest.raises(ValueError):
features.version_module(module)
def test_unsupported_feature() -> None:
# Arrange
feature = "unsupported_feature"
# Act / Assert
with pytest.raises(ValueError):
features.check_feature(feature)
with pytest.raises(ValueError):
features.version_feature(feature)
def test_unsupported_version() -> None:
assert features.version("unsupported_version") is None
def test_modulenotfound(monkeypatch: pytest.MonkeyPatch) -> None:
monkeypatch.setattr(features, "features", {"test": ("PIL._test", "", "")})
assert features.check_feature("test") is None
@pytest.mark.parametrize("supported_formats", (True, False))
def test_pilinfo(supported_formats: bool) -> None:
buf = io.StringIO()
features.pilinfo(buf, supported_formats=supported_formats)
out = buf.getvalue()
lines = out.splitlines()
assert lines[0] == "-" * 68
assert lines[1].startswith("Pillow ")
assert lines[2].startswith("Python ")
lines = lines[3:]
while lines[0].startswith(" "):
lines = lines[1:]
assert lines[0] == "-" * 68
assert lines[1].startswith("Python executable is")
lines = lines[2:]
if lines[0].startswith("Environment Python files loaded from"):
lines = lines[1:]
assert lines[0].startswith("System Python files loaded from")
assert lines[1] == "-" * 68
assert lines[2].startswith("Python Pillow modules loaded from ")
assert lines[3].startswith("Binary Pillow modules loaded from ")
assert lines[4] == "-" * 68
jpeg = (
"\n"
+ "-" * 68
+ "\n"
+ "JPEG image/jpeg\n"
+ "Extensions: .jfif, .jpe, .jpeg, .jpg\n"
+ "Features: open, save\n"
+ "-" * 68
+ "\n"
)
assert supported_formats == (jpeg in out)
|