Skip to content

Commit f724cb0

Browse files
committed
Merge branch 'release/4.0'
* release/4.0: Bump version to 4.0 Universal wheels! Replaces #301 autodiscover works with AppConfig Ignore autogenerated CTags file Do not try south modelinspector when not needed Make it possible to configure IMAGEKIT_CACHE_TIMEOUT Test against Django 1.11 Close the file only if it has been opened locally Cleanup caching configuration updated readme.rst with a svg badge honor post_save's update_fields and only fire the source_saved signal when needed Ignore VSCode workspace config files Fixed #350: Error when trying to access width/height after url Fixes #382: Tests no longer leave junk Fixes #379 Support for Django 1.10 Ignore .idea from git Include the test suite in the sourcetarball but do not install it. Make travis happy Drop support for older Django and Python versions Replace Lenna image in tests with a truly free alternative. Move compat module outside of templatetags package Fix test requirements for django 1.9 and Python3.5
2 parents bc93ec2 + 46d2a9e commit f724cb0

31 files changed

+313
-185
lines changed

.gitignore

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,11 +4,14 @@
44
*.pyc
55
.DS_Store
66
.tox
7+
.idea
8+
.vscode
79
MANIFEST
810
build
911
dist
1012
/tests/media/*
11-
!/tests/media/lenna.png
13+
!/tests/media/reference.png
1214
/venv
1315
/venv3
1416
/.env
17+
/tags

.travis.yml

Lines changed: 52 additions & 36 deletions
Original file line numberDiff line numberDiff line change
@@ -1,46 +1,62 @@
1+
12
language: python
2-
python: "2.7"
3+
34
sudo: false
45

5-
env:
6-
- TOX_ENV=py26-django12
7-
- TOX_ENV=py26-django13
8-
- TOX_ENV=py26-django14
9-
- TOX_ENV=py26-django15
10-
- TOX_ENV=py26-django16
11-
- TOX_ENV=py27-django12
12-
- TOX_ENV=py27-django13
13-
- TOX_ENV=py27-django14
14-
- TOX_ENV=py27-django15
15-
- TOX_ENV=py27-django16
16-
- TOX_ENV=py27-django17
17-
- TOX_ENV=py27-django18
18-
- TOX_ENV=py27-django19
19-
- TOX_ENV=py32-django15
20-
- TOX_ENV=py32-django16
21-
- TOX_ENV=py32-django17
22-
- TOX_ENV=py32-django18
23-
- TOX_ENV=py33-django15
24-
- TOX_ENV=py33-django16
25-
- TOX_ENV=py33-django17
26-
- TOX_ENV=py33-django18
27-
- TOX_ENV=py34-django16
28-
- TOX_ENV=py34-django17
29-
- TOX_ENV=py34-django18
30-
- TOX_ENV=py34-django19
31-
- TOX_ENV=py35-django19
6+
install:
7+
- pip install tox
8+
9+
script:
10+
- tox
3211

3312
matrix:
34-
# Python 3.5 not yet available on travis, watch this to see when it is.
3513
fast_finish: true
36-
allow_failures:
37-
- env: TOX_ENV=py35-django19
38-
39-
install:
40-
- pip install tox --use-mirrors
14+
include:
15+
- env: TOXENV=py27-django14
16+
python: 2.7
17+
- env: TOXENV=py27-django15
18+
python: 2.7
19+
- env: TOXENV=py27-django16
20+
python: 2.7
21+
- env: TOXENV=py27-django17
22+
python: 2.7
23+
- env: TOXENV=py27-django18
24+
python: 2.7
25+
- env: TOXENV=py27-django19
26+
python: 2.7
27+
- env: TOXENV=py27-django110
28+
python: 2.7
29+
- env: TOXENV=py27-django111
30+
python: 2.7
31+
- env: TOXENV=py33-django15
32+
python: 3.3
33+
- env: TOXENV=py33-django16
34+
python: 3.3
35+
- env: TOXENV=py33-django17
36+
python: 3.3
37+
- env: TOXENV=py33-django18
38+
python: 3.3
39+
- env: TOXENV=py34-django16
40+
python: 3.4
41+
- env: TOXENV=py34-django17
42+
python: 3.4
43+
- env: TOXENV=py34-django18
44+
python: 3.4
45+
- env: TOXENV=py34-django19
46+
python: 3.4
47+
- env: TOXENV=py34-django110
48+
python: 3.4
49+
- env: TOXENV=py34-django111
50+
python: 3.4
51+
- env: TOXENV=py35-django18
52+
python: 3.5
53+
- env: TOXENV=py35-django19
54+
python: 3.5
55+
- env: TOXENV=py35-django110
56+
python: 3.5
57+
- env: TOXENV=py35-django111
58+
python: 3.5
4159

42-
script:
43-
- tox -e $TOX_ENV
4460

4561
notifications:
4662
irc: "irc.freenode.org#imagekit"

MANIFEST.in

Lines changed: 15 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,18 @@
11
include AUTHORS
22
include LICENSE
33
include README.rst
4-
recursive-include docs *
5-
recursive-include imagekit/templates *
6-
prune tests
4+
include testrunner.py
5+
include setup.cfg
6+
include tests/*.py
7+
include tests/assets/Lenna.png
8+
include tests/assets/lenna-*.jpg
9+
include tests/media/lenna.png
10+
prune tests/media/CACHE
11+
prune tests/media/b
12+
prune tests/media/photos
13+
include docs/Makefile
14+
include docs/conf.py
15+
include docs/make.bat
16+
include docs/*.rst
17+
recursive-include docs/_themes LICENSE README.rst flask_theme_support.py theme.conf *.css_t *.css *.html
18+
recursive-include imagekit/templates *.html

README.rst

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
|Build Status|_
22

3-
.. |Build Status| image:: https://travis-ci.org/matthewwithanm/django-imagekit.png?branch=develop
3+
.. |Build Status| image:: https://travis-ci.org/matthewwithanm/django-imagekit.svg?branch=develop
44
.. _Build Status: https://travis-ci.org/matthewwithanm/django-imagekit
55

66
ImageKit is a Django app for processing images. Need a thumbnail? A

docs/caching.rst

Lines changed: 15 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -100,13 +100,21 @@ ImageKit. Each has its own pros and cons.
100100
Caching Data About Generated Files
101101
----------------------------------
102102

103-
The easiest, and most significant improvement you can make to improve the
104-
performance of your site is to have ImageKit cache the state of your generated
105-
files. The default cache file backend will already do this (if ``DEBUG`` is
106-
``False``), using your default Django cache backend, but you can make it way
107-
better by setting ``IMAGEKIT_CACHE_BACKEND``. Generally, once a file is
108-
generated, you will never be removing it; therefore, if you can, you should set
109-
``IMAGEKIT_CACHE_BACKEND`` to a cache backend that will cache forever.
103+
Generally, once a file is generated, you will never be removing it, so by
104+
default ImageKit will use default cache to cache the state of generated
105+
files "forever" (or only 5 minutes when ``DEBUG = True``).
106+
107+
The time for which ImageKit will cache state is configured with
108+
``IMAGEKIT_CACHE_TIMEOUT``. If set to ``None`` this means "never expire"
109+
(default when ``DEBUG = False``). You can reduce this timeout if you want
110+
or set it to some numeric value in seconds if your cache backend behaves
111+
differently and for example do not cache values if timeout is ``None``.
112+
113+
If you clear your cache durring deployment or some other reason probably
114+
you do not want to lose the cache for generated images especcialy if you
115+
are using some slow remote storage (like Amazon S3). Then you can configure
116+
seprate cache (for example redis) in your ``CACHES`` config and tell ImageKit
117+
to use it instead of the default cache by setting ``IMAGEKIT_CACHE_BACKEND``.
110118

111119

112120
Pre-Generating Images

docs/configuration.rst

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -55,6 +55,15 @@ Settings
5555
.. _`Django cache section`: https://docs.djangoproject.com/en/1.8/topics/cache/#accessing-the-cache
5656

5757

58+
.. attribute:: IMAGEKIT_CACHE_TIMEOUT
59+
60+
:default: ``None``
61+
62+
Use when you need to override the timeout used to cache file state.
63+
By default it is "cache forever".
64+
It's highly recommended that you use a very high timeout.
65+
66+
5867
.. attribute:: IMAGEKIT_CACHE_PREFIX
5968

6069
:default: ``'imagekit:'``

imagekit/cachefiles/backends.py

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@
22
import warnings
33
from copy import copy
44
from django.core.exceptions import ImproperlyConfigured
5+
from django.conf import settings
56

67

78
class CacheFileState(object):
@@ -52,8 +53,7 @@ class CachedFileBackend(object):
5253
@property
5354
def cache(self):
5455
if not getattr(self, '_cache', None):
55-
from django.conf import settings
56-
self._cache = get_cache(settings.IMAGEKIT_CACHE_BACKEND)
56+
self._cache = get_cache()
5757
return self._cache
5858

5959
def get_key(self, file):
@@ -75,7 +75,7 @@ def set_state(self, file, state):
7575
if state == CacheFileState.DOES_NOT_EXIST:
7676
self.cache.set(key, state, self.existence_check_timeout)
7777
else:
78-
self.cache.set(key, state)
78+
self.cache.set(key, state, settings.IMAGEKIT_CACHE_TIMEOUT)
7979

8080
def __getstate__(self):
8181
state = copy(self.__dict__)
File renamed without changes.

imagekit/conf.py

Lines changed: 14 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
from appconf import AppConf
22
from django.conf import settings
3+
from django.core.exceptions import ImproperlyConfigured
34

45

56
class ImageKitConf(AppConf):
@@ -13,32 +14,24 @@ class ImageKitConf(AppConf):
1314

1415
CACHE_BACKEND = None
1516
CACHE_PREFIX = 'imagekit:'
17+
CACHE_TIMEOUT = None
1618
USE_MEMCACHED_SAFE_CACHE_KEY = True
1719

1820
def configure_cache_backend(self, value):
1921
if value is None:
20-
# DEFAULT_CACHE_ALIAS doesn't exist in Django<=1.2
21-
try:
22-
from django.core.cache import DEFAULT_CACHE_ALIAS as default_cache_alias
23-
except ImportError:
24-
default_cache_alias = 'default'
25-
26-
caches = getattr(settings, 'CACHES', None)
27-
if caches is None:
28-
# Support Django<=1.2 there is no default `CACHES` setting
29-
try:
30-
from django.core.cache.backends.dummy import DummyCache
31-
except ImportError:
32-
dummy_cache = 'dummy://'
33-
else:
34-
dummy_cache = 'django.core.cache.backends.dummy.DummyCache'
35-
return dummy_cache
36-
37-
if default_cache_alias in caches:
38-
value = default_cache_alias
39-
else:
40-
raise ValueError("The default cache alias '%s' is not available in CACHES" % default_cache_alias)
22+
from django.core.cache import DEFAULT_CACHE_ALIAS
23+
return DEFAULT_CACHE_ALIAS
4124

25+
if value not in settings.CACHES:
26+
raise ImproperlyConfigured("{0} is not present in settings.CACHES".format(value))
27+
28+
return value
29+
30+
def configure_cache_timeout(self, value):
31+
if value is None and settings.DEBUG:
32+
# If value is not configured and is DEBUG set it to 5 minutes
33+
return 300
34+
# Otherwise leave it as is. If it is None then valies will never expire
4235
return value
4336

4437
def configure_default_file_storage(self, value):

imagekit/files.py

Lines changed: 12 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -56,7 +56,18 @@ def _get_size(self):
5656

5757
def open(self, mode='rb'):
5858
self._require_file()
59-
self.file.open(mode)
59+
try:
60+
self.file.open(mode)
61+
except ValueError:
62+
# if the underlaying file can't be reopened
63+
# then we will use the storage to try to open it again
64+
if self.file.closed:
65+
# clear cached file instance
66+
del self.file
67+
# Because file is a property we can acces it after
68+
# we deleted it
69+
return self.file.open(mode)
70+
raise
6071

6172
def _get_closed(self):
6273
file = getattr(self, '_file', None)

0 commit comments

Comments
 (0)