mirror of
https://github.com/python-pillow/Pillow.git
synced 2024-11-10 19:56:47 +03:00
add _close_exclusive_fp_after_load flag
This commit is contained in:
parent
900c5e5bf2
commit
86c1704646
|
@ -41,7 +41,8 @@ class DcxImageFile(PcxImageFile):
|
|||
|
||||
format = "DCX"
|
||||
format_description = "Intel DCX"
|
||||
|
||||
_close_exclusive_fp_after_loading = False
|
||||
|
||||
def _open(self):
|
||||
|
||||
# Header
|
||||
|
@ -58,7 +59,6 @@ class DcxImageFile(PcxImageFile):
|
|||
self._offset.append(offset)
|
||||
|
||||
self.__fp = self.fp
|
||||
self._exclusive_fp = False
|
||||
self.seek(0)
|
||||
|
||||
@property
|
||||
|
|
|
@ -37,7 +37,8 @@ class FliImageFile(ImageFile.ImageFile):
|
|||
|
||||
format = "FLI"
|
||||
format_description = "Autodesk FLI/FLC Animation"
|
||||
|
||||
_close_exclusive_fp_after_loading = False
|
||||
|
||||
def _open(self):
|
||||
|
||||
# HEAD
|
||||
|
@ -84,7 +85,6 @@ class FliImageFile(ImageFile.ImageFile):
|
|||
# set things up to decode first frame
|
||||
self.__frame = -1
|
||||
self.__fp = self.fp
|
||||
self._exclusive_fp = False
|
||||
self.__rewind = self.fp.tell()
|
||||
self._n_frames = None
|
||||
self._is_animated = None
|
||||
|
|
|
@ -47,6 +47,8 @@ class GifImageFile(ImageFile.ImageFile):
|
|||
|
||||
format = "GIF"
|
||||
format_description = "Compuserve GIF"
|
||||
_close_exclusive_fp_after_loading = False
|
||||
|
||||
global_palette = None
|
||||
|
||||
def data(self):
|
||||
|
@ -80,7 +82,6 @@ class GifImageFile(ImageFile.ImageFile):
|
|||
break
|
||||
|
||||
self.__fp = self.fp # FIXME: hack
|
||||
self._exclusive_fp = False
|
||||
self.__rewind = self.fp.tell()
|
||||
self._n_frames = None
|
||||
self._is_animated = None
|
||||
|
|
|
@ -109,6 +109,7 @@ class ImImageFile(ImageFile.ImageFile):
|
|||
|
||||
format = "IM"
|
||||
format_description = "IFUNC Image Memory"
|
||||
_close_exclusive_fp_after_loading = False
|
||||
|
||||
def _open(self):
|
||||
|
||||
|
@ -234,7 +235,6 @@ class ImImageFile(ImageFile.ImageFile):
|
|||
self.__offset = offs = self.fp.tell()
|
||||
|
||||
self.__fp = self.fp # FIXME: hack
|
||||
self._exclusive_fp = False
|
||||
|
||||
if self.rawmode[:2] == "F;":
|
||||
|
||||
|
|
12
PIL/Image.py
12
PIL/Image.py
|
@ -506,6 +506,7 @@ class Image(object):
|
|||
"""
|
||||
format = None
|
||||
format_description = None
|
||||
_close_exclusive_fp_after_loading = True
|
||||
|
||||
def __init__(self):
|
||||
# FIXME: take "new" parameters / other image?
|
||||
|
@ -560,6 +561,7 @@ class Image(object):
|
|||
"""
|
||||
try:
|
||||
self.fp.close()
|
||||
self.fp = None
|
||||
except Exception as msg:
|
||||
logger.debug("Error closing: %s", msg)
|
||||
|
||||
|
@ -568,6 +570,13 @@ class Image(object):
|
|||
# object is gone.
|
||||
self.im = deferred_error(ValueError("Operation on closed image"))
|
||||
|
||||
if sys.version_info >= (3,4,0):
|
||||
def __del__(self):
|
||||
if (hasattr(self, 'fp') and hasattr(self, '_exclusive_fp')
|
||||
and self.fp and self._exclusive_fp):
|
||||
self.fp.close()
|
||||
self.fp = None
|
||||
|
||||
def _copy(self):
|
||||
self.load()
|
||||
self.im = self.im.copy()
|
||||
|
@ -2440,8 +2449,7 @@ def open(fp, mode="r"):
|
|||
im = _open_core(fp, filename, prefix)
|
||||
|
||||
if im:
|
||||
if getattr(im, '_exclusive_fp', 'undef') is None:
|
||||
im._exclusive_fp = exclusive_fp
|
||||
im._exclusive_fp = exclusive_fp
|
||||
return im
|
||||
|
||||
if exclusive_fp:
|
||||
|
|
|
@ -242,7 +242,9 @@ class ImageFile(Image.Image):
|
|||
self.tile = []
|
||||
self.readonly = readonly
|
||||
|
||||
if self._exclusive_fp:
|
||||
self.load_end()
|
||||
|
||||
if self._exclusive_fp and self._close_exclusive_fp_after_loading:
|
||||
self.fp.close()
|
||||
self.fp = None
|
||||
|
||||
|
@ -250,8 +252,6 @@ class ImageFile(Image.Image):
|
|||
# still raised if decoder fails to return anything
|
||||
raise_ioerror(err_code)
|
||||
|
||||
self.load_end()
|
||||
|
||||
return Image.Image.load(self)
|
||||
|
||||
def load_prepare(self):
|
||||
|
|
|
@ -39,6 +39,7 @@ class MicImageFile(TiffImagePlugin.TiffImageFile):
|
|||
|
||||
format = "MIC"
|
||||
format_description = "Microsoft Image Composer"
|
||||
_close_exclusive_fp_after_loading = False
|
||||
|
||||
def _open(self):
|
||||
|
||||
|
@ -64,7 +65,6 @@ class MicImageFile(TiffImagePlugin.TiffImageFile):
|
|||
raise SyntaxError("not an MIC file; no image entries")
|
||||
|
||||
self.__fp = self.fp
|
||||
self._exclusive_fp = False
|
||||
self.frame = 0
|
||||
|
||||
if len(self.images) > 1:
|
||||
|
|
|
@ -39,7 +39,8 @@ class MpoImageFile(JpegImagePlugin.JpegImageFile):
|
|||
|
||||
format = "MPO"
|
||||
format_description = "MPO (CIPA DC-007)"
|
||||
|
||||
_close_exclusive_fp_after_loading = False
|
||||
|
||||
def _open(self):
|
||||
self.fp.seek(0) # prep the fp in order to pass the JPEG test
|
||||
JpegImagePlugin.JpegImageFile._open(self)
|
||||
|
@ -53,7 +54,6 @@ class MpoImageFile(JpegImagePlugin.JpegImageFile):
|
|||
assert self.__framecount == len(self.__mpoffsets)
|
||||
del self.info['mpoffset'] # no longer needed
|
||||
self.__fp = self.fp # FIXME: hack
|
||||
self._exclusive_fp = False
|
||||
self.__fp.seek(self.__mpoffsets[0]) # get ready to read first frame
|
||||
self.__frame = 0
|
||||
self.offset = 0
|
||||
|
|
|
@ -97,6 +97,7 @@ class SpiderImageFile(ImageFile.ImageFile):
|
|||
|
||||
format = "SPIDER"
|
||||
format_description = "Spider 2D image"
|
||||
_close_exclusive_fp_after_loading = False
|
||||
|
||||
def _open(self):
|
||||
# check header
|
||||
|
@ -154,7 +155,6 @@ class SpiderImageFile(ImageFile.ImageFile):
|
|||
("raw", (0, 0) + self.size, offset,
|
||||
(self.rawmode, 0, 1))]
|
||||
self.__fp = self.fp # FIXME: hack
|
||||
self._exclusive_fp = False
|
||||
|
||||
@property
|
||||
def n_frames(self):
|
||||
|
|
|
@ -884,6 +884,7 @@ class TiffImageFile(ImageFile.ImageFile):
|
|||
|
||||
format = "TIFF"
|
||||
format_description = "Adobe TIFF"
|
||||
_close_exclusive_fp_after_loading = False
|
||||
|
||||
def _open(self):
|
||||
"Open the first image in a TIFF file"
|
||||
|
@ -901,7 +902,6 @@ class TiffImageFile(ImageFile.ImageFile):
|
|||
self.__first = self.__next = self.tag_v2.next
|
||||
self.__frame = -1
|
||||
self.__fp = self.fp
|
||||
self._exclusive_fp = False
|
||||
self._frame_pos = []
|
||||
self._n_frames = None
|
||||
self._is_animated = None
|
||||
|
@ -1014,7 +1014,7 @@ class TiffImageFile(ImageFile.ImageFile):
|
|||
# allow closing if we're on the first frame, there's no next
|
||||
# This is the ImageFile.load path only, libtiff specific below.
|
||||
if self.__frame == 0 and not self.__next:
|
||||
self._exclusive_fp = True
|
||||
self._close_exclusive_fp_after_loading = True
|
||||
|
||||
def _load_libtiff(self):
|
||||
""" Overload method triggered when we detect a compressed tiff
|
||||
|
@ -1093,10 +1093,10 @@ class TiffImageFile(ImageFile.ImageFile):
|
|||
self.tile = []
|
||||
self.readonly = 0
|
||||
# libtiff closed the fp in a, we need to close self.fp, if possible
|
||||
if hasattr(self.fp, 'close'):
|
||||
if self._exclusive_fp:
|
||||
if self.__frame == 0 and not self.__next:
|
||||
self.fp.close()
|
||||
self.fp = None # might be shared
|
||||
self.fp = None # might be shared
|
||||
|
||||
if err < 0:
|
||||
raise IOError(err)
|
||||
|
|
|
@ -472,7 +472,6 @@ class TestFileTiff(PillowTestCase):
|
|||
def test_close_on_load(self):
|
||||
# same as test_fd_leak, but runs on unixlike os
|
||||
tmpfile = self.tempfile("temp.tif")
|
||||
import os
|
||||
|
||||
with Image.open("Tests/images/uint16_1_4660.tif") as im:
|
||||
im.save(tmpfile)
|
||||
|
|
Loading…
Reference in New Issue
Block a user