[Python-modules-commits] [sorl-thumbnail] 02/17: Import sorl-thumbnail_12.3.orig.tar.gz

Wolfgang Borgert debacle at moszumanska.debian.org
Wed Jan 6 21:05:25 UTC 2016


This is an automated email from the git hooks/post-receive script.

debacle pushed a commit to branch master
in repository sorl-thumbnail.

commit 42b81892242e6ae4979e886c38f92a113aa58721
Author: W. Martin Borgert <debacle at debian.org>
Date:   Fri Jan 1 18:06:40 2016 +0100

    Import sorl-thumbnail_12.3.orig.tar.gz
---
 .gitignore                                         |   5 +
 .travis.yml                                        | 136 ++--
 AUTHORS                                            |   5 +-
 README.rst                                         |  36 +-
 docs/management.rst                                |   6 +-
 docs/reference/settings.rst                        |   2 +-
 docs/template.rst                                  |   2 +-
 setup.py                                           |   8 +-
 sorl/__init__.py                                   |   6 +-
 sorl/thumbnail/base.py                             |   3 +-
 sorl/thumbnail/compat.py                           |  65 +-
 sorl/thumbnail/engines/base.py                     |  26 +-
 sorl/thumbnail/engines/convert_engine.py           |   9 +-
 sorl/thumbnail/engines/pil_engine.py               |   9 +-
 sorl/thumbnail/engines/wand_engine.py              |  10 +-
 sorl/thumbnail/fields.py                           |   2 +-
 sorl/thumbnail/helpers.py                          |   7 +-
 sorl/thumbnail/images.py                           |  12 +-
 sorl/thumbnail/kvstores/base.py                    |   8 +-
 sorl/thumbnail/kvstores/cached_db_kvstore.py       |  11 +-
 sorl/thumbnail/kvstores/dbm_kvstore.py             |   2 +
 sorl/thumbnail/management/commands/thumbnail.py    |   6 +-
 sorl/thumbnail/migrations/0001_initial.py          |  20 +
 sorl/thumbnail/migrations/__init__.py              |   0
 sorl/thumbnail/templatetags/thumbnail.py           |   2 +-
 tests/runalltests.sh                               |   6 -
 tests/runtests.py                                  |  74 --
 tests/settings/default.py                          |  24 +-
 tests/thumbnail_tests/compat.py                    |   9 +
 .../test_alternative_resolutions.py                |  58 ++
 tests/thumbnail_tests/test_backends.py             | 141 ++++
 tests/thumbnail_tests/test_commands.py             |  68 ++
 tests/thumbnail_tests/test_engines.py              | 363 +++++++++
 tests/thumbnail_tests/test_filters.py              |  48 ++
 tests/thumbnail_tests/test_kvstore.py              |  23 +
 tests/thumbnail_tests/test_parsers.py              |  36 +
 tests/thumbnail_tests/test_storage.py              |  52 ++
 tests/thumbnail_tests/test_templatetags.py         | 146 ++++
 tests/thumbnail_tests/tests.py                     | 892 ---------------------
 tests/thumbnail_tests/urls.py                      |   2 +-
 tests/thumbnail_tests/utils.py                     |  95 ++-
 tox.ini                                            | 389 +--------
 42 files changed, 1341 insertions(+), 1483 deletions(-)

diff --git a/.gitignore b/.gitignore
index 2775572..4df9375 100644
--- a/.gitignore
+++ b/.gitignore
@@ -54,3 +54,8 @@ docs/_build/
 # Virtualenv
 
 .env/
+
+# dbm stuff
+tests/thumbnail_kvstore
+tests/thumbnail_kvstore.db
+tests/thumbnail_kvstore.lock
diff --git a/.travis.yml b/.travis.yml
index 72f4a8d..1597464 100644
--- a/.travis.yml
+++ b/.travis.yml
@@ -1,87 +1,93 @@
 language: python
 
 python:
-  - "2.7"
-  - "3.3"
+  - "3.4"
 
