Added "closed" attribute to images

This commit is contained in:
Andrew Murray 2023-03-04 00:17:52 +11:00
parent 01520de6f7
commit 062753e6a8
3 changed files with 21 additions and 3 deletions

View File

@ -928,6 +928,17 @@ class TestImage:
im.apply_transparency() im.apply_transparency()
assert im.palette.colors[(27, 35, 6, 214)] == 24 assert im.palette.colors[(27, 35, 6, 214)] == 24
def test_closed(self):
im = Image.open("Tests/images/hopper.jpg")
assert not im.closed
im.close()
assert im.closed
with Image.open("Tests/images/hopper.jpg") as im:
assert not im.closed
assert im.closed
def test_categories_deprecation(self): def test_categories_deprecation(self):
with pytest.warns(DeprecationWarning): with pytest.warns(DeprecationWarning):
assert hopper().category == 0 assert hopper().category == 0

View File

@ -41,6 +41,7 @@ Image Lifecycle
* ``Image.open()`` Filenames and ``Path`` objects are opened as a file. * ``Image.open()`` Filenames and ``Path`` objects are opened as a file.
Metadata is read from the open file. The file is left open for further usage. Metadata is read from the open file. The file is left open for further usage.
When an image is created, the ``closed`` property is set to ``False``.
* ``Image.Image.load()`` When the pixel data from the image is * ``Image.Image.load()`` When the pixel data from the image is
required, ``load()`` is called. The current frame is read into required, ``load()`` is called. The current frame is read into
@ -58,14 +59,16 @@ Image Lifecycle
(e.g. multipage TIFF and animated GIF) the image file is left open so that (e.g. multipage TIFF and animated GIF) the image file is left open so that
``Image.Image.seek()`` can load the appropriate frame. ``Image.Image.seek()`` can load the appropriate frame.
* ``Image.Image.close()`` Closes the file and destroys the core image object. * ``Image.Image.close()`` Closes the file, sets the ``closed`` property to
``True`` and destroys the core image object.
The Pillow context manager will also close the file, but will not destroy The Pillow context manager will also close the file and update the ``closed``
the core image object. e.g.:: property, but will not destroy the core image object. e.g.::
with Image.open("test.jpg") as img: with Image.open("test.jpg") as img:
img.load() img.load()
assert img.fp is None assert img.fp is None
assert img.closed
img.save("test.png") img.save("test.png")

View File

@ -519,6 +519,7 @@ class Image:
self._category = 0 self._category = 0
self.readonly = 0 self.readonly = 0
self.pyaccess = None self.pyaccess = None
self.closed = False
self._exif = None self._exif = None
def __getattr__(self, name): def __getattr__(self, name):
@ -567,6 +568,7 @@ class Image:
if self.fp: if self.fp:
self.fp.close() self.fp.close()
self.fp = None self.fp = None
self.closed = True
def close(self): def close(self):
""" """
@ -594,6 +596,8 @@ class Image:
if getattr(self, "map", None): if getattr(self, "map", None):
self.map = None self.map = None
self.closed = True
# Instead of simply setting to None, we're setting up a # Instead of simply setting to None, we're setting up a
# deferred error that will better explain that the core image # deferred error that will better explain that the core image
# object is gone. # object is gone.