django-imagekit/imagekit/utils.py

155 lines
4.7 KiB
Python
Raw Permalink Normal View History

from __future__ import unicode_literals
2012-10-18 01:00:32 +00:00
import logging
import re
from tempfile import NamedTemporaryFile
from hashlib import md5
2009-01-08 21:11:15 +00:00
from django.conf import settings
2012-09-06 01:50:11 +00:00
from django.core.exceptions import ImproperlyConfigured
from django.core.files import File
2012-09-06 01:50:11 +00:00
from django.utils.importlib import import_module
from pilkit.utils import *
2013-12-14 18:02:21 +00:00
from .lib import NullHandler, force_bytes
bad_memcached_key_chars = re.compile('[\u0000-\u001f\\s]+')
2011-09-22 00:12:49 +00:00
_autodiscovered = False
2011-09-22 00:12:49 +00:00
def get_nonabstract_descendants(model):
""" Returns all non-abstract descendants of the model. """
if not model._meta.abstract:
yield model
for s in model.__subclasses__():
for m in get_nonabstract_descendants(s):
yield m
2013-02-01 03:01:01 +00:00
def get_by_qname(path, desc):
2012-09-06 01:50:11 +00:00
try:
dot = path.rindex('.')
except ValueError:
raise ImproperlyConfigured("%s isn't a %s module." % (path, desc))
2013-02-01 03:01:01 +00:00
module, objname = path[:dot], path[dot + 1:]
2012-09-06 01:50:11 +00:00
try:
mod = import_module(module)
except ImportError as e:
2012-09-06 01:50:11 +00:00
raise ImproperlyConfigured('Error importing %s module %s: "%s"' %
(desc, module, e))
try:
2013-02-01 03:01:01 +00:00
obj = getattr(mod, objname)
return obj
2012-09-06 01:50:11 +00:00
except AttributeError:
2013-02-01 03:01:01 +00:00
raise ImproperlyConfigured('%s module "%s" does not define "%s"'
% (desc[0].upper() + desc[1:], module, objname))
2012-09-06 01:50:11 +00:00
_singletons = {}
def get_singleton(class_path, desc):
global _singletons
2013-02-01 03:01:01 +00:00
cls = get_by_qname(class_path, desc)
2012-09-06 01:50:11 +00:00
instance = _singletons.get(cls)
if not instance:
instance = _singletons[cls] = cls()
return instance
2012-02-14 03:05:33 +00:00
def autodiscover():
"""
Auto-discover INSTALLED_APPS imagegenerators.py modules and fail silently
when not present. This forces an import on them to register any admin bits
they may want.
2012-02-14 03:05:33 +00:00
Copied from django.contrib.admin
"""
global _autodiscovered
if _autodiscovered:
return
2012-02-14 03:05:33 +00:00
from django.conf import settings
from django.utils.importlib import import_module
from django.utils.module_loading import module_has_submodule
_autodiscovered = True
2012-02-14 03:05:33 +00:00
for app in settings.INSTALLED_APPS:
mod = import_module(app)
# Attempt to import the app's admin module.
try:
import_module('%s.imagegenerators' % app)
2012-02-14 03:05:33 +00:00
except:
# Decide whether to bubble up this error. If the app just
# doesn't have an imagegenerators module, we can ignore the error
2012-02-14 03:05:33 +00:00
# attempting to import it, otherwise we want it to bubble up.
if module_has_submodule(mod, 'imagegenerators'):
2012-02-14 03:05:33 +00:00
raise
2012-10-18 01:00:32 +00:00
def get_logger(logger_name='imagekit', add_null_handler=True):
logger = logging.getLogger(logger_name)
if add_null_handler:
logger.addHandler(NullHandler())
2012-10-18 01:00:32 +00:00
return logger
2013-01-24 02:47:54 +00:00
def get_field_info(field_file):
"""
A utility for easily extracting information about the host model from a
Django FileField (or subclass). This is especially useful for when you want
to alter processors based on a property of the source model. For example::
class MySpec(ImageSpec):
def __init__(self, source):
instance, attname = get_field_info(source)
self.processors = [SmartResize(instance.thumbnail_width,
instance.thumbnail_height)]
"""
return (
getattr(field_file, 'instance', None),
getattr(getattr(field_file, 'field', None), 'attname', None),
)
def generate(generator):
"""
Calls the ``generate()`` method of a generator instance, and then wraps the
result in a Django File object so Django knows how to save it.
"""
content = generator.generate()
# If the file doesn't have a name, Django will raise an Exception while
# trying to save it, so we create a named temporary file.
if not getattr(content, 'name', None):
f = NamedTemporaryFile()
f.write(content.read())
f.seek(0)
content = f
return File(content)
def call_strategy_method(file, method_name):
strategy = getattr(file, 'cachefile_strategy', None)
fn = getattr(strategy, method_name, None)
if fn is not None:
fn(file)
def sanitize_cache_key(key):
if settings.IMAGEKIT_USE_MEMCACHED_SAFE_CACHE_KEY:
# Memcached keys can't contain whitespace or control characters.
new_key = bad_memcached_key_chars.sub('', key)
# The also can't be > 250 chars long. Since we don't know what the
# user's cache ``KEY_FUNCTION`` setting is like, we'll limit it to 200.
if len(new_key) >= 200:
new_key = '%s:%s' % (new_key[:200-33], md5(force_bytes(key)).hexdigest())
key = new_key
return key