mirror of
https://github.com/python-pillow/Pillow.git
synced 2025-01-13 10:46:16 +03:00
Merge pull request #6213 from radarhere/fp
This commit is contained in:
commit
2c58c3ee11
|
@ -637,6 +637,15 @@ def test_apng_save_blend(tmp_path):
|
|||
assert im.getpixel((0, 0)) == (0, 255, 0, 255)
|
||||
|
||||
|
||||
def test_seek_after_close():
|
||||
im = Image.open("Tests/images/apng/delay.png")
|
||||
im.seek(1)
|
||||
im.close()
|
||||
|
||||
with pytest.raises(ValueError):
|
||||
im.seek(0)
|
||||
|
||||
|
||||
def test_constants_deprecation():
|
||||
for enum, prefix in {
|
||||
PngImagePlugin.Disposal: "APNG_DISPOSE_",
|
||||
|
|
|
@ -46,6 +46,15 @@ def test_closed_file():
|
|||
im.close()
|
||||
|
||||
|
||||
def test_seek_after_close():
|
||||
im = Image.open(animated_test_file)
|
||||
im.seek(1)
|
||||
im.close()
|
||||
|
||||
with pytest.raises(ValueError):
|
||||
im.seek(0)
|
||||
|
||||
|
||||
def test_context_manager():
|
||||
with warnings.catch_warnings():
|
||||
with Image.open(static_test_file) as im:
|
||||
|
|
|
@ -46,6 +46,19 @@ def test_closed_file():
|
|||
im.close()
|
||||
|
||||
|
||||
def test_seek_after_close():
|
||||
im = Image.open("Tests/images/iss634.gif")
|
||||
im.load()
|
||||
im.close()
|
||||
|
||||
with pytest.raises(ValueError):
|
||||
im.is_animated
|
||||
with pytest.raises(ValueError):
|
||||
im.n_frames
|
||||
with pytest.raises(ValueError):
|
||||
im.seek(1)
|
||||
|
||||
|
||||
def test_context_manager():
|
||||
with warnings.catch_warnings():
|
||||
with Image.open(TEST_GIF) as im:
|
||||
|
|
|
@ -48,6 +48,14 @@ def test_closed_file():
|
|||
im.close()
|
||||
|
||||
|
||||
def test_seek_after_close():
|
||||
im = Image.open(test_files[0])
|
||||
im.close()
|
||||
|
||||
with pytest.raises(ValueError):
|
||||
im.seek(1)
|
||||
|
||||
|
||||
def test_context_manager():
|
||||
with warnings.catch_warnings():
|
||||
with Image.open(test_files[0]) as im:
|
||||
|
|
|
@ -70,6 +70,15 @@ class TestFileTiff:
|
|||
im.load()
|
||||
im.close()
|
||||
|
||||
def test_seek_after_close(self):
|
||||
im = Image.open("Tests/images/multipage.tiff")
|
||||
im.close()
|
||||
|
||||
with pytest.raises(ValueError):
|
||||
im.n_frames
|
||||
with pytest.raises(ValueError):
|
||||
im.seek(1)
|
||||
|
||||
def test_context_manager(self):
|
||||
with warnings.catch_warnings():
|
||||
with Image.open("Tests/images/multipage.tiff") as im:
|
||||
|
|
|
@ -57,7 +57,7 @@ class DcxImageFile(PcxImageFile):
|
|||
break
|
||||
self._offset.append(offset)
|
||||
|
||||
self.__fp = self.fp
|
||||
self._fp = self.fp
|
||||
self.frame = None
|
||||
self.n_frames = len(self._offset)
|
||||
self.is_animated = self.n_frames > 1
|
||||
|
@ -67,22 +67,13 @@ class DcxImageFile(PcxImageFile):
|
|||
if not self._seek_check(frame):
|
||||
return
|
||||
self.frame = frame
|
||||
self.fp = self.__fp
|
||||
self.fp = self._fp
|
||||
self.fp.seek(self._offset[frame])
|
||||
PcxImageFile._open(self)
|
||||
|
||||
def tell(self):
|
||||
return self.frame
|
||||
|
||||
def _close__fp(self):
|
||||
try:
|
||||
if self.__fp != self.fp:
|
||||
self.__fp.close()
|
||||
except AttributeError:
|
||||
pass
|
||||
finally:
|
||||
self.__fp = None
|
||||
|
||||
|
||||
Image.register_open(DcxImageFile.format, DcxImageFile, _accept)
|
||||
|
||||
|
|
|
@ -91,7 +91,7 @@ class FliImageFile(ImageFile.ImageFile):
|
|||
|
||||
# set things up to decode first frame
|
||||
self.__frame = -1
|
||||
self.__fp = self.fp
|
||||
self._fp = self.fp
|
||||
self.__rewind = self.fp.tell()
|
||||
self.seek(0)
|
||||
|
||||
|
@ -125,7 +125,7 @@ class FliImageFile(ImageFile.ImageFile):
|
|||
def _seek(self, frame):
|
||||
if frame == 0:
|
||||
self.__frame = -1
|
||||
self.__fp.seek(self.__rewind)
|
||||
self._fp.seek(self.__rewind)
|
||||
self.__offset = 128
|
||||
else:
|
||||
# ensure that the previous frame was loaded
|
||||
|
@ -136,7 +136,7 @@ class FliImageFile(ImageFile.ImageFile):
|
|||
self.__frame = frame
|
||||
|
||||
# move to next frame
|
||||
self.fp = self.__fp
|
||||
self.fp = self._fp
|
||||
self.fp.seek(self.__offset)
|
||||
|
||||
s = self.fp.read(4)
|
||||
|
@ -153,15 +153,6 @@ class FliImageFile(ImageFile.ImageFile):
|
|||
def tell(self):
|
||||
return self.__frame
|
||||
|
||||
def _close__fp(self):
|
||||
try:
|
||||
if self.__fp != self.fp:
|
||||
self.__fp.close()
|
||||
except AttributeError:
|
||||
pass
|
||||
finally:
|
||||
self.__fp = None
|
||||
|
||||
|
||||
#
|
||||
# registry
|
||||
|
|
|
@ -102,7 +102,7 @@ class GifImageFile(ImageFile.ImageFile):
|
|||
p = ImagePalette.raw("RGB", p)
|
||||
self.global_palette = self.palette = p
|
||||
|
||||
self.__fp = self.fp # FIXME: hack
|
||||
self._fp = self.fp # FIXME: hack
|
||||
self.__rewind = self.fp.tell()
|
||||
self._n_frames = None
|
||||
self._is_animated = None
|
||||
|
@ -161,7 +161,7 @@ class GifImageFile(ImageFile.ImageFile):
|
|||
self.__offset = 0
|
||||
self.dispose = None
|
||||
self.__frame = -1
|
||||
self.__fp.seek(self.__rewind)
|
||||
self._fp.seek(self.__rewind)
|
||||
self.disposal_method = 0
|
||||
else:
|
||||
# ensure that the previous frame was loaded
|
||||
|
@ -171,7 +171,7 @@ class GifImageFile(ImageFile.ImageFile):
|
|||
if frame != self.__frame + 1:
|
||||
raise ValueError(f"cannot seek to frame {frame}")
|
||||
|
||||
self.fp = self.__fp
|
||||
self.fp = self._fp
|
||||
if self.__offset:
|
||||
# backup to last frame
|
||||
self.fp.seek(self.__offset)
|
||||
|
@ -281,7 +281,7 @@ class GifImageFile(ImageFile.ImageFile):
|
|||
s = None
|
||||
|
||||
if interlace is None:
|
||||
# self.__fp = None
|
||||
# self._fp = None
|
||||
raise EOFError
|
||||
if not update_image:
|
||||
return
|
||||
|
@ -443,15 +443,6 @@ class GifImageFile(ImageFile.ImageFile):
|
|||
def tell(self):
|
||||
return self.__frame
|
||||
|
||||
def _close__fp(self):
|
||||
try:
|
||||
if self.__fp != self.fp:
|
||||
self.__fp.close()
|
||||
except AttributeError:
|
||||
pass
|
||||
finally:
|
||||
self.__fp = None
|
||||
|
||||
|
||||
# --------------------------------------------------------------------
|
||||
# Write GIF files
|
||||
|
|
|
@ -245,7 +245,7 @@ class ImImageFile(ImageFile.ImageFile):
|
|||
|
||||
self.__offset = offs = self.fp.tell()
|
||||
|
||||
self.__fp = self.fp # FIXME: hack
|
||||
self._fp = self.fp # FIXME: hack
|
||||
|
||||
if self.rawmode[:2] == "F;":
|
||||
|
||||
|
@ -294,22 +294,13 @@ class ImImageFile(ImageFile.ImageFile):
|
|||
size = ((self.size[0] * bits + 7) // 8) * self.size[1]
|
||||
offs = self.__offset + frame * size
|
||||
|
||||
self.fp = self.__fp
|
||||
self.fp = self._fp
|
||||
|
||||
self.tile = [("raw", (0, 0) + self.size, offs, (self.rawmode, 0, -1))]
|
||||
|
||||
def tell(self):
|
||||
return self.frame
|
||||
|
||||
def _close__fp(self):
|
||||
try:
|
||||
if self.__fp != self.fp:
|
||||
self.__fp.close()
|
||||
except AttributeError:
|
||||
pass
|
||||
finally:
|
||||
self.__fp = None
|
||||
|
||||
|
||||
#
|
||||
# --------------------------------------------------------------------
|
||||
|
|
|
@ -549,8 +549,10 @@ class Image:
|
|||
|
||||
def __exit__(self, *args):
|
||||
if hasattr(self, "fp") and getattr(self, "_exclusive_fp", False):
|
||||
if hasattr(self, "_close__fp"):
|
||||
self._close__fp()
|
||||
if getattr(self, "_fp", False):
|
||||
if self._fp != self.fp:
|
||||
self._fp.close()
|
||||
self._fp = DeferredError(ValueError("Operation on closed image"))
|
||||
if self.fp:
|
||||
self.fp.close()
|
||||
self.fp = None
|
||||
|
@ -568,8 +570,10 @@ class Image:
|
|||
more information.
|
||||
"""
|
||||
try:
|
||||
if hasattr(self, "_close__fp"):
|
||||
self._close__fp()
|
||||
if getattr(self, "_fp", False):
|
||||
if self._fp != self.fp:
|
||||
self._fp.close()
|
||||
self._fp = DeferredError(ValueError("Operation on closed image"))
|
||||
if self.fp:
|
||||
self.fp.close()
|
||||
self.fp = None
|
||||
|
|
|
@ -62,7 +62,6 @@ class MicImageFile(TiffImagePlugin.TiffImageFile):
|
|||
if not self.images:
|
||||
raise SyntaxError("not an MIC file; no image entries")
|
||||
|
||||
self.__fp = self.fp
|
||||
self.frame = None
|
||||
self._n_frames = len(self.images)
|
||||
self.is_animated = self._n_frames > 1
|
||||
|
@ -89,15 +88,6 @@ class MicImageFile(TiffImagePlugin.TiffImageFile):
|
|||
def tell(self):
|
||||
return self.frame
|
||||
|
||||
def _close__fp(self):
|
||||
try:
|
||||
if self.__fp != self.fp:
|
||||
self.__fp.close()
|
||||
except AttributeError:
|
||||
pass
|
||||
finally:
|
||||
self.__fp = None
|
||||
|
||||
|
||||
#
|
||||
# --------------------------------------------------------------------
|
||||
|
|
|
@ -58,20 +58,20 @@ class MpoImageFile(JpegImagePlugin.JpegImageFile):
|
|||
assert self.n_frames == len(self.__mpoffsets)
|
||||
del self.info["mpoffset"] # no longer needed
|
||||
self.is_animated = self.n_frames > 1
|
||||
self.__fp = self.fp # FIXME: hack
|
||||
self.__fp.seek(self.__mpoffsets[0]) # get ready to read first frame
|
||||
self._fp = self.fp # FIXME: hack
|
||||
self._fp.seek(self.__mpoffsets[0]) # get ready to read first frame
|
||||
self.__frame = 0
|
||||
self.offset = 0
|
||||
# for now we can only handle reading and individual frame extraction
|
||||
self.readonly = 1
|
||||
|
||||
def load_seek(self, pos):
|
||||
self.__fp.seek(pos)
|
||||
self._fp.seek(pos)
|
||||
|
||||
def seek(self, frame):
|
||||
if not self._seek_check(frame):
|
||||
return
|
||||
self.fp = self.__fp
|
||||
self.fp = self._fp
|
||||
self.offset = self.__mpoffsets[frame]
|
||||
|
||||
self.fp.seek(self.offset + 2) # skip SOI marker
|
||||
|
@ -97,15 +97,6 @@ class MpoImageFile(JpegImagePlugin.JpegImageFile):
|
|||
def tell(self):
|
||||
return self.__frame
|
||||
|
||||
def _close__fp(self):
|
||||
try:
|
||||
if self.__fp != self.fp:
|
||||
self.__fp.close()
|
||||
except AttributeError:
|
||||
pass
|
||||
finally:
|
||||
self.__fp = None
|
||||
|
||||
@staticmethod
|
||||
def adopt(jpeg_instance, mpheader=None):
|
||||
"""
|
||||
|
|
|
@ -710,7 +710,7 @@ class PngImageFile(ImageFile.ImageFile):
|
|||
|
||||
if not _accept(self.fp.read(8)):
|
||||
raise SyntaxError("not a PNG file")
|
||||
self.__fp = self.fp
|
||||
self._fp = self.fp
|
||||
self.__frame = 0
|
||||
|
||||
#
|
||||
|
@ -767,7 +767,7 @@ class PngImageFile(ImageFile.ImageFile):
|
|||
self._close_exclusive_fp_after_loading = False
|
||||
self.png.save_rewind()
|
||||
self.__rewind_idat = self.__prepare_idat
|
||||
self.__rewind = self.__fp.tell()
|
||||
self.__rewind = self._fp.tell()
|
||||
if self.default_image:
|
||||
# IDAT chunk contains default image and not first animation frame
|
||||
self.n_frames += 1
|
||||
|
@ -822,7 +822,7 @@ class PngImageFile(ImageFile.ImageFile):
|
|||
def _seek(self, frame, rewind=False):
|
||||
if frame == 0:
|
||||
if rewind:
|
||||
self.__fp.seek(self.__rewind)
|
||||
self._fp.seek(self.__rewind)
|
||||
self.png.rewind()
|
||||
self.__prepare_idat = self.__rewind_idat
|
||||
self.im = None
|
||||
|
@ -830,7 +830,7 @@ class PngImageFile(ImageFile.ImageFile):
|
|||
self.pyaccess = None
|
||||
self.info = self.png.im_info
|
||||
self.tile = self.png.im_tile
|
||||
self.fp = self.__fp
|
||||
self.fp = self._fp
|
||||
self._prev_im = None
|
||||
self.dispose = None
|
||||
self.default_image = self.info.get("default_image", False)
|
||||
|
@ -849,7 +849,7 @@ class PngImageFile(ImageFile.ImageFile):
|
|||
self.im.paste(self.dispose, self.dispose_extent)
|
||||
self._prev_im = self.im.copy()
|
||||
|
||||
self.fp = self.__fp
|
||||
self.fp = self._fp
|
||||
|
||||
# advance to the next frame
|
||||
if self.__prepare_idat:
|
||||
|
@ -1027,15 +1027,6 @@ class PngImageFile(ImageFile.ImageFile):
|
|||
else {}
|
||||
)
|
||||
|
||||
def _close__fp(self):
|
||||
try:
|
||||
if self.__fp != self.fp:
|
||||
self.__fp.close()
|
||||
except AttributeError:
|
||||
pass
|
||||
finally:
|
||||
self.__fp = None
|
||||
|
||||
|
||||
# --------------------------------------------------------------------
|
||||
# PNG writer
|
||||
|
|
|
@ -132,7 +132,7 @@ class PsdImageFile(ImageFile.ImageFile):
|
|||
self.tile = _maketile(self.fp, mode, (0, 0) + self.size, channels)
|
||||
|
||||
# keep the file open
|
||||
self.__fp = self.fp
|
||||
self._fp = self.fp
|
||||
self.frame = 1
|
||||
self._min_frame = 1
|
||||
|
||||
|
@ -146,7 +146,7 @@ class PsdImageFile(ImageFile.ImageFile):
|
|||
self.mode = mode
|
||||
self.tile = tile
|
||||
self.frame = layer
|
||||
self.fp = self.__fp
|
||||
self.fp = self._fp
|
||||
return name, bbox
|
||||
except IndexError as e:
|
||||
raise EOFError("no such layer") from e
|
||||
|
@ -155,15 +155,6 @@ class PsdImageFile(ImageFile.ImageFile):
|
|||
# return layer number (0=image, 1..max=layers)
|
||||
return self.frame
|
||||
|
||||
def _close__fp(self):
|
||||
try:
|
||||
if self.__fp != self.fp:
|
||||
self.__fp.close()
|
||||
except AttributeError:
|
||||
pass
|
||||
finally:
|
||||
self.__fp = None
|
||||
|
||||
|
||||
def _layerinfo(fp, ct_bytes):
|
||||
# read layerinfo block
|
||||
|
|
|
@ -149,7 +149,7 @@ class SpiderImageFile(ImageFile.ImageFile):
|
|||
self.mode = "F"
|
||||
|
||||
self.tile = [("raw", (0, 0) + self.size, offset, (self.rawmode, 0, 1))]
|
||||
self.__fp = self.fp # FIXME: hack
|
||||
self._fp = self.fp # FIXME: hack
|
||||
|
||||
@property
|
||||
def n_frames(self):
|
||||
|
@ -172,7 +172,7 @@ class SpiderImageFile(ImageFile.ImageFile):
|
|||
if not self._seek_check(frame):
|
||||
return
|
||||
self.stkoffset = self.hdrlen + frame * (self.hdrlen + self.imgbytes)
|
||||
self.fp = self.__fp
|
||||
self.fp = self._fp
|
||||
self.fp.seek(self.stkoffset)
|
||||
self._open()
|
||||
|
||||
|
@ -191,15 +191,6 @@ class SpiderImageFile(ImageFile.ImageFile):
|
|||
|
||||
return ImageTk.PhotoImage(self.convert2byte(), palette=256)
|
||||
|
||||
def _close__fp(self):
|
||||
try:
|
||||
if self.__fp != self.fp:
|
||||
self.__fp.close()
|
||||
except AttributeError:
|
||||
pass
|
||||
finally:
|
||||
self.__fp = None
|
||||
|
||||
|
||||
# --------------------------------------------------------------------
|
||||
# Image series
|
||||
|
|
|
@ -1073,7 +1073,7 @@ class TiffImageFile(ImageFile.ImageFile):
|
|||
# setup frame pointers
|
||||
self.__first = self.__next = self.tag_v2.next
|
||||
self.__frame = -1
|
||||
self.__fp = self.fp
|
||||
self._fp = self.fp
|
||||
self._frame_pos = []
|
||||
self._n_frames = None
|
||||
|
||||
|
@ -1106,7 +1106,7 @@ class TiffImageFile(ImageFile.ImageFile):
|
|||
self.im = Image.core.new(self.mode, self.size)
|
||||
|
||||
def _seek(self, frame):
|
||||
self.fp = self.__fp
|
||||
self.fp = self._fp
|
||||
|
||||
# reset buffered io handle in case fp
|
||||
# was passed to libtiff, invalidating the buffer
|
||||
|
@ -1515,15 +1515,6 @@ class TiffImageFile(ImageFile.ImageFile):
|
|||
|
||||
self._tile_orientation = self.tag_v2.get(0x0112)
|
||||
|
||||
def _close__fp(self):
|
||||
try:
|
||||
if self.__fp != self.fp:
|
||||
self.__fp.close()
|
||||
except AttributeError:
|
||||
pass
|
||||
finally:
|
||||
self.__fp = None
|
||||
|
||||
|
||||
#
|
||||
# --------------------------------------------------------------------
|
||||
|
|
Loading…
Reference in New Issue
Block a user