/lib/python/django/utils/image.py

https://github.com/mozilla/moztrap-vendor-lib · Python · 154 lines · 87 code · 15 blank · 52 comment · 21 complexity · 0cf12d0fb3ac534b57d0c5972a9546a4 MD5 · raw file

  1. # -*- coding: utf-8 -*-
  2. """
  3. To provide a shim layer over Pillow/PIL situation until the PIL support is
  4. removed.
  5. Combinations To Account For
  6. ===========================
  7. * Pillow:
  8. * never has ``_imaging`` under any Python
  9. * has the ``Image.alpha_composite``, which may aid in detection
  10. * PIL
  11. * CPython 2.x may have _imaging (& work)
  12. * CPython 2.x may *NOT* have _imaging (broken & needs a error message)
  13. * CPython 3.x doesn't work
  14. * PyPy will *NOT* have _imaging (but works?)
  15. * On some platforms (Homebrew and RHEL6 reported) _imaging isn't available,
  16. the needed import is from PIL import _imaging (refs #21355)
  17. Restated, that looks like:
  18. * If we're on Python 2.x, it could be either Pillow or PIL:
  19. * If ``import _imaging`` results in ``ImportError``, either they have a
  20. working Pillow installation or a broken PIL installation, so we need to
  21. detect further:
  22. * To detect, we first ``import Image``.
  23. * If ``Image`` has a ``alpha_composite`` attribute present, only Pillow
  24. has this, so we assume it's working.
  25. * If ``Image`` DOES NOT have a ``alpha_composite``attribute, it must be
  26. PIL & is a broken (likely C compiler-less) install, which we need to
  27. warn the user about.
  28. * If ``import _imaging`` works, it must be PIL & is a working install.
  29. * Python 3.x
  30. * If ``import Image`` works, it must be Pillow, since PIL isn't Python 3.x
  31. compatible.
  32. * PyPy
  33. * If ``import _imaging`` results in ``ImportError``, it could be either
  34. Pillow or PIL, both of which work without it on PyPy, so we're fine.
  35. Approach
  36. ========
  37. * Attempt to import ``Image``
  38. * ``ImportError`` - nothing is installed, toss an exception
  39. * Either Pillow or the PIL is installed, so continue detecting
  40. * Attempt to ``hasattr(Image, 'alpha_composite')``
  41. * If it works, it's Pillow & working
  42. * If it fails, we've got a PIL install, continue detecting
  43. * The only option here is that we're on Python 2.x or PyPy, of which
  44. we only care about if we're on CPython.
  45. * If we're on CPython, attempt to ``from PIL import _imaging`` and
  46. ``import _imaging``
  47. * ``ImportError`` - Bad install, toss an exception
  48. """
  49. from __future__ import unicode_literals
  50. import warnings
  51. from django.core.exceptions import ImproperlyConfigured
  52. from django.utils.translation import ugettext_lazy as _
  53. Image = None
  54. _imaging = None
  55. ImageFile = None
  56. def _detect_image_library():
  57. global Image
  58. global _imaging
  59. global ImageFile
  60. # Skip re-attempting to import if we've already run detection.
  61. if Image is not None:
  62. return Image, _imaging, ImageFile
  63. # Assume it's not there.
  64. PIL_imaging = False
  65. try:
  66. # Try from the Pillow (or one variant of PIL) install location first.
  67. from PIL import Image as PILImage
  68. except ImportError as err:
  69. try:
  70. # If that failed, try the alternate import syntax for PIL.
  71. import Image as PILImage
  72. except ImportError as err:
  73. # Neither worked, so it's likely not installed.
  74. raise ImproperlyConfigured(
  75. _("Neither Pillow nor PIL could be imported: %s") % err
  76. )
  77. # ``Image.alpha_composite`` was added to Pillow in SHA: e414c6 & is not
  78. # available in any version of the PIL.
  79. if hasattr(PILImage, 'alpha_composite'):
  80. PIL_imaging = False
  81. else:
  82. # We're dealing with the PIL. Determine if we're on CPython & if
  83. # ``_imaging`` is available.
  84. import platform
  85. # This is the Alex Approved way.
  86. # See http://mail.python.org/pipermail//pypy-dev/2011-November/008739.html
  87. if platform.python_implementation().lower() == 'cpython':
  88. # We're on CPython (likely 2.x). Since a C compiler is needed to
  89. # produce a fully-working PIL & will create a ``_imaging`` module,
  90. # we'll attempt to import it to verify their kit works.
  91. try:
  92. from PIL import _imaging as PIL_imaging
  93. except ImportError:
  94. try:
  95. import _imaging as PIL_imaging
  96. except ImportError as err:
  97. raise ImproperlyConfigured(
  98. _("The '_imaging' module for the PIL could not be "
  99. "imported: %s") % err
  100. )
  101. # Try to import ImageFile as well.
  102. try:
  103. from PIL import ImageFile as PILImageFile
  104. except ImportError:
  105. import ImageFile as PILImageFile
  106. # Finally, warn about deprecation...
  107. if PIL_imaging is not False:
  108. warnings.warn(
  109. "Support for the PIL will be removed in Django 1.8. Please " +
  110. "uninstall it & install Pillow instead.",
  111. PendingDeprecationWarning
  112. )
  113. return PILImage, PIL_imaging, PILImageFile
  114. Image, _imaging, ImageFile = _detect_image_library()