Added Image.WARN_POSSIBLE_FORMATS

This commit is contained in:
Andrew Murray 2024-05-16 17:47:35 +10:00
parent 0da83a1164
commit 1036aa74a7
3 changed files with 24 additions and 7 deletions

View File

@ -116,6 +116,17 @@ 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"")
Image.WARN_POSSIBLE_FORMATS = True
try:
with pytest.warns(UserWarning):
with pytest.raises(UnidentifiedImageError):
with Image.open(im):
pass
finally:
Image.WARN_POSSIBLE_FORMATS = False
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

@ -374,6 +374,11 @@ Constants
Set to 89,478,485, approximately 0.25GB for a 24-bit (3 bpp) image. Set to 89,478,485, approximately 0.25GB for a 24-bit (3 bpp) image.
See :py:meth:`~PIL.Image.open` for more information about how this is used. See :py:meth:`~PIL.Image.open` for more information about how this is used.
.. data:: WARN_POSSIBLE_FORMATS
Set to false. If true, when an image cannot be identified, warnings will be raised
from formats that attempted to read the data.
Transpose methods Transpose methods
^^^^^^^^^^^^^^^^^ ^^^^^^^^^^^^^^^^^

View File

@ -76,6 +76,8 @@ class DecompressionBombError(Exception):
pass pass
WARN_POSSIBLE_FORMATS: bool = False
# Limit to around a quarter gigabyte for a 24-bit (3 bpp) image # Limit to around a quarter gigabyte for a 24-bit (3 bpp) image
MAX_IMAGE_PIXELS: int | None = int(1024 * 1024 * 1024 // 4 // 3) MAX_IMAGE_PIXELS: int | None = int(1024 * 1024 * 1024 // 4 // 3)
@ -3344,7 +3346,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],
@ -3360,16 +3362,15 @@ 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 if WARN_POSSIBLE_FORMATS:
# opening failures that are entirely expected. warning_messages.append(i + " opening failed. " + str(e))
# logger.debug("", exc_info=True)
continue continue
except BaseException: except BaseException:
if exclusive_fp: if exclusive_fp:
@ -3395,7 +3396,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)