-env:
-  - DJANGO_VERSION=">=1.5,<1.6" SETTINGS=pil APT='libjpeg62 libjpeg62-dev zlib1g-dev'
-  - DJANGO_VERSION=">=1.5,<1.6" SETTINGS=imagemagick APT=imagemagick
-  - DJANGO_VERSION=">=1.5,<1.6" SETTINGS=graphicsmagick APT=graphicsmagick
-  - DJANGO_VERSION=">=1.5,<1.6" SETTINGS=wand APT=libmagickwand-dev PIP=wand
-  - DJANGO_VERSION=">=1.5,<1.6" SETTINGS=redis PIP=redis
-
-  - DJANGO_VERSION=">=1.6,<1.7" SETTINGS=pil APT='libjpeg62 libjpeg62-dev zlib1g-dev'
-  - DJANGO_VERSION=">=1.6,<1.7" SETTINGS=imagemagick APT=imagemagick
-  - DJANGO_VERSION=">=1.6,<1.7" SETTINGS=graphicsmagick APT=graphicsmagick
-  - DJANGO_VERSION=">=1.6,<1.7" SETTINGS=wand APT=libmagickwand-dev PIP=wand
-  - DJANGO_VERSION=">=1.6,<1.7" SETTINGS=redis PIP=redis
-
-  - DJANGO_VERSION=">=1.7,<1.8" SETTINGS=pil APT='libjpeg62 libjpeg62-dev zlib1g-dev'
-  - DJANGO_VERSION=">=1.7,<1.8" SETTINGS=imagemagick APT=imagemagick
-  - DJANGO_VERSION=">=1.7,<1.8" SETTINGS=graphicsmagick APT=graphicsmagick
-  - DJANGO_VERSION=">=1.7,<1.8" SETTINGS=wand APT=libmagickwand-dev PIP=wand
-  - DJANGO_VERSION=">=1.7,<1.8" SETTINGS=redis PIP=redis
-
-matrix:
-  include:
-    - python: "2.7"
-      env:
-        - DJANGO_VERSION=">=1.4,<1.5" SETTINGS=pil APT='libjpeg62 libjpeg62-dev zlib1g-dev'
-
-    - python: "2.7"
-      env:
-        - DJANGO_VERSION=">=1.4,<1.5" SETTINGS=imagemagick APT=imagemagick
-
-    - python: "2.7"
-      env:
-        - DJANGO_VERSION=">=1.4,<1.5" SETTINGS=graphicsmagick APT=graphicsmagick
+cache:
+  pip:
+  apt:
+  directories:
+    - .tox
 
-    - python: "2.7"
-      env:
-        - DJANGO_VERSION=">=1.4,<1.5" SETTINGS=wand APT=libmagickwand-dev PIP=wand
-
-    - python: "2.7"
-      env:
-        - DJANGO_VERSION=">=1.4,<1.5" SETTINGS=redis PIP=redis
-
-    - python: "2.7"
-      env:
-        - DJANGO_VERSION=">=1.4,<1.5" SETTINGS=pgmagick APT='libgraphicsmagick++-dev libboost-python-dev libboost-thread-dev'
-        - PIP=pgmagick
-
-    - python: "2.7"
-      env:
-        - DJANGO_VERSION=">=1.5,<1.6" SETTINGS=pgmagick APT='libgraphicsmagick++-dev libboost-python-dev libboost-thread-dev'
-        - PIP=pgmagick
-
-    - python: "2.7"
-      env:
-        - DJANGO_VERSION=">=1.6,<1.7" SETTINGS=pgmagick APT='libgraphicsmagick++-dev libboost-python-dev libboost-thread-dev'
-        - PIP=pgmagick
+env:
+  - TOX_ENV=py27-django14-pil APT='libjpeg62 libjpeg62-dev zlib1g-dev'
+  - TOX_ENV=py27-django14-imagemagick APT=imagemagick
+  - TOX_ENV=py27-django14-graphicsmagick APT=graphicsmagick
+  - TOX_ENV=py27-django14-redis
+  - TOX_ENV=py27-django14-wand
+  - TOX_ENV=py27-django14-pgmagick APT='libgraphicsmagick++1-dev libboost-python-dev'
+  - TOX_ENV=py27-django14-dbm
+  - TOX_ENV=py27-django15-pil APT='libjpeg62 libjpeg62-dev zlib1g-dev'
+  - TOX_ENV=py27-django15-imagemagick APT=imagemagick
+  - TOX_ENV=py27-django15-graphicsmagick APT=graphicsmagick
+  - TOX_ENV=py27-django15-redis
+  - TOX_ENV=py27-django15-wand
+  - TOX_ENV=py27-django15-pgmagick APT='libgraphicsmagick++1-dev libboost-python-dev'
+  - TOX_ENV=py27-django15-dbm
+  - TOX_ENV=py27-django16-pil APT='libjpeg62 libjpeg62-dev zlib1g-dev'
+  - TOX_ENV=py27-django16-imagemagick APT=imagemagick
+  - TOX_ENV=py27-django16-graphicsmagick APT=graphicsmagick
+  - TOX_ENV=py27-django16-redis
+  - TOX_ENV=py27-django16-wand
+  - TOX_ENV=py27-django16-pgmagick APT='libgraphicsmagick++1-dev libboost-python-dev'
+  - TOX_ENV=py27-django16-dbm
+  - TOX_ENV=py27-django17-pil APT='libjpeg62 libjpeg62-dev zlib1g-dev'
+  - TOX_ENV=py27-django17-imagemagick APT=imagemagick
+  - TOX_ENV=py27-django17-graphicsmagick APT=graphicsmagick
+  - TOX_ENV=py27-django17-redis
+  - TOX_ENV=py27-django17-wand
+  - TOX_ENV=py27-django17-pgmagick APT='libgraphicsmagick++1-dev libboost-python-dev'
+  - TOX_ENV=py27-django17-dbm
+  - TOX_ENV=py27-django18-pil APT='libjpeg62 libjpeg62-dev zlib1g-dev'
+  - TOX_ENV=py27-django18-imagemagick APT=imagemagick
+  - TOX_ENV=py27-django18-graphicsmagick APT=graphicsmagick
+  - TOX_ENV=py27-django18-redis
+  - TOX_ENV=py27-django18-wand
+  - TOX_ENV=py27-django18-pgmagick APT='libgraphicsmagick++1-dev libboost-python-dev'
+  - TOX_ENV=py27-django18-dbm
+  - TOX_ENV=py34-django15-pil APT='libjpeg62 libjpeg62-dev zlib1g-dev'
+  - TOX_ENV=py34-django15-imagemagick APT=imagemagick
+  - TOX_ENV=py34-django15-graphicsmagick APT=graphicsmagick
+  - TOX_ENV=py34-django15-redis
+  - TOX_ENV=py34-django15-wand
+  - TOX_ENV=py34-django15-dbm
+  - TOX_ENV=py34-django16-pil APT='libjpeg62 libjpeg62-dev zlib1g-dev'
+  - TOX_ENV=py34-django16-imagemagick APT=imagemagick
+  - TOX_ENV=py34-django16-graphicsmagick APT=graphicsmagick
+  - TOX_ENV=py34-django16-redis
+  - TOX_ENV=py34-django16-wand
+  - TOX_ENV=py34-django16-dbm
+  - TOX_ENV=py34-django17-pil APT='libjpeg62 libjpeg62-dev zlib1g-dev'
+  - TOX_ENV=py34-django17-imagemagick APT=imagemagick
+  - TOX_ENV=py34-django17-graphicsmagick APT=graphicsmagick
+  - TOX_ENV=py34-django17-redis
+  - TOX_ENV=py34-django17-wand
+  - TOX_ENV=py34-django17-dbm
+  - TOX_ENV=py34-django18-pil APT='libjpeg62 libjpeg62-dev zlib1g-dev'
+  - TOX_ENV=py34-django18-imagemagick APT=imagemagick
+  - TOX_ENV=py34-django18-graphicsmagick APT=graphicsmagick
+  - TOX_ENV=py34-django18-redis
+  - TOX_ENV=py34-django18-wand
+  - TOX_ENV=py34-django18-dbm
 
 before_install:
   - sudo apt-get update -qq
   - sudo apt-get install -qq $APT
 
 after_failure:
