Opened 16 years ago

Closed 16 years ago

#8187 closed (fixed)

Import PIL consistently and with exception handling, list as optional dependency in INSTALL

Reported by: Jeff Kowalczyk Owned by: nobody
Component: Uncategorized Version: dev
Severity: Keywords: PIL imaging easy_install
Cc: Triage Stage: Unreviewed
Has patch: no Needs documentation: no
Needs tests: no Patch needs improvement: no
Easy pickings: no UI/UX: no

Description

Some projects import PIL, some Imaging intending to reach the same code depending on how PIL was installed. Django appears to use the second form in at least one spot.

Some imports handle ImportError exceptions, some don't.

PIL is not mentioned in the INSTALL document.

$ ack -B 4 -A 4 'PIL|Imaging'
django/forms/fields.py
472-
473-    def clean(self, data, initial=None):
474-        """
475-        Checks that the file-upload field data contains a valid image (GIF, JPG,
476:        PNG, possibly others -- whatever the Python Imaging Library supports).
477-        """
478-        f = super(ImageField, self).clean(data, initial)
479-        if f is None:
480-            return None
481-        elif not data and initial:
482-            return initial
483:        from PIL import Image
484-
485:        # We need to get a file object for PIL. We might have a path or we might
486-        # have to read the data into memory.
487-        if hasattr(data, 'temporary_file_path'):
488-            file = data.temporary_file_path()
489-        else:
--
507-            #  but it must be called immediately after the constructor
508-            trial_image = Image.open(file)
509-            trial_image.verify()
510-        except ImportError: 
511:            # Under PyPy, it is possible to import PIL. However, the underlying
512-            # _imaging C module isn't available, so an ImportError will be 
513-            # raised. Catch and re-raise. 
514-            raise
515:        except Exception: # Python Imaging Library doesn't recognize it as an image
516-            raise ValidationError(self.error_messages['invalid_image'])
517-        if hasattr(f, 'seek') and callable(f.seek):
518-            f.seek(0)
519-        return f

django/core/files/images.py
1-"""
2-Utility functions for handling images.
3-
4:Requires PIL, as you might imagine.
5-"""
6-
7-from django.core.files import File
8-
--
25-        return self._dimensions_cache
26-
27-def get_image_dimensions(file_or_path):
28-    """Returns the (width, height) of an image, given an open file or a path."""
29:    from PIL import ImageFile as PILImageFile
30:    p = PILImageFile.Parser()
31-    if hasattr(file_or_path, 'read'):
32-        file = file_or_path
33-    else:
34-        file = open(file_or_path, 'rb')

django/core/validators.py
167-
168-def isValidImage(field_data, all_data):
169-    """
170-    Checks that the file-upload field data contains a valid image (GIF, JPG,
171:    PNG, possibly others -- whatever the Python Imaging Library supports).
172-    """
173:    from PIL import Image
174-    from cStringIO import StringIO
175-    try:
176-        content = field_data.read()
177-    except TypeError:
--
184-        # verify() is the only method that can spot a corrupt PNG,
185-        #  but it must be called immediately after the constructor
186-        trial_image = Image.open(StringIO(content))
187-        trial_image.verify()
188:    except Exception: # Python Imaging Library doesn't recognize it as an image
189-        raise ValidationError, _("Upload a valid image. The file you uploaded was either not an image or a corrupted image.")
190-
191-def isValidImageURL(field_data, all_data):
192-    uc = URLMimeTypeCheck(('image/jpeg', 'image/gif', 'image/png'))

django/core/management/validation.py
47-            if isinstance(f, models.FileField) and not f.upload_to:
48-                e.add(opts, '"%s": FileFields require an "upload_to" attribute.' % f.name)
49-            if isinstance(f, models.ImageField):
50-                try:
51:                    from PIL import Image
52-                except ImportError:
53:                    e.add(opts, '"%s": To use ImageFields, you need to install the Python Imaging Library. Get it at http://www.pythonware.com/products/pil/ .' % f.name)
54-            if f.choices:
55-                if isinstance(f.choices, basestring) or not is_iterable(f.choices):
56-                    e.add(opts, '"%s": "choices" should be iterable (e.g., a tuple or list).' % f.name)
57-                else:

tests/regressiontests/file_storage/models.py
6-
7-temp_storage = FileSystemStorage(tempfile.gettempdir())
8-
9-# Test for correct behavior of width_field/height_field.
10:# Of course, we can't run this without PIL.
11-
12-try:
13-    # Checking for the existence of Image is enough for CPython, but
14-    # for PyPy, you need to check for the underlying modules
15-    import Image, _imaging
16-except ImportError:
17-    Image = None
18-
19:# If we have PIL, do these tests
20-if Image:
21-    class Person(models.Model):
22-        name = models.CharField(max_length=50)
23-        mugshot = models.ImageField(storage=temp_storage, upload_to='tests', 

tests/regressiontests/serializers_regress/models.py
1-"""
2-A test spanning all the capabilities of all the serializers.
3-
4-This class sets up a model for each model field type
5:(except for image types, because of the PIL dependency).
6-"""
7-
8-from django.db import models
9-from django.contrib.contenttypes import generic

tests/modeltests/model_forms/models.py
70-
71-class ImageFile(models.Model):
72-    description = models.CharField(max_length=20)
73-    try:
74:        # If PIL is available, try testing PIL.
75-        # Checking for the existence of Image is enough for CPython, but
76-        # for PyPy, you need to check for the underlying modules
77:        # If PIL is not available, this test is equivalent to TextFile above.
78-        import Image, _imaging
79-        image = models.ImageField(storage=temp_storage, upload_to='tests')
80-    except ImportError:
81-        image = models.FileField(storage=temp_storage, upload_to='tests')

Attachments (1)

patch-8185-vs-r8255.diff (1.2 KB ) - added by sebastian.hillig 16 years ago.
Replacing Image imports with from PIL import Image

Download all attachments as: .zip

Change History (4)

by sebastian.hillig, 16 years ago

Attachment: patch-8185-vs-r8255.diff added

Replacing Image imports with from PIL import Image

comment:1 by Jacob, 16 years ago

Resolution: fixed
Status: newclosed

(In [8257]) Fixed #8187: made PIL imports consistant. Thanks, bastih.

comment:2 by edrex, 16 years ago

Resolution: fixed
Status: closedreopened

Imports fail if PIL is installed via an egg, since in this case there is no PIL module, only Image, ImageFile, etc.

   virtualenv --no-site-packages env
   source env/bin/activate
   easy_install --find-links http://www.pythonware.com/products/pil/ Imaging

See how django-photologue does the imports: http://code.google.com/p/django-photologue/source/browse/trunk/photologue/models.py#20

so should be

try:
    import Image
except ImportError:
    try:
        from PIL import Image
    except ImportError:
        raise ImportError('...')

comment:3 by edrex, 16 years ago

Resolution: fixed
Status: reopenedclosed

I realized that the way of installing PIL listed above is invalid, should always be in a PIL module. Sorry for the noise.

Note: See TracTickets for help on using tickets.
Back to Top