Merge pull request #3169 from radarhere/support

Add warnings if image file identification fails due to lack of support
This commit is contained in:
Hugo 2018-09-30 09:28:34 +03:00 committed by GitHub
commit 8344aec583
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
3 changed files with 43 additions and 10 deletions

View File

@ -1,6 +1,6 @@
from helper import unittest, PillowTestCase, hopper from helper import unittest, PillowTestCase, hopper
from PIL import Image from PIL import Image, WebPImagePlugin
try: try:
from PIL import _webp from PIL import _webp
@ -13,15 +13,27 @@ class TestFileWebp(PillowTestCase):
def setUp(self): def setUp(self):
if not HAVE_WEBP: if not HAVE_WEBP:
self.skipTest('WebP support not installed')
return return
self.rgb_mode = "RGB" self.rgb_mode = "RGB"
def test_unsupported(self):
if HAVE_WEBP:
WebPImagePlugin.SUPPORTED = False
file_path = "Tests/images/hopper.webp"
self.assert_warning(UserWarning,
lambda: self.assertRaises(IOError, Image.open, file_path))
if HAVE_WEBP:
WebPImagePlugin.SUPPORTED = True
@unittest.skipIf(not HAVE_WEBP, "WebP support not installed")
def test_version(self): def test_version(self):
_webp.WebPDecoderVersion() _webp.WebPDecoderVersion()
_webp.WebPDecoderBuggyAlpha() _webp.WebPDecoderBuggyAlpha()
@unittest.skipIf(not HAVE_WEBP, "WebP support not installed")
def test_read_rgb(self): def test_read_rgb(self):
""" """
Can we read a RGB mode WebP file without error? Can we read a RGB mode WebP file without error?
@ -41,6 +53,7 @@ class TestFileWebp(PillowTestCase):
self.assert_image_similar_tofile( self.assert_image_similar_tofile(
image, 'Tests/images/hopper_webp_bits.ppm', 1.0) image, 'Tests/images/hopper_webp_bits.ppm', 1.0)
@unittest.skipIf(not HAVE_WEBP, "WebP support not installed")
def test_write_rgb(self): def test_write_rgb(self):
""" """
Can we write a RGB mode file to webp without error. Can we write a RGB mode file to webp without error.
@ -70,6 +83,7 @@ class TestFileWebp(PillowTestCase):
target = hopper(self.rgb_mode) target = hopper(self.rgb_mode)
self.assert_image_similar(image, target, 12.0) self.assert_image_similar(image, target, 12.0)
@unittest.skipIf(not HAVE_WEBP, "WebP support not installed")
def test_write_unsupported_mode_L(self): def test_write_unsupported_mode_L(self):
""" """
Saving a black-and-white file to WebP format should work, and be Saving a black-and-white file to WebP format should work, and be
@ -90,6 +104,7 @@ class TestFileWebp(PillowTestCase):
self.assert_image_similar(image, target, 10.0) self.assert_image_similar(image, target, 10.0)
@unittest.skipIf(not HAVE_WEBP, "WebP support not installed")
def test_write_unsupported_mode_P(self): def test_write_unsupported_mode_P(self):
""" """
Saving a palette-based file to WebP format should work, and be Saving a palette-based file to WebP format should work, and be
@ -110,6 +125,7 @@ class TestFileWebp(PillowTestCase):
self.assert_image_similar(image, target, 50.0) self.assert_image_similar(image, target, 50.0)
@unittest.skipIf(not HAVE_WEBP, "WebP support not installed")
def test_WebPEncode_with_invalid_args(self): def test_WebPEncode_with_invalid_args(self):
""" """
Calling encoder functions with no arguments should result in an error. Calling encoder functions with no arguments should result in an error.
@ -119,6 +135,7 @@ class TestFileWebp(PillowTestCase):
self.assertRaises(TypeError, _webp.WebPAnimEncoder) self.assertRaises(TypeError, _webp.WebPAnimEncoder)
self.assertRaises(TypeError, _webp.WebPEncode) self.assertRaises(TypeError, _webp.WebPEncode)
@unittest.skipIf(not HAVE_WEBP, "WebP support not installed")
def test_WebPDecode_with_invalid_args(self): def test_WebPDecode_with_invalid_args(self):
""" """
Calling decoder functions with no arguments should result in an error. Calling decoder functions with no arguments should result in an error.
@ -128,6 +145,7 @@ class TestFileWebp(PillowTestCase):
self.assertRaises(TypeError, _webp.WebPAnimDecoder) self.assertRaises(TypeError, _webp.WebPAnimDecoder)
self.assertRaises(TypeError, _webp.WebPDecode) self.assertRaises(TypeError, _webp.WebPDecode)
@unittest.skipIf(not HAVE_WEBP, "WebP support not installed")
def test_no_resource_warning(self): def test_no_resource_warning(self):
file_path = "Tests/images/hopper.webp" file_path = "Tests/images/hopper.webp"
image = Image.open(file_path) image = Image.open(file_path)