-  - pip freeze
   - cat /home/travis/.pip/pip.log
 
 after_success:
-  - pip freeze
   - coveralls
 
 install:
-  - pip install -U pip
-  - pip install -q coveralls
-  - pip install -q Pillow $PIP
-  - pip install -q Django$DJANGO_VERSION
-  - pip install flake8
+  - pip install pip wheel
+  - pip install -q coveralls flake8 tox
 
 script:
-  - cd tests && coverage run --source=sorl runtests.py --settings=settings.$SETTINGS
-  - cd .. && flake8 --show-source sorl/
+  - env | sort
+  - tox -e $TOX_ENV
+  - flake8 --show-source sorl/
 
 services:
   - redis-server
diff --git a/AUTHORS b/AUTHORS
index 4122e8d..adbc7e8 100644
--- a/AUTHORS
+++ b/AUTHORS
@@ -3,5 +3,6 @@ sorl-thumbnail was originally created in 2010 at Aino.se by Mikko Hellsing
 The PRIMARY AUTHORS are (and/or have been):
 
   * Mikko Hellsing
-  * Mario César Señoranis Ayala
-  * Rolf Erik Lekang
\ No newline at end of file
+  * M. César Señoranis
+  * Rolf Erik Lekang
+  * Frankie Robertson
\ No newline at end of file
diff --git a/README.rst b/README.rst
index 43e106f..37d5525 100644
--- a/README.rst
+++ b/README.rst
@@ -5,8 +5,8 @@ Thumbnails for Django.
 Features at a glance
 ====================
 
-- Support for Django 1.4, 1.5, 1.6 and 1.7
-- Python 3 support (for Django 1.5, 1.6, 1.7)
+- Support for Django 1.4, 1.5, 1.6, 1.7 and 1.8
+- Python 3 support (for Django 1.5, 1.6, 1.7, 1.8)
 - Storage support
 - Pluggable Engine support for `Pillow`_, `ImageMagick`_, `PIL`_, `Wand`_ and `pgmagick`_
 - Pluggable Key Value Store support (cached db, redis)
@@ -26,18 +26,26 @@ Developers
 ==========
 
 Feel free to create a new Pull request if you want to propose a new feature.
-If you need development support or want to discuss with other developers 
+If you need development support or want to discuss with other developers
 join us in the channel #sorl-thumnbnail at freenode.net or Gitter.
 
 For releases updates and more in deep development discussion use our mailing list
 in Google Groups.
 
 - IRC Channel: irc://irc.freenode.net/#sorl-thumbnail
-   
+
 - Gitter: https://gitter.im/mariocesar/sorl-thumbnail
 
 - Mailing List: sorl-thumbnail at googlegroups.com https://groups.google.com/d/forum/sorl-thumbnail
 
+Tests
+-----
+The tests should run with tox and pytest. Running `tox` will run all tests for all environments.
+However, it is possible to run a certain environment with `tox -e <env>`, a list of all environments
+can be found with `tox -l`. These tests require the dependencies of the different engines defined in
+the documentation. It is possible to install these dependencies into a vagrant image with the
+Vagrantfile in the repo.
+
 User Support
 ============
 
