mirror of
https://github.com/python-pillow/Pillow.git
synced 2026-01-09 18:21:22 +03:00
Add ImageFile context manager (#9367)
This commit is contained in:
commit
8dee8dd5ba
|
|
@ -164,7 +164,7 @@ def test_reduce() -> None:
|
|||
with Image.open("Tests/images/test-card-lossless.jp2") as im:
|
||||
assert callable(im.reduce)
|
||||
|
||||
im.reduce = 2
|
||||
im.reduce = 2 # type: ignore[assignment, method-assign]
|
||||
assert im.reduce == 2
|
||||
|
||||
im.load()
|
||||
|
|
|
|||
|
|
@ -823,7 +823,7 @@ class TestFilePng:
|
|||
monkeypatch.setattr(sys, "stdout", mystdout)
|
||||
|
||||
with Image.open(TEST_PNG_FILE) as im:
|
||||
im.save(sys.stdout, "PNG")
|
||||
im.save(sys.stdout, "PNG") # type: ignore[arg-type]
|
||||
|
||||
if isinstance(mystdout, MyStdOut):
|
||||
mystdout = mystdout.buffer
|
||||
|
|
|
|||
|
|
@ -389,7 +389,7 @@ def test_save_stdout(buffer: bool, monkeypatch: pytest.MonkeyPatch) -> None:
|
|||
monkeypatch.setattr(sys, "stdout", mystdout)
|
||||
|
||||
with Image.open(TEST_FILE) as im:
|
||||
im.save(sys.stdout, "PPM")
|
||||
im.save(sys.stdout, "PPM") # type: ignore[arg-type]
|
||||
|
||||
if isinstance(mystdout, MyStdOut):
|
||||
mystdout = mystdout.buffer
|
||||
|
|
|
|||
|
|
@ -250,14 +250,14 @@ class TestImageTransform:
|
|||
def test_missing_method_data(self) -> None:
|
||||
with hopper() as im:
|
||||
with pytest.raises(ValueError):
|
||||
im.transform((100, 100), None)
|
||||
im.transform((100, 100), None) # type: ignore[arg-type]
|
||||
|
||||
@pytest.mark.parametrize("resample", (Image.Resampling.BOX, "unknown"))
|
||||
def test_unknown_resampling_filter(self, resample: Image.Resampling | str) -> None:
|
||||
with hopper() as im:
|
||||
(w, h) = im.size
|
||||
with pytest.raises(ValueError):
|
||||
im.transform((100, 100), Image.Transform.EXTENT, (0, 0, w, h), resample)
|
||||
im.transform((100, 100), Image.Transform.EXTENT, (0, 0, w, h), resample) # type: ignore[arg-type]
|
||||
|
||||
|
||||
class TestImageTransformAffine:
|
||||
|
|
|
|||
|
|
@ -590,16 +590,11 @@ class Image:
|
|||
return new
|
||||
|
||||
# Context manager support
|
||||
def __enter__(self):
|
||||
def __enter__(self) -> Image:
|
||||
return self
|
||||
|
||||
def __exit__(self, *args):
|
||||
from . import ImageFile
|
||||
|
||||
if isinstance(self, ImageFile.ImageFile):
|
||||
if getattr(self, "_exclusive_fp", False):
|
||||
self._close_fp()
|
||||
self.fp = None
|
||||
def __exit__(self, *args: object) -> None:
|
||||
pass
|
||||
|
||||
def close(self) -> None:
|
||||
"""
|
||||
|
|
|
|||
|
|
@ -131,6 +131,7 @@ class ImageFile(Image.Image):
|
|||
self.decoderconfig: tuple[Any, ...] = ()
|
||||
self.decodermaxblock = MAXBLOCK
|
||||
|
||||
self.fp: IO[bytes] | None
|
||||
self._fp: IO[bytes] | DeferredError
|
||||
if is_path(fp):
|
||||
# filename
|
||||
|
|
@ -168,6 +169,10 @@ class ImageFile(Image.Image):
|
|||
def _open(self) -> None:
|
||||
pass
|
||||
|
||||
# Context manager support
|
||||
def __enter__(self) -> ImageFile:
|
||||
return self
|
||||
|
||||
def _close_fp(self) -> None:
|
||||
if getattr(self, "_fp", False) and not isinstance(self._fp, DeferredError):
|
||||
if self._fp != self.fp:
|
||||
|
|
@ -176,6 +181,11 @@ class ImageFile(Image.Image):
|
|||
if self.fp:
|
||||
self.fp.close()
|
||||
|
||||
def __exit__(self, *args: object) -> None:
|
||||
if getattr(self, "_exclusive_fp", False):
|
||||
self._close_fp()
|
||||
self.fp = None
|
||||
|
||||
def close(self) -> None:
|
||||
"""
|
||||
Closes the file pointer, if possible.
|
||||
|
|
@ -268,7 +278,7 @@ class ImageFile(Image.Image):
|
|||
|
||||
# raise exception if something's wrong. must be called
|
||||
# directly after open, and closes file when finished.
|
||||
if self._exclusive_fp:
|
||||
if self._exclusive_fp and self.fp:
|
||||
self.fp.close()
|
||||
self.fp = None
|
||||
|
||||
|
|
|
|||
Loading…
Reference in New Issue
Block a user