Added argument to raise warnings on UnidentifiedImageError

This commit is contained in:
Andrew Murray 2024-04-30 13:11:40 +10:00
parent 9b1390792c
commit f91eb8e071
2 changed files with 16 additions and 4 deletions

View File

@ -117,6 +117,13 @@ class TestImage:
assert im.mode == "RGB" assert im.mode == "RGB"
assert im.size == (128, 128) assert im.size == (128, 128)
def test_open_verbose_failure(self) -> None:
im = io.BytesIO(b"")
with pytest.warns(UserWarning):
with pytest.raises(UnidentifiedImageError):
with Image.open(im, warn_possible_formats=True):
pass
def test_width_height(self) -> None: def test_width_height(self) -> None:
im = Image.new("RGB", (1, 2)) im = Image.new("RGB", (1, 2))
assert im.width == 1 assert im.width == 1

View File

@ -3251,6 +3251,7 @@ def open(
fp: StrOrBytesPath | IO[bytes], fp: StrOrBytesPath | IO[bytes],
mode: Literal["r"] = "r", mode: Literal["r"] = "r",
formats: list[str] | tuple[str, ...] | None = None, formats: list[str] | tuple[str, ...] | None = None,
warn_possible_formats: bool = False,
) -> ImageFile.ImageFile: ) -> ImageFile.ImageFile:
""" """
Opens and identifies the given image file. Opens and identifies the given image file.
@ -3272,6 +3273,8 @@ def open(
Pass ``None`` to try all supported formats. You can print the set of Pass ``None`` to try all supported formats. You can print the set of
available formats by running ``python3 -m PIL`` or using available formats by running ``python3 -m PIL`` or using
the :py:func:`PIL.features.pilinfo` function. the :py:func:`PIL.features.pilinfo` function.
:param warn_possible_formats: If an image cannot be identified, raise warnings
from formats that attempted to read the data.
:returns: An :py:class:`~PIL.Image.Image` object. :returns: An :py:class:`~PIL.Image.Image` object.
:exception FileNotFoundError: If the file cannot be found. :exception FileNotFoundError: If the file cannot be found.
:exception PIL.UnidentifiedImageError: If the image cannot be opened and :exception PIL.UnidentifiedImageError: If the image cannot be opened and
@ -3318,7 +3321,7 @@ def open(
preinit() preinit()
accept_warnings: list[str] = [] warning_messages: list[str] = []
def _open_core( def _open_core(
fp: IO[bytes], fp: IO[bytes],
@ -3334,16 +3337,18 @@ def open(
factory, accept = OPEN[i] factory, accept = OPEN[i]
result = not accept or accept(prefix) result = not accept or accept(prefix)
if isinstance(result, str): if isinstance(result, str):
accept_warnings.append(result) warning_messages.append(result)
elif 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)
return im return im
except (SyntaxError, IndexError, TypeError, struct.error): except (SyntaxError, IndexError, TypeError, struct.error) as e:
# Leave disabled by default, spams the logs with image # Leave disabled by default, spams the logs with image
# opening failures that are entirely expected. # opening failures that are entirely expected.
# logger.debug("", exc_info=True) # logger.debug("", exc_info=True)
if warn_possible_formats:
warning_messages.append(i + " opening failed. " + str(e))
continue continue
except BaseException: except BaseException:
if exclusive_fp: if exclusive_fp:
@ -3369,7 +3374,7 @@ def open(
if exclusive_fp: if exclusive_fp:
fp.close() fp.close()
for message in accept_warnings: for message in warning_messages:
warnings.warn(message) warnings.warn(message)
msg = "cannot identify image file %r" % (filename if filename else fp) msg = "cannot identify image file %r" % (filename if filename else fp)
raise UnidentifiedImageError(msg) raise UnidentifiedImageError(msg)