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