from PIL import ImageFile as PillowImageFile
import zlib
import struct


def get_pillow_attribute(file, pil_attr):
    """
    Returns an attribute from a Pillow image of the given file,
    file
        a file. wrappable by Pillow. Must be open
    pil_attr
        the attribute to read.
    return 
        the attribut, or None, if unreadaable. the file is not closed.
    """
    # This devilish, ticketed code is lifted from 
    # django.core.files.images, where it seeks image dimensions.
    # Unfortunately, that code is not configurable nor overridable.

    p = PillowImageFile.Parser()
    file_pos = file.tell()
    file.seek(0)
    try:
        # Most of the time Pillow only needs a small chunk to parse the
        # image and get data, but with some TIFF files Pillow needs to
        # parse the whole file.
        chunk_size = 1024
        while 1:
            data = file.read(chunk_size)
            if not data:
                break
            try:
                p.feed(data)
            except zlib.error as e:
                # ignore zlib complaining on truncated stream, just feed more
                # data to parser (ticket #19457).
                if e.args[0].startswith("Error -5"):
                    pass
                else:
                    raise
            except struct.error:
                # Ignore PIL failing on a too short buffer when reads return
                # less bytes than expected. Skip and feed more data to the
                # parser (ticket #24544).
                pass
            except RuntimeError:
                # e.g. "RuntimeError: could not create decoder object" for
                # WebP files. A different chunk_size may work.
                pass
            if p.image:
                return getattr(p.image, pil_attr)
            chunk_size *= 2
        return None
    finally:
        file.seek(file_pos)