@@ -75,7 +83,7 @@ your project's settings. ::
 
 
 Templates Usage
-----------------
+---------------
 
 All of the examples assume that you first load the thumbnail template tag in
 your template.::
@@ -118,6 +126,22 @@ You can use the 'get_thumbnail'::
 
 See more examples in the section `Low level API examples`_ in the Documentation
 
+--------------------------
+Frequently asked questions
+--------------------------
+
+Is so slow in Amazon S3 !
+-------------------------
+
+Posible related to the implementation of your Amazon S3 Backend, see the issue `#351`_
+due the storage backend reviews if there is an existing thumbnail when tries to
+generate the thumbnail that makes an extensive use of the S3 API
+
+A fast workaround if you are not willing to tweak your storage backend is to set
+the `THUMBNAIL_FORCE_OVERWRITE` setting to `True` by default is `False`, so it will
+avoid to overly query the S3 API
+
+
 
 
 .. |travis| image:: https://secure.travis-ci.org/mariocesar/sorl-thumbnail.png?branch=master
@@ -127,7 +151,6 @@ See more examples in the section `Low level API examples`_ in the Documentation
 .. |coveralls| image:: https://coveralls.io/repos/mariocesar/sorl-thumbnail/badge.png?branch=master
     :target: https://coveralls.io/r/mariocesar/sorl-thumbnail?branch=master
 
-
 .. _`Pillow`: http://pillow.readthedocs.org/en/latest/
 .. _`ImageMagick`: http://www.imagemagick.org/script/index.php
 .. _`PIL`: http://www.pythonware.com/products/pil/
@@ -137,3 +160,4 @@ See more examples in the section `Low level API examples`_ in the Documentation
 .. _`Template examples`: http://sorl-thumbnail.readthedocs.org/en/latest/examples.html#template-examples
 .. _`Model examples`: http://sorl-thumbnail.readthedocs.org/en/latest/examples.html#model-examples
 .. _`Low level API examples`: http://sorl-thumbnail.readthedocs.org/en/latest/examples.html#low-level-api-examples
+.. _ `#351`: https://github.com/mariocesar/sorl-thumbnail/issues/351
\ No newline at end of file
diff --git a/docs/management.rst b/docs/management.rst
index 5919704..26fe4e7 100644
--- a/docs/management.rst
+++ b/docs/management.rst
@@ -32,7 +32,7 @@ you're switching Key Value Store backend.
 .. _thumbnail-clear-delete-referenced:
 
 thumbnail clear_delete_referenced
-===============
+=================================
 ``python manage.py thumbnail clear_delete_referenced``
 
 Equivalent to to ``clear`` but first it will delete all thumbnail files
@@ -42,10 +42,10 @@ long as all the original images still exist this will trigger a regeneration of
 all the thumbnails the Key Value Store knows about.
 
 
-.. _thumbnail-clear:
+.. _thumbnail-clear-delete-all:
 
 thumbnail clear_delete_all
-===============
+==========================
 ``python manage.py thumbnail clear_delete_all``
 
 Equivalent to to ``clear`` but afterwards it will delete all thumbnail files
diff --git a/docs/reference/settings.rst b/docs/reference/settings.rst
index 247b2db..e109766 100644
--- a/docs/reference/settings.rst
+++ b/docs/reference/settings.rst
@@ -298,7 +298,7 @@ options.
 
 
 ``THUMBNAIL_ORIENTATION``
-========================
+=========================
 
 - Default: ``True``
 
diff --git a/docs/template.rst b/docs/template.rst
index ae05632..aa4846b 100644
--- a/docs/template.rst
+++ b/docs/template.rst
@@ -175,7 +175,7 @@ Images are not padded by default, but this can be changed by setting
 ``padding_color``
 ^^^^^^^^^^^^^^^^^
 This is the color to use for padding the image. It defaults to ``#ffffff`` and
-can be globally set with the setting ``THUBMNAIL_PADDING_COLOR``.
+can be globally set with the setting ``THUMBNAIL_PADDING_COLOR``.
 
 
 ``options``
