Skip to content

Reduce duplicate code in Image open - #1392

Closed
radarhere wants to merge 1 commit into
python-pillow:masterfrom
radarhere:duplicate
Closed

radarhere wants to merge 1 commit into
python-pillow:masterfrom
radarhere:duplicate

Conversation

@radarhere

Copy link
Copy Markdown
Member

Minor cleanup. If anyone feels if this is more confusing than helpful, feel free to close.

@hugovk

hugovk commented Aug 25, 2015

Copy link
Copy Markdown
Member

Note: GitHub is under a DDoS attack:

https://status.github.com/messages

Hence the AppVeyor failures:

fatal: unable to access 'https://github.com/python-pillow/Pillow.git/': Failed connect to github.com:443; No error
Command exited with code 128

We'll have to restart those later.

@radarhere

Copy link
Copy Markdown
Member Author

The tests have completed now. Coveralls has equated the fewer lines of code with fewer lines of covered code, and so reported a drop in coverage.

Comment thread PIL/Image.py

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Decent idea to dedup code, but this looks really confusing.

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I know. I can't seem to think of a neat solution. Again, feel free to close if this just doesn't work.

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

How about something like:

def _something(prefix, fp, filename):
    for i in ID:
        try:
            factory, accept = OPEN[i]
            if not accept or accept(prefix):
                fp.seek(0)
                im = factory(fp, filename)
                _decompression_bomb_check(im.size)
                return im
        except (SyntaxError, IndexError, TypeError, struct.error):
            logger.debug("", exc_info=True)


def open(fp, mode="r"):
    ...
    ...
    ...
    _something(prefix, fp, filename)

    if init():

        _something(prefix, fp, filename)

    raise IOError("cannot identify image file %r"
                  % (filename if filename else fp))

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I've got this passing the tests:

def open(fp, mode="r"):
    """
    Opens and identifies the given image file.

    This is a lazy operation; this function identifies the file, but
    the file remains open and the actual image data is not read from
    the file until you try to process the data (or call the
    :py:meth:`~PIL.Image.Image.load` method).  See
    :py:func:`~PIL.Image.new`.

    :param fp: A filename (string), pathlib.Path object or a file object.
       The file object must implement :py:meth:`~file.read`,
       :py:meth:`~file.seek`, and :py:meth:`~file.tell` methods,
       and be opened in binary mode.
    :param mode: The mode.  If given, this argument must be "r".
    :returns: An :py:class:`~PIL.Image.Image` object.
    :exception IOError: If the file cannot be found, or the image cannot be
       opened and identified.
    """

    if mode != "r":
        raise ValueError("bad mode %r" % mode)

    filename = ""
    if isPath(fp):
        filename = fp
    elif sys.version_info >= (3, 4):
        from pathlib import Path
        if isinstance(fp, Path):
            filename = str(fp.resolve())
    if filename:
        fp = builtins.open(filename, "rb")

    try:
        fp.seek(0)
    except (AttributeError, io.UnsupportedOperation):
        fp = io.BytesIO(fp.read())

    prefix = fp.read(16)

    preinit()

    def _open_core(fp, filename, prefix):
        for i in ID:
            try:
                factory, accept = OPEN[i]
                if not accept or accept(prefix):
                    fp.seek(0)
                    im = factory(fp, filename)
                    _decompression_bomb_check(im.size)
                    return im
            except (SyntaxError, IndexError, TypeError, struct.error):
                logger.debug("", exc_info=True)
        return None

    im = _open_core(fp, filename, prefix)

    if im is None:
        if init():
            im = _open_core(fp, filename, prefix)

    if im:
        return im

    raise IOError("cannot identify image file %r"
                  % (filename if filename else fp))

And I'll tell you, I sorely want to put things like:
if im: return im to condense things, but someone would just run flake8 on it.

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks! For some reason, I thought that the option of separating it out into a function would look more garbled than that. Nice work.

@radarhere

Copy link
Copy Markdown
Member Author

Closed in favour of #1415

@radarhere radarhere closed this Sep 10, 2015
@radarhere
radarhere deleted the duplicate branch September 10, 2015 14:24
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants