diff --git a/PIL/features.py b/PIL/features.py new file mode 100644 index 00000000000..b9ff99ee999 --- /dev/null +++ b/PIL/features.py @@ -0,0 +1,71 @@ +from PIL import Image + +modules = { + "PIL CORE": "PIL._imaging", + "TKINTER": "PIL._imagingtk", + "FREETYPE2": "PIL._imagingft", + "LITTLECMS2": "PIL._imagingcms", + "WEBP": "PIL._webp", + "Transparent WEBP": ("WEBP", "WebPDecoderBuggyAlpha") +} + + +def check_module(feature): + module = modules[feature] + + method_to_call = None + if type(module) is tuple: + module, method_to_call = module + + try: + imported_module = __import__(module) + except ImportError: + # If a method is being checked, None means that + # rather than the method failing, the module required for the method + # failed to be imported first + return None if method_to_call else False + + if method_to_call: + method = getattr(imported_module, method_to_call) + return method() is True + else: + return True + + +def get_supported_modules(): + supported_modules = [] + for feature in get_all_modules(): + if check_module(feature): + supported_modules.append(feature) + return supported_modules + + +def get_all_modules(): + # While the dictionary keys could be used here, + # a static list is used to maintain order + return ["PIL CORE", "TKINTER", "FREETYPE2", + "LITTLECMS2", "WEBP", "Transparent WEBP"] + +codecs = { + "JPEG": "jpeg", + "JPEG 2000": "jpeg2k", + "ZLIB (PNG/ZIP)": "zip", + "LIBTIFF": "libtiff" +} + + +def check_codec(feature): + codec = codecs[feature] + return codec + "_encoder" in dir(Image.core) + + +def get_supported_codecs(): + supported_codecs = [] + for feature in get_all_codecs(): + if check_codec(feature): + supported_codecs.append(feature) + return supported_codecs + + +def get_all_codecs(): + return ["JPEG", "JPEG 2000", "ZLIB (PNG/ZIP)", "LIBTIFF"] diff --git a/selftest.py b/selftest.py index b13dfec28a0..1872d3e9763 100644 --- a/selftest.py +++ b/selftest.py @@ -9,6 +9,7 @@ del sys.path[0] from PIL import Image, ImageDraw, ImageFilter, ImageMath +from PIL import features if "--installed" in sys.argv: sys.path.insert(0, sys_path_0) @@ -162,22 +163,6 @@ def testimage(): """ -def check_module(feature, module): - try: - __import__(module) - except ImportError: - print("***", feature, "support not installed") - else: - print("---", feature, "support ok") - - -def check_codec(feature, codec): - if codec + "_encoder" not in dir(Image.core): - print("***", feature, "support not installed") - else: - print("---", feature, "support ok") - - if __name__ == "__main__": # check build sanity @@ -189,23 +174,22 @@ def check_codec(feature, codec): print("Python modules loaded from", os.path.dirname(Image.__file__)) print("Binary modules loaded from", os.path.dirname(Image.core.__file__)) print("-"*68) - check_module("PIL CORE", "PIL._imaging") - check_module("TKINTER", "PIL._imagingtk") - check_codec("JPEG", "jpeg") - check_codec("JPEG 2000", "jpeg2k") - check_codec("ZLIB (PNG/ZIP)", "zip") - check_codec("LIBTIFF", "libtiff") - check_module("FREETYPE2", "PIL._imagingft") - check_module("LITTLECMS2", "PIL._imagingcms") - check_module("WEBP", "PIL._webp") - try: - from PIL import _webp - if _webp.WebPDecoderBuggyAlpha(): - print("***", "Transparent WEBP", "support not installed") + for feature in features.get_all_modules(): + supported = features.check_module(feature) + + if supported is None: + # A method was being tested, but the module required + # for the method could not be correctly imported + pass + elif supported: + print("---", feature, "support ok") + else: + print("***", feature, "support not installed") + for feature in features.get_all_codecs(): + if features.check_codec(feature): + print("---", feature, "support ok") else: - print("---", "Transparent WEBP", "support ok") - except Exception: - pass + print("***", feature, "support not installed") print("-"*68) # use doctest to make sure the test program behaves as documented!