View File

@ -2615,11 +2615,15 @@ def open(fp, mode="r"):
preinit() preinit()
accept_warnings = []
def _open_core(fp, filename, prefix): def _open_core(fp, filename, prefix):
for i in ID: for i in ID:
try: try:
factory, accept = OPEN[i] factory, accept = OPEN[i]
if not accept or accept(prefix): result = not accept or accept(prefix)
if type(result) in [str, bytes]:
accept_warnings.append(result)
elif result:
fp.seek(0) fp.seek(0)
im = factory(fp, filename) im = factory(fp, filename)
_decompression_bomb_check(im.size) _decompression_bomb_check(im.size)
@ -2643,6 +2647,8 @@ def open(fp, mode="r"):
if exclusive_fp: if exclusive_fp:
fp.close() fp.close()
for message in accept_warnings:
warnings.warn(message)
raise IOError("cannot identify image file %r" raise IOError("cannot identify image file %r"
% (filename if filename else fp)) % (filename if filename else fp))

View File

@ -1,4 +1,9 @@
from . import Image, ImageFile, _webp from . import Image, ImageFile
try:
from . import _webp
SUPPORTED = True
except ImportError as e:
SUPPORTED = False
from io import BytesIO from io import BytesIO
@ -25,7 +30,10 @@ def _accept(prefix):
is_webp_file = prefix[8:12] == b"WEBP" is_webp_file = prefix[8:12] == b"WEBP"
is_valid_vp8_mode = prefix[12:16] in _VP8_MODES_BY_IDENTIFIER is_valid_vp8_mode = prefix[12:16] in _VP8_MODES_BY_IDENTIFIER
return is_riff_file_format and is_webp_file and is_valid_vp8_mode if is_riff_file_format and is_webp_file and is_valid_vp8_mode:
if not SUPPORTED:
return "image file could not be identified because WEBP support not installed"
return True
class WebPImageFile(ImageFile.ImageFile): class WebPImageFile(ImageFile.ImageFile):
@ -321,8 +329,9 @@ def _save(im, fp, filename):
Image.register_open(WebPImageFile.format, WebPImageFile, _accept) Image.register_open(WebPImageFile.format, WebPImageFile, _accept)
Image.register_save(WebPImageFile.format, _save) if SUPPORTED:
if _webp.HAVE_WEBPANIM: Image.register_save(WebPImageFile.format, _save)
Image.register_save_all(WebPImageFile.format, _save_all) if _webp.HAVE_WEBPANIM:
Image.register_extension(WebPImageFile.format, ".webp") Image.register_save_all(WebPImageFile.format, _save_all)
Image.register_mime(WebPImageFile.format, "image/webp") Image.register_extension(WebPImageFile.format, ".webp")
Image.register_mime(WebPImageFile.format, "image/webp")