add version to features info block

This commit is contained in:
nulano 2019-10-12 14:29:10 +01:00 committed by Andrew Murray
parent 11a4f1135d
commit a324f4a466
8 changed files with 73 additions and 27 deletions

View File

@ -2,14 +2,14 @@ import io
import sys import sys
import pytest import pytest
from PIL import IcnsImagePlugin, Image from PIL import IcnsImagePlugin, Image, features
from .helper import assert_image_equal, assert_image_similar from .helper import assert_image_equal, assert_image_similar
# sample icon file # sample icon file
TEST_FILE = "Tests/images/pillow.icns" TEST_FILE = "Tests/images/pillow.icns"
ENABLE_JPEG2K = hasattr(Image.core, "jp2klib_version") ENABLE_JPEG2K = features.check_codec("jpg_2000")
def test_sanity(): def test_sanity():

View File

@ -3,7 +3,7 @@ import re
from io import BytesIO from io import BytesIO
import pytest import pytest
from PIL import ExifTags, Image, ImageFile, JpegImagePlugin from PIL import ExifTags, Image, ImageFile, JpegImagePlugin, features
from .helper import ( from .helper import (
assert_image, assert_image,
@ -41,7 +41,7 @@ class TestFileJpeg:
def test_sanity(self): def test_sanity(self):
# internal version number # internal version number
assert re.search(r"\d+\.\d+$", Image.core.jpeglib_version) assert re.search(r"\d+\.\d+$", features.version_codec("jpg"))
with Image.open(TEST_FILE) as im: with Image.open(TEST_FILE) as im:
im.load() im.load()

View File

@ -2,7 +2,7 @@ import re
from io import BytesIO from io import BytesIO
import pytest import pytest
from PIL import Image, ImageFile, Jpeg2KImagePlugin from PIL import Image, ImageFile, Jpeg2KImagePlugin, features
from .helper import ( from .helper import (
assert_image_equal, assert_image_equal,
@ -35,7 +35,7 @@ def roundtrip(im, **options):
def test_sanity(): def test_sanity():
# Internal version number # Internal version number
assert re.search(r"\d+\.\d+\.\d+$", Image.core.jp2klib_version) assert re.search(r"\d+\.\d+\.\d+$", features.version_codec("jpg_2000"))
with Image.open("Tests/images/test-card-lossless.jp2") as im: with Image.open("Tests/images/test-card-lossless.jp2") as im:
px = im.load() px = im.load()

View File

@ -3,7 +3,7 @@ import zlib
from io import BytesIO from io import BytesIO
import pytest import pytest
from PIL import Image, ImageFile, PngImagePlugin from PIL import Image, ImageFile, PngImagePlugin, features
from .helper import ( from .helper import (
PillowLeakTestCase, PillowLeakTestCase,
@ -73,7 +73,7 @@ class TestFilePng:
def test_sanity(self, tmp_path): def test_sanity(self, tmp_path):
# internal version number # internal version number
assert re.search(r"\d+\.\d+\.\d+(\.\d+)?$", Image.core.zlib_version) assert re.search(r"\d+\.\d+\.\d+(\.\d+)?$", features.version_codec("zlib"))
test_file = str(tmp_path / "temp.png") test_file = str(tmp_path / "temp.png")

View File

@ -4,7 +4,7 @@ import re
from io import BytesIO from io import BytesIO
import pytest import pytest
from PIL import Image, ImageMode from PIL import Image, ImageMode, features
from .helper import assert_image, assert_image_equal, assert_image_similar, hopper from .helper import assert_image, assert_image_equal, assert_image_similar, hopper
@ -46,7 +46,7 @@ def test_sanity():
assert list(map(type, v)) == [str, str, str, str] assert list(map(type, v)) == [str, str, str, str]
# internal version number # internal version number
assert re.search(r"\d+\.\d+$", ImageCms.core.littlecms_version) assert re.search(r"\d+\.\d+$", features.version_module("littlecms2"))
skip_missing() skip_missing()
i = ImageCms.profileToProfile(hopper(), SRGB, SRGB) i = ImageCms.profileToProfile(hopper(), SRGB, SRGB)

View File

@ -7,7 +7,7 @@ import sys
from io import BytesIO from io import BytesIO
import pytest import pytest
from PIL import Image, ImageDraw, ImageFont from PIL import Image, ImageDraw, ImageFont, features
from .helper import ( from .helper import (
assert_image_equal, assert_image_equal,
@ -40,7 +40,7 @@ class TestImageFont:
@classmethod @classmethod
def setup_class(self): def setup_class(self):
freetype = distutils.version.StrictVersion(ImageFont.core.freetype2_version) freetype = distutils.version.StrictVersion(features.version_module("freetype2"))
self.metrics = self.METRICS["Default"] self.metrics = self.METRICS["Default"]
for conditions, metrics in self.METRICS.items(): for conditions, metrics in self.METRICS.items():
@ -67,7 +67,7 @@ class TestImageFont:
) )
def test_sanity(self): def test_sanity(self):
assert re.search(r"\d+\.\d+\.\d+$", ImageFont.core.freetype2_version) assert re.search(r"\d+\.\d+\.\d+$", features.version_module("freetype2"))
def test_font_properties(self): def test_font_properties(self):
ttf = self.get_font() ttf = self.get_font()
@ -619,7 +619,7 @@ class TestImageFont:
def test_variation_get(self): def test_variation_get(self):
font = self.get_font() font = self.get_font()
freetype = distutils.version.StrictVersion(ImageFont.core.freetype2_version) freetype = distutils.version.StrictVersion(features.version_module("freetype2"))
if freetype < "2.9.1": if freetype < "2.9.1":
with pytest.raises(NotImplementedError): with pytest.raises(NotImplementedError):
font.get_variation_names() font.get_variation_names()
@ -691,7 +691,7 @@ class TestImageFont:
def test_variation_set_by_name(self): def test_variation_set_by_name(self):
font = self.get_font() font = self.get_font()
freetype = distutils.version.StrictVersion(ImageFont.core.freetype2_version) freetype = distutils.version.StrictVersion(features.version_module("freetype2"))
if freetype < "2.9.1": if freetype < "2.9.1":
with pytest.raises(NotImplementedError): with pytest.raises(NotImplementedError):
font.set_variation_by_name("Bold") font.set_variation_by_name("Bold")
@ -715,7 +715,7 @@ class TestImageFont:
def test_variation_set_by_axes(self): def test_variation_set_by_axes(self):
font = self.get_font() font = self.get_font()
freetype = distutils.version.StrictVersion(ImageFont.core.freetype2_version) freetype = distutils.version.StrictVersion(features.version_module("freetype2"))
if freetype < "2.9.1": if freetype < "2.9.1":
with pytest.raises(NotImplementedError): with pytest.raises(NotImplementedError):
font.set_variation_by_axes([100]) font.set_variation_by_axes([100])

View File

@ -23,10 +23,10 @@ import subprocess
import sys import sys
import tempfile import tempfile
from PIL import Image, ImageFile, PngImagePlugin from PIL import Image, ImageFile, PngImagePlugin, features
from PIL._binary import i8 from PIL._binary import i8
enable_jpeg2k = hasattr(Image.core, "jp2klib_version") enable_jpeg2k = features.check_codec("jpg_2000")
if enable_jpeg2k: if enable_jpeg2k:
from PIL import Jpeg2KImagePlugin from PIL import Jpeg2KImagePlugin

View File

@ -8,11 +8,11 @@ import PIL
from . import Image from . import Image
modules = { modules = {
"pil": "PIL._imaging", "pil": ("PIL._imaging", None),
"tkinter": "PIL._tkinter_finder", "tkinter": ("PIL._tkinter_finder", None),
"freetype2": "PIL._imagingft", "freetype2": ("PIL._imagingft", "freetype2"),
"littlecms2": "PIL._imagingcms", "littlecms2": ("PIL._imagingcms", "littlecms"),
"webp": "PIL._webp", "webp": ("PIL._webp", None),
} }
@ -27,7 +27,7 @@ def check_module(feature):
if not (feature in modules): if not (feature in modules):
raise ValueError("Unknown module %s" % feature) raise ValueError("Unknown module %s" % feature)
module = modules[feature] module, lib = modules[feature]
try: try:
__import__(module) __import__(module)
@ -36,6 +36,20 @@ def check_module(feature):
return False return False
def version_module(feature):
if not check_module(feature):
return None
module, lib = modules[feature]
if lib is None:
return None
attr = lib + "_version"
return getattr(__import__(module, fromlist=[attr]), attr)
def get_supported_modules(): def get_supported_modules():
""" """
:returns: A list of all supported modules. :returns: A list of all supported modules.
@ -43,7 +57,12 @@ def get_supported_modules():
return [f for f in modules if check_module(f)] return [f for f in modules if check_module(f)]
codecs = {"jpg": "jpeg", "jpg_2000": "jpeg2k", "zlib": "zip", "libtiff": "libtiff"} codecs = {
"jpg": ("jpeg", "jpeglib"),
"jpg_2000": ("jpeg2k", "jp2klib"),
"zlib": ("zip", "zlib"),
"libtiff": ("libtiff", "libtiff"),
}
def check_codec(feature): def check_codec(feature):
@ -57,11 +76,25 @@ def check_codec(feature):
if feature not in codecs: if feature not in codecs:
raise ValueError("Unknown codec %s" % feature) raise ValueError("Unknown codec %s" % feature)
codec = codecs[feature] codec, lib = codecs[feature]
return codec + "_encoder" in dir(Image.core) return codec + "_encoder" in dir(Image.core)
def version_codec(feature):
if not check_codec(feature):
return None
codec, lib = codecs[feature]
version = getattr(Image.core, lib + "_version")
if feature == "libtiff":
return version.split("\n")[0].split("Version ")[1]
return version
def get_supported_codecs(): def get_supported_codecs():
""" """
:returns: A list of all supported codecs. :returns: A list of all supported codecs.
@ -125,6 +158,14 @@ def check(feature):
return False return False
def version(feature):
if feature in modules:
return version_module(feature)
if feature in codecs:
return version_codec(feature)
return None
def get_supported(): def get_supported():
""" """
:returns: A list of all supported modules, features, and codecs. :returns: A list of all supported modules, features, and codecs.
@ -187,7 +228,12 @@ def pilinfo(out=None, supported_formats=True):
("xcb", "XCB (X protocol)"), ("xcb", "XCB (X protocol)"),
]: ]:
if check(name): if check(name):
print("---", feature, "support ok", file=out) v = version(name)
if v is not None:
support = "ok (version {})".format(v)
else:
support = "ok"
print("---", feature, "support", support, file=out)
else: else:
print("***", feature, "support not installed", file=out) print("***", feature, "support not installed", file=out)
print("-" * 68, file=out) print("-" * 68, file=out)