diff options
| author | Daniel Lindsley <daniel@toastdriven.com> | 2013-05-14 19:31:16 -0700 |
|---|---|---|
| committer | Daniel Lindsley <daniel@toastdriven.com> | 2013-05-14 19:32:04 -0700 |
| commit | 33793f7c3edd8ff144ff2e9434367267c20af26a (patch) | |
| tree | 2fc05d98ee3d9c2bb9fd9a208647ad280d52b78c /django/utils | |
| parent | c792c83cad54f064b6ba13e285e95a90e2c61f09 (diff) | |
Fixed #19934 - Use of Pillow is now preferred over PIL.
This starts the deprecation period for PIL (support to end in 1.8).
Diffstat (limited to 'django/utils')
| -rw-r--r-- | django/utils/image.py | 146 |
1 files changed, 146 insertions, 0 deletions
diff --git a/django/utils/image.py b/django/utils/image.py new file mode 100644 index 0000000000..ed9b210973 --- /dev/null +++ b/django/utils/image.py @@ -0,0 +1,146 @@ +# -*- coding: utf-8 -*- +""" +To provide a shim layer over Pillow/PIL situation until the PIL support is +removed. + + +Combinations To Account For +=========================== + +* Pillow: + + * never has ``_imaging`` under any Python + * has the ``Image.alpha_composite``, which may aid in detection + +* PIL + + * CPython 2.x may have _imaging (& work) + * CPython 2.x may *NOT* have _imaging (broken & needs a error message) + * CPython 3.x doesn't work + * PyPy will *NOT* have _imaging (but works?) + +Restated, that looks like: + +* If we're on Python 2.x, it could be either Pillow or PIL: + + * If ``import _imaging`` results in ``ImportError``, either they have a + working Pillow installation or a broken PIL installation, so we need to + detect further: + + * To detect, we first ``import Image``. + * If ``Image`` has a ``alpha_composite`` attribute present, only Pillow + has this, so we assume it's working. + * If ``Image`` DOES NOT have a ``alpha_composite``attribute, it must be + PIL & is a broken (likely C compiler-less) install, which we need to + warn the user about. + + * If ``import _imaging`` works, it must be PIL & is a working install. + +* Python 3.x + + * If ``import Image`` works, it must be Pillow, since PIL isn't Python 3.x + compatible. + +* PyPy + + * If ``import _imaging`` results in ``ImportError``, it could be either + Pillow or PIL, both of which work without it on PyPy, so we're fine. + + +Approach +======== + +* Attempt to import ``Image`` + + * ``ImportError`` - nothing is installed, toss an exception + * Either Pillow or the PIL is installed, so continue detecting + +* Attempt to ``hasattr(Image, 'alpha_composite')`` + + * If it works, it's Pillow & working + * If it fails, we've got a PIL install, continue detecting + + * The only option here is that we're on Python 2.x or PyPy, of which + we only care about if we're on CPython. + * If we're on CPython, attempt to ``import _imaging`` + + * ``ImportError`` - Bad install, toss an exception + +""" +import warnings + +from django.core.exceptions import ImproperlyConfigured +from django.utils.translation import ugettext_lazy as _ + + +Image = None +_imaging = None +ImageFile = None + + +def _detect_image_library(): + global Image + global _imaging + global ImageFile + + # Skip re-attempting to import if we've already run detection. + if Image is not None: + return Image, _imaging, ImageFile + + # Assume it's not there. + PIL_imaging = False + + try: + # Try from the Pillow (or one variant of PIL) install location first. + from PIL import Image as PILImage + except ImportError as err: + try: + # If that failed, try the alternate import syntax for PIL. + import Image as PILImage + except ImportError as err: + # Neither worked, so it's likely not installed. + raise ImproperlyConfigured( + _(u"Neither Pillow nor PIL could be imported: %s" % err) + ) + + # ``Image.alpha_composite`` was added to Pillow in SHA: e414c6 & is not + # available in any version of the PIL. + if hasattr(PILImage, u'alpha_composite'): + PIL_imaging = False + else: + # We're dealing with the PIL. Determine if we're on CPython & if + # ``_imaging`` is available. + import platform + + # This is the Alex Approved™ way. + # See http://mail.python.org/pipermail//pypy-dev/2011-November/008739.html + if platform.python_implementation().lower() == u'cpython': + # We're on CPython (likely 2.x). Since a C compiler is needed to + # produce a fully-working PIL & will create a ``_imaging`` module, + # we'll attempt to import it to verify their kit works. + try: + import _imaging as PIL_imaging + except ImportError as err: + raise ImproperlyConfigured( + _(u"The '_imaging' module for the PIL could not be " + + u"imported: %s" % err) + ) + + # Try to import ImageFile as well. + try: + from PIL import ImageFile as PILImageFile + except ImportError: + import ImageFile as PILImageFile + + # Finally, warn about deprecation... + if PIL_imaging is not False: + warnings.warn( + "Support for the PIL will be removed in Django 1.8. Please " + + "uninstall it & install Pillow instead.", + PendingDeprecationWarning + ) + + return PILImage, PIL_imaging, PILImageFile + + +Image, _imaging, ImageFile = _detect_image_library() |
