mirror of
				https://github.com/python-pillow/Pillow.git
				synced 2025-11-04 09:57:43 +03:00 
			
		
		
		
	Merge pull request #551 from wiredfool/with
Image.close, Context manager support
This commit is contained in:
		
						commit
						5ca5652d0b
					
				
							
								
								
									
										43
									
								
								PIL/Image.py
									
									
									
									
									
								
							
							
						
						
									
										43
									
								
								PIL/Image.py
									
									
									
									
									
								
							| 
						 | 
					@ -92,7 +92,7 @@ except ImportError:
 | 
				
			||||||
 | 
					
 | 
				
			||||||
from PIL import ImageMode
 | 
					from PIL import ImageMode
 | 
				
			||||||
from PIL._binary import i8, o8
 | 
					from PIL._binary import i8, o8
 | 
				
			||||||
from PIL._util import isPath, isStringType
 | 
					from PIL._util import isPath, isStringType, deferred_error
 | 
				
			||||||
 | 
					
 | 
				
			||||||
import os, sys
 | 
					import os, sys
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					@ -497,6 +497,35 @@ class Image:
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    _makeself = _new # compatibility
 | 
					    _makeself = _new # compatibility
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    # Context Manager Support
 | 
				
			||||||
 | 
					    def __enter__(self):
 | 
				
			||||||
 | 
					        return self
 | 
				
			||||||
 | 
					    def __exit__(self, *args):
 | 
				
			||||||
 | 
					        self.close()
 | 
				
			||||||
 | 
					        
 | 
				
			||||||
 | 
					    def close(self):
 | 
				
			||||||
 | 
					        """
 | 
				
			||||||
 | 
					        Closes the file pointer, if possible.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        This operation will destroy the image core and release it's memory.
 | 
				
			||||||
 | 
					        The image data will be unusable afterward.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        This function is only required to close images that have not
 | 
				
			||||||
 | 
					        had their file read and closed by the
 | 
				
			||||||
 | 
					        :py:meth:`~PIL.Image.Image.load` method.
 | 
				
			||||||
 | 
					        """
 | 
				
			||||||
 | 
					        try:
 | 
				
			||||||
 | 
					            self.fp.close()
 | 
				
			||||||
 | 
					        except Exception as msg:
 | 
				
			||||||
 | 
					            if Image.DEBUG:
 | 
				
			||||||
 | 
					                print ("Error closing: %s" %msg)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        # Instead of simply setting to None, we're setting up a
 | 
				
			||||||
 | 
					        # deferred error that will better explain that the core image
 | 
				
			||||||
 | 
					        # object is gone.
 | 
				
			||||||
 | 
					        self.im = deferred_error(ValueError("Operation on closed image"))
 | 
				
			||||||
 | 
					        
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    def _copy(self):
 | 
					    def _copy(self):
 | 
				
			||||||
        self.load()
 | 
					        self.load()
 | 
				
			||||||
        self.im = self.im.copy()
 | 
					        self.im = self.im.copy()
 | 
				
			||||||
| 
						 | 
					@ -642,7 +671,8 @@ class Image:
 | 
				
			||||||
        Allocates storage for the image and loads the pixel data.  In
 | 
					        Allocates storage for the image and loads the pixel data.  In
 | 
				
			||||||
        normal cases, you don't need to call this method, since the
 | 
					        normal cases, you don't need to call this method, since the
 | 
				
			||||||
        Image class automatically loads an opened image when it is
 | 
					        Image class automatically loads an opened image when it is
 | 
				
			||||||
        accessed for the first time.
 | 
					        accessed for the first time. This method will close the file
 | 
				
			||||||
 | 
					        associated with the image. 
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        :returns: An image access object.
 | 
					        :returns: An image access object.
 | 
				
			||||||
        """
 | 
					        """
 | 
				
			||||||
| 
						 | 
					@ -2074,10 +2104,11 @@ def open(fp, mode="r"):
 | 
				
			||||||
    """
 | 
					    """
 | 
				
			||||||
    Opens and identifies the given image file.
 | 
					    Opens and identifies the given image file.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    This is a lazy operation; this function identifies the file, but the
 | 
					    This is a lazy operation; this function identifies the file, but
 | 
				
			||||||
    actual image data is not read from the file until you try to process
 | 
					    the file remains open and the actual image data is not read from
 | 
				
			||||||
    the data (or call the :py:meth:`~PIL.Image.Image.load` method).
 | 
					    the file until you try to process the data (or call the
 | 
				
			||||||
    See :py:func:`~PIL.Image.new`.
 | 
					    :py:meth:`~PIL.Image.Image.load` method).  See
 | 
				
			||||||
 | 
					    :py:func:`~PIL.Image.new`.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    :param file: A filename (string) or a file object.  The file object
 | 
					    :param file: A filename (string) or a file object.  The file object
 | 
				
			||||||
       must implement :py:meth:`~file.read`, :py:meth:`~file.seek`, and
 | 
					       must implement :py:meth:`~file.read`, :py:meth:`~file.seek`, and
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -89,8 +89,8 @@ try:
 | 
				
			||||||
