From 1008644dd614069b4303cf484326fe03939745cf Mon Sep 17 00:00:00 2001 From: Jon Dufresne Date: Sat, 25 May 2019 11:11:33 -0700 Subject: [PATCH] Add __main__.py to output basic format and support information MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit To help debug and show supported formats, users can run: $ python -m PIL to get basic format and support information about the installed version of Pillow. The new feature works as follows: $ python -m PIL -------------------------------------------------------------------- Pillow 6.1.0.dev0 -------------------------------------------------------------------- Python modules loaded from .../Pillow/src/PIL Binary modules loaded from .../Pillow/src/PIL -------------------------------------------------------------------- Python 3.7.3 (default, May 11 2019, 00:38:04) [GCC 9.1.1 20190503 (Red Hat 9.1.1-1)] -------------------------------------------------------------------- --- PIL CORE support ok --- TKINTER support ok --- FREETYPE2 support ok --- LITTLECMS2 support ok --- WEBP support ok --- WEBP Transparency support ok --- WEBPMUX support ok --- WEBP Animation support ok --- JPEG support ok --- OPENJPEG (JPEG2000) support ok --- ZLIB (PNG/ZIP) support ok --- LIBTIFF support ok --- RAQM (Bidirectional Text) support ok -------------------------------------------------------------------- BLP Extensions: .blp Features: open -------------------------------------------------------------------- BMP image/bmp Extensions: .bmp Features: open, save -------------------------------------------------------------------- BUFR Extensions: .bufr Features: open, save -------------------------------------------------------------------- … --- Tests/test_features.py | 26 ++++++++++++++ Tests/test_main.py | 28 +++++++++++++++ src/PIL/__main__.py | 3 ++ src/PIL/features.py | 82 ++++++++++++++++++++++++++++++++++++++++++ 4 files changed, 139 insertions(+) create mode 100644 Tests/test_main.py create mode 100644 src/PIL/__main__.py diff --git a/Tests/test_features.py b/Tests/test_features.py index 15b5982cee6..642083ed5b9 100644 --- a/Tests/test_features.py +++ b/Tests/test_features.py @@ -1,3 +1,7 @@ +from __future__ import unicode_literals + +import io + from .helper import unittest, PillowTestCase from PIL import features @@ -63,3 +67,25 @@ def test_unsupported_module(self): module = "unsupported_module" # Act / Assert self.assertRaises(ValueError, features.check_module, module) + + def test_pilinfo(self): + buf = io.StringIO() + features.pilinfo(buf) + out = buf.getvalue() + lines = out.splitlines() + self.assertEqual(lines[0], "-" * 68) + self.assertTrue(lines[1].startswith("Pillow ")) + self.assertEqual(lines[2], "-" * 68) + self.assertTrue(lines[3].startswith("Python modules loaded from ")) + self.assertTrue(lines[4].startswith("Binary modules loaded from ")) + self.assertEqual(lines[5], "-" * 68) + self.assertTrue(lines[6].startswith("Python ")) + jpeg = ( + "\n" + + "-" * 68 + "\n" + + "JPEG image/jpeg\n" + + "Extensions: .jfif, .jpe, .jpeg, .jpg\n" + + "Features: open, save\n" + + "-" * 68 + "\n" + ) + self.assertIn(jpeg, out) diff --git a/Tests/test_main.py b/Tests/test_main.py new file mode 100644 index 00000000000..c9445ce9c8e --- /dev/null +++ b/Tests/test_main.py @@ -0,0 +1,28 @@ +from __future__ import unicode_literals + +import os +import subprocess +import sys +from unittest import TestCase + + +class TestMain(TestCase): + def test_main(self): + out = subprocess.check_output([sys.executable, "-m", "PIL"]).decode("utf-8") + lines = out.splitlines() + self.assertEqual(lines[0], "-" * 68) + self.assertTrue(lines[1].startswith("Pillow ")) + self.assertEqual(lines[2], "-" * 68) + self.assertTrue(lines[3].startswith("Python modules loaded from ")) + self.assertTrue(lines[4].startswith("Binary modules loaded from ")) + self.assertEqual(lines[5], "-" * 68) + self.assertTrue(lines[6].startswith("Python ")) + jpeg = ( + os.linesep + + "-" * 68 + os.linesep + + "JPEG image/jpeg" + os.linesep + + "Extensions: .jfif, .jpe, .jpeg, .jpg" + os.linesep + + "Features: open, save" + os.linesep + + "-" * 68 + os.linesep + ) + self.assertIn(jpeg, out) diff --git a/src/PIL/__main__.py b/src/PIL/__main__.py new file mode 100644 index 00000000000..a05323f93b6 --- /dev/null +++ b/src/PIL/__main__.py @@ -0,0 +1,3 @@ +from .features import pilinfo + +pilinfo() diff --git a/src/PIL/features.py b/src/PIL/features.py index 6530038b75f..f6e638407ef 100644 --- a/src/PIL/features.py +++ b/src/PIL/features.py @@ -1,3 +1,10 @@ +from __future__ import print_function, unicode_literals + +import collections +import os +import sys + +import PIL from . import Image modules = { @@ -84,3 +91,78 @@ def get_supported(): ret.extend(get_supported_features()) ret.extend(get_supported_codecs()) return ret + + +def pilinfo(out=None): + if out is None: + out = sys.stdout + + Image.init() + + print("-" * 68, file=out) + print("Pillow {}".format(PIL.__version__), file=out) + print("-" * 68, file=out) + print( + "Python modules loaded from {}".format(os.path.dirname(Image.__file__)), + file=out, + ) + print( + "Binary modules loaded from {}".format(os.path.dirname(Image.core.__file__)), + file=out, + ) + print("-" * 68, file=out) + + v = sys.version.splitlines() + print("Python {}".format(v[0].strip()), file=out) + for v in v[1:]: + print(" {}".format(v.strip()), file=out) + print("-" * 68, file=out) + + for name, feature in [ + ("pil", "PIL CORE"), + ("tkinter", "TKINTER"), + ("freetype2", "FREETYPE2"), + ("littlecms2", "LITTLECMS2"), + ("webp", "WEBP"), + ("transp_webp", "WEBP Transparency"), + ("webp_mux", "WEBPMUX"), + ("webp_anim", "WEBP Animation"), + ("jpg", "JPEG"), + ("jpg_2000", "OPENJPEG (JPEG2000)"), + ("zlib", "ZLIB (PNG/ZIP)"), + ("libtiff", "LIBTIFF"), + ("raqm", "RAQM (Bidirectional Text)"), + ]: + if check(name): + print("---", feature, "support ok", file=out) + else: + print("***", feature, "support not installed", file=out) + print("-" * 68, file=out) + + extensions = collections.defaultdict(list) + for ext, i in Image.EXTENSION.items(): + extensions[i].append(ext) + + for i in sorted(Image.ID): + line = "{}".format(i) + if i in Image.MIME: + line = "{} {}".format(line, Image.MIME[i]) + print(line, file=out) + + if i in extensions: + print("Extensions: {}".format(", ".join(sorted(extensions[i]))), file=out) + + features = [] + if i in Image.OPEN: + features.append("open") + if i in Image.SAVE: + features.append("save") + if i in Image.SAVE_ALL: + features.append("save_all") + if i in Image.DECODERS: + features.append("decode") + if i in Image.ENCODERS: + features.append("encode") + + print("Features: {}".format(", ".join(features)), file=out) + print("-" * 68, file=out)