Merge pull request #2520 from wiredfool/features

Updated Features detection
This commit is contained in:
wiredfool 2017-06-13 13:03:27 +01:00 committed by GitHub
commit 9d46f4f282
5 changed files with 91 additions and 50 deletions

View File

@ -3,7 +3,7 @@
set -e
sudo apt-get update
sudo apt-get -qq install libfreetype6-dev liblcms2-dev\
sudo apt-get -qq install libfreetype6-dev liblcms2-dev python-tk \
python-qt4 ghostscript libffi-dev libjpeg-turbo-progs cmake imagemagick
pip install cffi
pip install nose

View File

@ -2,45 +2,26 @@ from . import Image
modules = {
"pil": "PIL._imaging",
"tkinter": "PIL._imagingtk",
"tkinter": "PIL._tkinter_finder",
"freetype2": "PIL._imagingft",
"littlecms2": "PIL._imagingcms",
"webp": "PIL._webp",
"transp_webp": ("WEBP", "WebPDecoderBuggyAlpha")
}
def check_module(feature):
if feature not in modules:
if not (feature in modules):
raise ValueError("Unknown module %s" % feature)
module = modules[feature]
method_to_call = None
if isinstance(module, 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
except ImportError:
return False
def get_supported_modules():
supported_modules = []
for feature in modules:
if check_module(feature):
supported_modules.append(feature)
return supported_modules
return [f for f in modules if check_module(f)]
codecs = {
"jpg": "jpeg",
@ -49,7 +30,6 @@ codecs = {
"libtiff": "libtiff"
}
def check_codec(feature):
if feature not in codecs:
raise ValueError("Unknown codec %s" % feature)
@ -60,8 +40,38 @@ def check_codec(feature):
def get_supported_codecs():
supported_codecs = []
for feature in codecs:
if check_codec(feature):
supported_codecs.append(feature)
return supported_codecs
return [f for f in codecs if check_codec(f)]
features = {
"webp_mux": ("PIL._webp", 'HAVE_WEBPMUX'),
"transp_webp": ("PIL._webp", "HAVE_TRANSPARENCY"),
}
def check_feature(feature):
if feature not in features:
raise ValueError("Unknown feature %s" % feature)
module, flag = features[feature]
try:
imported_module = __import__(module, fromlist=['PIL'])
return getattr(imported_module, flag)
except ImportError:
return None
def get_supported_features():
return [f for f in features if check_feature(f)]
def check(feature):
return (feature in modules and check_module(feature) or \
feature in codecs and check_codec(feature) or \
feature in features and check_feature(feature))
def get_supported():
ret = get_supported_modules()
ret.extend(get_supported_features())
ret.extend(get_supported_codecs())
return ret

View File

@ -2,19 +2,50 @@ from helper import unittest, PillowTestCase
from PIL import features
try:
from PIL import _webp
HAVE_WEBP = True
except:
HAVE_WEBP = False
class TestFeatures(PillowTestCase):
def test_check_features(self):
def test_check(self):
# Check the correctness of the convenience function
for module in features.modules:
self.assertEqual(features.check_module(module),
features.check(module))
for codec in features.codecs:
self.assertEqual(features.check_codec(codec),
features.check(codec))
for feature in features.features:
self.assertEqual(features.check_feature(feature),
features.check(feature))
@unittest.skipUnless(HAVE_WEBP, True)
def check_webp_transparency(self):
self.assertEqual(features.check('transp_webp'),
not _webp.WebPDecoderBuggyAlpha())
self.assertEqual(features.check('transp_webp'),
_webp.HAVE_TRANSPARENCY)
@unittest.skipUnless(HAVE_WEBP, True)
def check_webp_mux(self):
self.assertEqual(features.check('webp_mux'),
_webp.HAVE_WEBPMUX)
def test_check_modules(self):
for feature in features.modules:
self.assertIn(
features.check_module(feature), [True, False, None])
self.assertIn(features.check_module(feature), [True, False])
for feature in features.codecs:
self.assertIn(features.check_codec(feature), [True, False])
def test_supported_features(self):
def test_supported_modules(self):
self.assertIsInstance(features.get_supported_modules(), list)
self.assertIsInstance(features.get_supported_codecs(), list)
self.assertIsInstance(features.get_supported_features(), list)
self.assertIsInstance(features.get_supported(), list)
def test_unsupported_codec(self):
# Arrange

13
_webp.c
View File

@ -247,8 +247,12 @@ PyObject* WebPDecoderVersion_wrapper(PyObject* self, PyObject* args){
* The version of webp that ships with (0.1.3) Ubuntu 12.04 doesn't handle alpha well.
* Files that are valid with 0.3 are reported as being invalid.
*/
int WebPDecoderBuggyAlpha() {
return WebPGetDecoderVersion()==0x0103;
}
PyObject* WebPDecoderBuggyAlpha_wrapper(PyObject* self, PyObject* args){
return Py_BuildValue("i", WebPGetDecoderVersion()==0x0103);
return Py_BuildValue("i", WebPDecoderBuggyAlpha());
}
static PyMethodDef webpMethods[] =
@ -268,6 +272,11 @@ void addMuxFlagToModule(PyObject* m) {
#endif
}
void addTransparencyFlagToModule(PyObject* m) {
PyModule_AddObject(m, "HAVE_TRANSPARENCY",
PyBool_FromLong(!WebPDecoderBuggyAlpha()));
}
#if PY_VERSION_HEX >= 0x03000000
PyMODINIT_FUNC
@ -284,6 +293,7 @@ PyInit__webp(void) {
m = PyModule_Create(&module_def);
addMuxFlagToModule(m);
addTransparencyFlagToModule(m);
return m;
}
#else
@ -292,5 +302,6 @@ init_webp(void)
{
PyObject* m = Py_InitModule("_webp", webpMethods);
addMuxFlagToModule(m);
addTransparencyFlagToModule(m);
}
#endif

View File

@ -178,25 +178,14 @@ if __name__ == "__main__":
("freetype2", "FREETYPE2"),
("littlecms2", "LITTLECMS2"),
("webp", "WEBP"),
("transp_webp", "Transparent WEBP")
]:
supported = features.check_module(name)
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 name, feature in [
("transp_webp", "Transparent WEBP"),
("webp_mux", "WEBPMUX"),
("jpg", "JPEG"),
("jpg_2000", "OPENJPEG (JPEG2000)"),
("zlib", "ZLIB (PNG/ZIP)"),
("libtiff", "LIBTIFF")
]:
if features.check_codec(name):
if features.check(name):
print("---", feature, "support ok")
else:
print("***", feature, "support not installed")