except ImportError as ex:
 | 
					except ImportError as ex:
 | 
				
			||||||
    # Allow error import for doc purposes, but error out when accessing
 | 
					    # Allow error import for doc purposes, but error out when accessing
 | 
				
			||||||
    # anything in core. 
 | 
					    # anything in core. 
 | 
				
			||||||
    from _util import import_err
 | 
					    from _util import deferred_error
 | 
				
			||||||
    _imagingcms = import_err(ex)
 | 
					    _imagingcms = deferred_error(ex)
 | 
				
			||||||
from PIL._util import isStringType
 | 
					from PIL._util import isStringType
 | 
				
			||||||
 | 
					
 | 
				
			||||||
core = _imagingcms
 | 
					core = _imagingcms
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -15,7 +15,7 @@ else:
 | 
				
			||||||
def isDirectory(f):
 | 
					def isDirectory(f):
 | 
				
			||||||
    return isPath(f) and os.path.isdir(f)
 | 
					    return isPath(f) and os.path.isdir(f)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
class import_err(object):
 | 
					class deferred_error(object):
 | 
				
			||||||
    def __init__(self, ex):
 | 
					    def __init__(self, ex):
 | 
				
			||||||
        self.ex = ex
 | 
					        self.ex = ex
 | 
				
			||||||
    def __getattr__(self, elt):
 | 
					    def __getattr__(self, elt):
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -2,6 +2,8 @@ from tester import *
 | 
				
			||||||
 | 
					
 | 
				
			||||||
from PIL import Image
 | 
					from PIL import Image
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					import os
 | 
				
			||||||
 | 
					
 | 
				
			||||||
def test_sanity():
 | 
					def test_sanity():
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    im = lena()
 | 
					    im = lena()
 | 
				
			||||||
| 
						 | 
					@ -9,3 +11,17 @@ def test_sanity():
 | 
				
			||||||
    pix = im.load()
 | 
					    pix = im.load()
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    assert_equal(pix[0, 0], (223, 162, 133))
 | 
					    assert_equal(pix[0, 0], (223, 162, 133))
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					def test_close():    
 | 
				
			||||||
 | 
					    im = Image.open("Images/lena.gif")
 | 
				
			||||||
 | 
					    assert_no_exception(lambda: im.close())
 | 
				
			||||||
 | 
					    assert_exception(ValueError, lambda: im.load())
 | 
				
			||||||
 | 
					    assert_exception(ValueError, lambda: im.getpixel((0,0)))
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					def test_contextmanager():
 | 
				
			||||||
 | 
					    fn = None
 | 
				
			||||||
 | 
					    with Image.open("Images/lena.gif") as im:
 | 
				
			||||||
 | 
					        fn = im.fp.fileno()
 | 
				
			||||||
 | 
					        assert_no_exception(lambda: os.fstat(fn))
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    assert_exception(OSError, lambda: os.fstat(fn))    
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -126,8 +126,8 @@ Identify Image Files
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    for infile in sys.argv[1:]:
 | 
					    for infile in sys.argv[1:]:
 | 
				
			||||||
        try:
 | 
					        try:
 | 
				
			||||||
            im = Image.open(infile)
 | 
					            with Image.open(infile) as im:
 | 
				
			||||||
            print(infile, im.format, "%dx%d" % im.size, im.mode)
 | 
					                print(infile, im.format, "%dx%d" % im.size, im.mode)
 | 
				
			||||||
        except IOError:
 | 
					        except IOError:
 | 
				
			||||||
            pass
 | 
					            pass
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -136,9 +136,9 @@ ITU-R 709, using the D65 luminant) to the CIE XYZ color space:
 | 
				
			||||||
.. automethod:: PIL.Image.Image.verify
 | 
					.. automethod:: PIL.Image.Image.verify
 | 
				
			||||||
 | 
					
 | 
				
			||||||
.. automethod:: PIL.Image.Image.fromstring
 | 
					.. automethod:: PIL.Image.Image.fromstring
 | 
				
			||||||
.. deprecated:: 2.0
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
.. automethod:: PIL.Image.Image.load
 | 
					.. automethod:: PIL.Image.Image.load
 | 
				
			||||||
 | 
					.. automethod:: PIL.Image.Image.close
 | 
				
			||||||
 | 
					
 | 
				
			||||||
Attributes
 | 
					Attributes
 | 
				
			||||||
----------
 | 
					----------
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
		Loading…
	
		Reference in New Issue
	
	Block a user