diff --git a/setup.py b/setup.py
index 05793f1..6cd7202 100644
--- a/setup.py
+++ b/setup.py
@@ -27,7 +27,7 @@ setup(
     platforms='any',
     zip_safe=False,
     classifiers=[
-        'Development Status :: 4 - Beta',
+        'Development Status :: 5 - Production/Stable',
         'Environment :: Web Environment',
         'Intended Audience :: Developers',
         'License :: OSI Approved :: BSD License',
@@ -35,9 +35,15 @@ setup(
         'Programming Language :: Python',
         'Programming Language :: Python :: 2.7',
         'Programming Language :: Python :: 3.3',
+        'Programming Language :: Python :: 3.4',
         'Topic :: Internet :: WWW/HTTP :: Dynamic Content',
         'Topic :: Multimedia :: Graphics',
         'Framework :: Django',
+        'Framework :: Django :: 1.4',
+        'Framework :: Django :: 1.5',
+        'Framework :: Django :: 1.6',
+        'Framework :: Django :: 1.7',
+        'Framework :: Django :: 1.8',
     ],
     cmdclass={"test": TestCommand},
 )
diff --git a/sorl/__init__.py b/sorl/__init__.py
index 518b407..5af7ec6 100644
--- a/sorl/__init__.py
+++ b/sorl/__init__.py
@@ -5,10 +5,10 @@ import logging
 
 __author__ = "Mikko Hellsing"
 __license__ = "BSD"
-__version__ = '12.2'
+__version__ = '12.3'
 __maintainer__ = "Mario César Señoranis Ayala"
-__email__ = "mariocesar at creat1va.com"
-__status__ = "Beta"
+__email__ = "mariocesar at humanzilla.com"
+__status__ = "Production/Stable"
 
 
 class NullHandler(logging.Handler):
diff --git a/sorl/thumbnail/base.py b/sorl/thumbnail/base.py
index 9dbd01e..b826fed 100644
--- a/sorl/thumbnail/base.py
+++ b/sorl/thumbnail/base.py
@@ -101,7 +101,8 @@ class ThumbnailBackend(object):
         if not thumbnail.exists():
             try:
                 source_image = default.engine.get_image(source)
-            except IOError:
+            except IOError as e:
+                logger.exception(e)
                 if settings.THUMBNAIL_DUMMY:
                     return DummyImageFile(geometry_string)
                 else:
diff --git a/sorl/thumbnail/compat.py b/sorl/thumbnail/compat.py
index 5a7c4e8..30e5c63 100644
--- a/sorl/thumbnail/compat.py
+++ b/sorl/thumbnail/compat.py
@@ -1,8 +1,8 @@
 from __future__ import unicode_literals
 
 import sys
-import django
 
+import django
 
 __all__ = [
     'json',
@@ -12,13 +12,19 @@ __all__ = [
     'quote',
     'quote_plus',
     'URLError',
+    'get_cache',
     'force_unicode', 'text_type'
 ]
 
-PY2 = sys.version_info[0] == 2
-PY3 = sys.version_info[0] == 3
+PythonVersion = sys.version_info[0]
+
+PY2 = PythonVersion == 2
+PY3 = PythonVersion == 3
+
+# -- import_module
+from importlib import import_module
 
-# Django version
+# -- Related to django 1.5 incompatibility
 
 if django.VERSION < (1, 5):
     from django.utils import simplejson as json
@@ -27,16 +33,36 @@ else:
     import json
     from django.utils.encoding import force_text as force_unicode
 
+# -- Cache
+
+if django.VERSION >= (1, 7):
+    from django.core.cache import caches
+
+    get_cache = lambda cache_name: caches[cache_name]
+else:
+    from django.core.cache import get_cache
+
+# -- Text
+
 try:
     from django.utils.encoding import smart_text
 except ImportError:
     from django.utils.encoding import smart_unicode as smart_text
 
-# Python 2 and 3
+# -- Ordered Dict
+
+try:
+    from collections import OrderedDict
+except ImportError:
+    from django.utils.datastructures import SortedDict as OrderedDict
+
+
+# -- Python 2 and 3
 
 if PY3:
     from urllib.error import URLError
-    from urllib.request import urlopen
+    from urllib.request import Request
+    from urllib.request import urlopen as _urlopen
     from urllib.parse import quote, quote_plus
 
     import urllib.parse as urlparse
@@ -46,17 +72,23 @@ if PY3:
     text_type = str
     string_type = str
 
+
+    def b(s):
+        return s.encode("latin-1")
+
+
     def encode(value, charset='utf-8', errors='ignore'):
         if isinstance(value, bytes):
             return value
         return value.encode(charset, errors)
 
+
     def urlsplit(url):
         return urlparse.urlsplit(url.decode('ascii', 'ignore'))
 
 elif PY2:
-    from urllib2 import URLError
-    from urllib2 import urlopen
+    from urllib2 import URLError, Request
+    from urllib2 import urlopen as _urlopen
     from urllib import quote, quote_plus
 
     import urlparse
@@ -67,7 +99,24 @@ elif PY2:
     string_type = basestring
     urlsplit = urlparse.urlsplit
 
+
+    def b(s):
+        return s
+
+
     def encode(value, charset='utf-8', errors='ignore'):
         if isinstance(value, unicode):
             return value.encode(charset, errors)
         return unicode(value, errors=errors).encode(charset)
+
+
+# -- Urlopen with a proper default user agent
+
+def urlopen(url):
+    from sorl.thumbnail.conf import settings
+
+    req = Request(
+        url,
+        headers={'User-Agent': "python-urllib%s/0.6" % PythonVersion}
+    )
+    return _urlopen(req, timeout=settings.THUMBNAIL_URL_TIMEOUT)
diff --git a/sorl/thumbnail/engines/base.py b/sorl/thumbnail/engines/base.py
index 3aa9f94..b8e2a9f 100644
--- a/sorl/thumbnail/engines/base.py
+++ b/sorl/thumbnail/engines/base.py
@@ -172,19 +172,19 @@ class EngineBase(object):
         """
         Returns the backend image objects from an ImageFile instance
         """
-        raise NotImplemented()
+        raise NotImplementedError()
 
     def get_image_size(self, image):
         """
         Returns the image width and height as a tuple
         """
-        raise NotImplemented()
+        raise NotImplementedError()
 
     def is_valid_image(self, raw_data):
         """
         Checks if the supplied raw data is valid image data
         """
-        raise NotImplemented()
+        raise NotImplementedError()
 
     def _orientation(self, image):
         """
@@ -200,51 +200,51 @@ class EngineBase(object):
 
             RGB, GRAY
         """
-        raise NotImplemented()
+        raise NotImplementedError()
 
     def _remove_border(self, image, image_width, image_height):
         """
         Remove borders around images
         """
-        raise NotImplemented()
+        raise NotImplementedError()
 
     def _entropy_crop(self, image, geometry_width, geometry_height, image_width, image_height):
         """
         Crop the image to the correct aspect ratio
         by removing the lowest entropy parts
         """
-        raise NotImplemented()
+        raise NotImplementedError()
 
     def _scale(self, image, width, height):
         """
         Does the resizing of the image
         """
-        raise NotImplemented()
+        raise NotImplementedError()
 
     def _crop(self, image, width, height, x_offset, y_offset):
         """
         Crops the image
         """
-        raise NotImplemented()
+        raise NotImplementedError()
 
     def _get_raw_data(self, image, format_, quality, image_info=None, progressive=False):
         """
         Gets raw data given the image, format and quality. This method is
         called from :meth:`write`
         """
-        raise NotImplemented()
+        raise NotImplementedError()
 
     def _padding(self, image, geometry, options):
         """
         Pads the image
         """
-        raise NotImplemented()
+        raise NotImplementedError()
 
     def _cropbox(self, image, x, y, x2, y2):
-        raise NotImplemented()
+        raise NotImplementedError()
 
     def _rounded(self, image, r):
-        raise NotImplemented()
+        raise NotImplementedError()
 
     def _blur(self, image, radius):
-        raise NotImplemented()
+        raise NotImplementedError()
diff --git a/sorl/thumbnail/engines/convert_engine.py b/sorl/thumbnail/engines/convert_engine.py
index f8c6888..6926aba 100644
--- a/sorl/thumbnail/engines/convert_engine.py
+++ b/sorl/thumbnail/engines/convert_engine.py
@@ -2,14 +2,15 @@ from __future__ import unicode_literals, with_statement
 import re
 import os
 import subprocess
-from tempfile import NamedTemporaryFile
 
-from django.utils.datastructures import SortedDict
 from django.utils.encoding import smart_str
+from django.core.files.temp import NamedTemporaryFile
 
 from sorl.thumbnail.base import EXTENSIONS
+from sorl.thumbnail.compat import b
 from sorl.thumbnail.conf import settings
 from sorl.thumbnail.engines.base import EngineBase
+from sorl.thumbnail.compat import OrderedDict
 
 
 size_re = re.compile(r'^(?:.+) (?:[A-Z]+) (?P<x>\d+)x(?P<y>\d+)')
@@ -69,7 +70,7 @@ class Engine(EngineBase):
         """
         with NamedTemporaryFile(mode='wb', delete=False) as fp:
             fp.write(source.read())
-        return {'source': fp.name, 'options': SortedDict(), 'size': None}
+        return {'source': fp.name, 'options': OrderedDict(), 'size': None}
 
     def get_image_size(self, image):
         """
@@ -108,7 +109,7 @@ class Engine(EngineBase):
             p = subprocess.Popen(args, stdout=subprocess.PIPE, stderr=subprocess.PIPE)
             p.wait()
             result = p.stdout.read().strip()
-            if result and result != 'unknown':
+            if result and result != b('unknown'):
                 result = int(result)
                 options = image['options']
                 if result == 2:
diff --git a/sorl/thumbnail/engines/pil_engine.py b/sorl/thumbnail/engines/pil_engine.py
index 5cff1e4..db77187 100644
--- a/sorl/thumbnail/engines/pil_engine.py
+++ b/sorl/thumbnail/engines/pil_engine.py
@@ -69,7 +69,7 @@ class Engine(EngineBase):
     def _orientation(self, image):
         try:
             exif = image._getexif()
-        except (AttributeError, IOError, KeyError, IndexError):
+        except:
             exif = None
 
         if exif:
@@ -97,7 +97,12 @@ class Engine(EngineBase):
             if image.mode == 'RGBA':
                 return image  # RGBA is just RGB + Alpha
             if image.mode == 'LA' or (image.mode == 'P' and 'transparency' in image.info):
-                return image.convert('RGBA')
+                newimage = image.convert('RGBA')
+                transparency = image.info.get('transparency')
+                if transparency is not None:
+                    mask = Image.new('L', image.size, color=transparency)
+                    newimage.putalpha(mask)
+                return newimage
             return image.convert('RGB')
         if colorspace == 'GRAY':
             return image.convert('L')
diff --git a/sorl/thumbnail/engines/wand_engine.py b/sorl/thumbnail/engines/wand_engine.py
index 955c2c7..189e2ef 100644
--- a/sorl/thumbnail/engines/wand_engine.py
+++ b/sorl/thumbnail/engines/wand_engine.py
@@ -50,9 +50,15 @@ class Engine(EngineBase):
 
     def _colorspace(self, image, colorspace):
         if colorspace == 'RGB':
-            image.type = 'truecolor'
+            if image.alpha_channel:
+                image.type = 'truecolormatte'
+            else:
+                image.type = 'truecolor'
         elif colorspace == 'GRAY':
-            image.type = 'grayscale'
+            if image.alpha_channel:
+                image.type = 'grayscalematte'
+            else:
+                image.type = 'grayscale'
         else:
             return image
         return image
diff --git a/sorl/thumbnail/fields.py b/sorl/thumbnail/fields.py
index ce4c309..af4cd0c 100644
--- a/sorl/thumbnail/fields.py
+++ b/sorl/thumbnail/fields.py
@@ -47,7 +47,7 @@ class ImageField(models.ImageField):
         return (cls_name, args, kwargs)
 
 
-class ImageFormField(forms.ImageField):
+class ImageFormField(forms.FileField):
     default_error_messages = {
         'invalid_image': _("Upload a valid image. The file you uploaded was "
                            "either not an image or a corrupted image."),
diff --git a/sorl/thumbnail/helpers.py b/sorl/thumbnail/helpers.py
index 24d360d..800e4e2 100644
--- a/sorl/thumbnail/helpers.py
+++ b/sorl/thumbnail/helpers.py
@@ -1,11 +1,10 @@
 from __future__ import unicode_literals
-import math
+
 import hashlib
+import math
 
 from django.core.exceptions import ImproperlyConfigured
-from django.utils.importlib import import_module
-
-from sorl.thumbnail.compat import json, encode, smart_text
+from sorl.thumbnail.compat import encode, json, smart_text, import_module
 
 
 class ThumbnailError(Exception):
diff --git a/sorl/thumbnail/images.py b/sorl/thumbnail/images.py
index 3ed9991..22fc887 100644
--- a/sorl/thumbnail/images.py
+++ b/sorl/thumbnail/images.py
@@ -7,7 +7,6 @@ import re
 from django.core.files.base import File, ContentFile
 from django.core.files.storage import Storage, default_storage
 from django.utils.functional import LazyObject, empty
-
 from sorl.thumbnail import default
 from sorl.thumbnail.conf import settings
 from sorl.thumbnail.compat import (json, urlopen, urlparse, urlsplit,
@@ -16,7 +15,6 @@ from sorl.thumbnail.compat import (json, urlopen, urlparse, urlsplit,
 from sorl.thumbnail.helpers import ThumbnailError, tokey, get_module_class, deserialize
 from sorl.thumbnail.parsers import parse_geometry
 
-
 url_pat = re.compile(r'^(https?|ftp):\/\/')
 
 
@@ -48,7 +46,7 @@ class BaseImageFile(object):
     size = []
 
     def exists(self):
-        raise NotImplemented()
+        raise NotImplementedError()
 
     @property
     def width(self):
@@ -71,7 +69,7 @@ class BaseImageFile(object):
 
     @property
     def url(self):
-        raise NotImplemented()
+        raise NotImplementedError()
 
     src = url
 
@@ -203,11 +201,7 @@ class UrlStorage(Storage):
         return urlparse.urlunsplit((scheme, netloc, path, qs, anchor))
 
     def open(self, name, mode='rb'):
-        return urlopen(
-            self.normalize_url(name),
-            None,
-            settings.THUMBNAIL_URL_TIMEOUT
-        )
+        return urlopen(self.normalize_url(name))
 
     def exists(self, name):
         try:
diff --git a/sorl/thumbnail/kvstores/base.py b/sorl/thumbnail/kvstores/base.py
index 763cd8a..dad35e1 100644
--- a/sorl/thumbnail/kvstores/base.py
+++ b/sorl/thumbnail/kvstores/base.py
@@ -184,7 +184,7 @@ class KVStoreBase(object):
         """
         Gets the value from keystore, returns `None` if not found.
         """
-        raise NotImplemented()
+        raise NotImplementedError()
 
     def _set_raw(self, key, value):
         """
@@ -192,16 +192,16 @@ class KVStoreBase(object):
         chars. Value is a ``unicode`` object with an unknown (reasonable)
         length.
         """
-        raise NotImplemented()
+        raise NotImplementedError()
 
     def _delete_raw(self, *keys):
         """
         Deletes the keys. Silent failure for missing keys.
         """
-        raise NotImplemented()
+        raise NotImplementedError()
 
     def _find_keys_raw(self, prefix):
         """
         Finds all keys with prefix
         """
-        raise NotImplemented()
+        raise NotImplementedError()
diff --git a/sorl/thumbnail/kvstores/cached_db_kvstore.py b/sorl/thumbnail/kvstores/cached_db_kvstore.py
index 8dedaea..3ad238b 100644
--- a/sorl/thumbnail/kvstores/cached_db_kvstore.py
+++ b/sorl/thumbnail/kvstores/cached_db_kvstore.py
@@ -1,4 +1,5 @@
-from django.core.cache import cache, get_cache, InvalidCacheBackendError
+from django.core.cache import cache, InvalidCacheBackendError
+from sorl.thumbnail.compat import get_cache
 from sorl.thumbnail.kvstores.base import KVStoreBase
 from sorl.thumbnail.conf import settings
 from sorl.thumbnail.models import KVStore as KVStoreModel
@@ -11,10 +12,14 @@ class EMPTY_VALUE(object):
 class KVStore(KVStoreBase):
     def __init__(self):
         super(KVStore, self).__init__()
+
+    @property
+    def cache(self):
         try:
-            self.cache = get_cache(settings.THUMBNAIL_CACHE)
+            kv_cache = get_cache(settings.THUMBNAIL_CACHE)
         except InvalidCacheBackendError:
-            self.cache = cache
+            kv_cache = cache
+        return kv_cache
 
     def clear(self, delete_thumbnails=False):
         """
diff --git a/sorl/thumbnail/kvstores/dbm_kvstore.py b/sorl/thumbnail/kvstores/dbm_kvstore.py
index 629f5e6..8a645b6 100644
--- a/sorl/thumbnail/kvstores/dbm_kvstore.py
+++ b/sorl/thumbnail/kvstores/dbm_kvstore.py
@@ -7,6 +7,8 @@ from sorl.thumbnail.conf import settings
 
 try:
     import anydbm as dbm
+except KeyError:
+    import dbm
 except ImportError:
     # Python 3, hopefully
     import dbm
diff --git a/sorl/thumbnail/management/commands/thumbnail.py b/sorl/thumbnail/management/commands/thumbnail.py
index b344d66..2218c2d 100644
--- a/sorl/thumbnail/management/commands/thumbnail.py
+++ b/sorl/thumbnail/management/commands/thumbnail.py
@@ -4,17 +4,17 @@ from __future__ import unicode_literals, print_function
 
 import sys
 
-from django.core.management.base import BaseCommand, CommandError
+from django.core.management.base import LabelCommand, CommandError
 
 from sorl.thumbnail import default
 from sorl.thumbnail.images import delete_all_thumbnails
 
 
-class Command(BaseCommand):
+class Command(LabelCommand):
     help = (
         'Handles thumbnails and key value store'
     )
-    args = '[cleanup, clear clear_delete_referenced clear_delete_all]'
+    missing_args_message = 'Enter one of [cleanup, clear clear_delete_referenced clear_delete_all]'
 
     def handle(self, *labels, **options):
         verbosity = int(options.get('verbosity'))
diff --git a/sorl/thumbnail/migrations/0001_initial.py b/sorl/thumbnail/migrations/0001_initial.py
new file mode 100644
index 0000000..7e4c226
--- /dev/null
+++ b/sorl/thumbnail/migrations/0001_initial.py
@@ -0,0 +1,20 @@
+# -*- coding: utf-8 -*-
+from __future__ import unicode_literals
+
+from django.db import models, migrations
+
+
+class Migration(migrations.Migration):
+
+    dependencies = [
+    ]
+
+    operations = [
+        migrations.CreateModel(
+            name='KVStore',
+            fields=[
+                ('key', models.CharField(serialize=False, db_column='key', max_length=200, primary_key=True)),
+                ('value', models.TextField()),
+            ],
+        ),
+    ]
diff --git a/sorl/thumbnail/migrations/__init__.py b/sorl/thumbnail/migrations/__init__.py
new file mode 100644
index 0000000..e69de29
diff --git a/sorl/thumbnail/templatetags/thumbnail.py b/sorl/thumbnail/templatetags/thumbnail.py
index fd35eef..31b1794 100644
--- a/sorl/thumbnail/templatetags/thumbnail.py
+++ b/sorl/thumbnail/templatetags/thumbnail.py
@@ -86,7 +86,7 @@ class ThumbnailNodeBase(Node):
             return self.nodelist_empty.render(context)
 
     def _render(self, context):
-        raise NotImplemented()
+        raise NotImplementedError()
 
 
 class ThumbnailNode(ThumbnailNodeBase):
diff --git a/tests/runalltests.sh b/tests/runalltests.sh
deleted file mode 100755
index 3682ed3..0000000
--- a/tests/runalltests.sh
+++ /dev/null
@@ -1,6 +0,0 @@
-#/bin/bash
-
-for name in pil pgmagick imagemagick graphicsmagick wand redis dbm
-do
-    ./runtests.py --settings=settings.$name;
-done
diff --git a/tests/runtests.py b/tests/runtests.py
deleted file mode 100755
index bdbd8bd..0000000
--- a/tests/runtests.py
+++ /dev/null
@@ -1,74 +0,0 @@
-#!/usr/bin/env python
-from __future__ import unicode_literals
-import os
-import sys
-from os.path import abspath, dirname, join as pjoin
-
-import django
-from django.conf import settings
-
... 2555 lines suppressed ...

-- 
Alioth's /usr/local/bin/git-commit-notice on /srv/git.debian.org/git/python-modules/packages/sorl-thumbnail.git



More information about the Python-modules-commits mailing list