Renaming/repackaging of generated file related classes

This commit is contained in:
Matthew Tretter 2013-01-31 10:03:42 -05:00
parent 8e6abc1e65
commit d6b73b8da7
14 changed files with 95 additions and 94 deletions

View file

@ -3,11 +3,11 @@ from django.conf import settings
class ImageKitConf(AppConf):
DEFAULT_GENERATEDFILE_BACKEND = 'imagekit.generators.filebackends.Simple'
DEFAULT_GENERATEDFILE_BACKEND = 'imagekit.generatedfiles.backends.Simple'
CACHE_BACKEND = None
GENERATED_FILE_DIR = 'generated/images'
CACHE_PREFIX = 'imagekit:'
DEFAULT_IMAGE_GENERATOR_STRATEGY = 'imagekit.generators.strategies.JustInTime'
DEFAULT_GENERATEDFILE_STRATEGY = 'imagekit.generatedfiles.strategies.JustInTime'
DEFAULT_FILE_STORAGE = 'django.core.files.storage.FileSystemStorage'
def configure_cache_backend(self, value):

View file

@ -1,13 +1,7 @@
from django.conf import settings
from django.core.files.base import ContentFile, File
from django.core.files.images import ImageFile
from django.core.files.base import File, ContentFile
from django.utils.encoding import smart_str, smart_unicode
from django.utils.functional import LazyObject
import os
from .registry import generator_registry
from .signals import before_access
from .utils import (format_to_mimetype, extension_to_mimetype, get_logger,
get_singleton, generate)
from .utils import format_to_mimetype, extension_to_mimetype
class BaseIKFile(File):
@ -72,63 +66,6 @@ class BaseIKFile(File):
file.close()
class GeneratedImageFile(BaseIKFile, ImageFile):
"""
A file that represents the result of a generator. Creating an instance of
this class is not enough to trigger the generation of the file. In fact,
one of the main points of this class is to allow the creation of the file
to be deferred until the time that the image generator strategy requires it.
"""
def __init__(self, generator, name=None, storage=None, generatedfile_backend=None):
"""
:param generator: The object responsible for generating a new image.
:param name: The filename
:param storage: A Django storage object that will be used to save the
file.
:param generatedfile_backend: The object responsible for managing the
state of the file.
"""
self.generator = generator
self.name = name or getattr(generator, 'generatedfile_name', None)
storage = storage or getattr(generator, 'generatedfile_storage',
None) or get_singleton(settings.IMAGEKIT_DEFAULT_FILE_STORAGE,
'file storage backend')
self.generatedfile_backend = generatedfile_backend or getattr(generator,
'generatedfile_backend', None)
super(GeneratedImageFile, self).__init__(storage=storage)
def _require_file(self):
before_access.send(sender=self, file=self)
return super(GeneratedImageFile, self)._require_file()
def generate(self, force=False):
if force:
self._generate()
else:
self.generatedfile_backend.ensure_exists(self)
def _generate(self):
# Generate the file
content = generate(self.generator)
actual_name = self.storage.save(self.name, content)
if actual_name != self.name:
get_logger().warning('The storage backend %s did not save the file'
' with the requested name ("%s") and instead used'
' "%s". This may be because a file already existed with'
' the requested name. If so, you may have meant to call'
' ensure_exists() instead of generate(), or there may be a'
' race condition in the file backend %s. The saved file'
' will not be used.' % (self.storage,
self.name, actual_name,
self.generatedfile_backend))
class IKContentFile(ContentFile):
"""
Wraps a ContentFile in a file-like object with a filename and a
@ -156,14 +93,3 @@ class IKContentFile(ContentFile):
def __unicode__(self):
return smart_unicode(self.file.name or u'')
class LazyGeneratedImageFile(LazyObject):
def __init__(self, generator_id, *args, **kwargs):
super(LazyGeneratedImageFile, self).__init__()
def setup():
generator = generator_registry.get(generator_id, *args, **kwargs)
self._wrapped = GeneratedImageFile(generator)
self.__dict__['_setup'] = setup

View file

@ -0,0 +1,75 @@
from django.conf import settings
from django.core.files.images import ImageFile
from django.utils.functional import LazyObject
from ..files import BaseIKFile
from ..registry import generator_registry
from ..signals import before_access
from ..utils import get_logger, get_singleton, generate
class GeneratedImageFile(BaseIKFile, ImageFile):
"""
A file that represents the result of a generator. Creating an instance of
this class is not enough to trigger the generation of the file. In fact,
one of the main points of this class is to allow the creation of the file
to be deferred until the time that the generated file strategy requires it.
"""
def __init__(self, generator, name=None, storage=None, generatedfile_backend=None):
"""
:param generator: The object responsible for generating a new image.
:param name: The filename
:param storage: A Django storage object that will be used to save the
file.
:param generatedfile_backend: The object responsible for managing the
state of the file.
"""
self.generator = generator
self.name = name or getattr(generator, 'generatedfile_name', None)
storage = storage or getattr(generator, 'generatedfile_storage',
None) or get_singleton(settings.IMAGEKIT_DEFAULT_FILE_STORAGE,
'file storage backend')
self.generatedfile_backend = generatedfile_backend or getattr(generator,
'generatedfile_backend', None)
super(GeneratedImageFile, self).__init__(storage=storage)
def _require_file(self):
before_access.send(sender=self, file=self)
return super(GeneratedImageFile, self)._require_file()
def generate(self, force=False):
if force:
self._generate()
else:
self.generatedfile_backend.ensure_exists(self)
def _generate(self):
# Generate the file
content = generate(self.generator)
actual_name = self.storage.save(self.name, content)
if actual_name != self.name:
get_logger().warning('The storage backend %s did not save the file'
' with the requested name ("%s") and instead used'
' "%s". This may be because a file already existed with'
' the requested name. If so, you may have meant to call'
' ensure_exists() instead of generate(), or there may be a'
' race condition in the file backend %s. The saved file'
' will not be used.' % (self.storage,
self.name, actual_name,
self.generatedfile_backend))
class LazyGeneratedImageFile(LazyObject):
def __init__(self, generator_id, *args, **kwargs):
super(LazyGeneratedImageFile, self).__init__()
def setup():
generator = generator_registry.get(generator_id, *args, **kwargs)
self._wrapped = GeneratedImageFile(generator)
self.__dict__['_setup'] = setup

View file

@ -39,7 +39,7 @@ class DictStrategy(object):
class StrategyWrapper(LazyObject):
def __init__(self, strategy):
if isinstance(strategy, basestring):
strategy = get_singleton(strategy, 'generator strategy')
strategy = get_singleton(strategy, 'generated file strategy')
elif isinstance(strategy, dict):
strategy = DictStrategy(strategy)
elif callable(strategy):

View file

@ -27,14 +27,14 @@ class ImageSpecField(SpecHostField):
"""
def __init__(self, processors=None, format=None, options=None,
source=None, generatedfile_storage=None, autoconvert=None,
generatedfile_backend=None, generator_strategy=None, spec=None,
generatedfile_backend=None, generatedfile_strategy=None, spec=None,
id=None):
SpecHost.__init__(self, processors=processors, format=format,
options=options, generatedfile_storage=generatedfile_storage,
autoconvert=autoconvert,
generatedfile_backend=generatedfile_backend,
generator_strategy=generator_strategy, spec=spec,
generatedfile_strategy=generatedfile_strategy, spec=spec,
spec_id=id)
# TODO: Allow callable for source. See https://github.com/jdriscoll/django-imagekit/issues/158#issuecomment-10921664

View file

@ -1,4 +1,4 @@
from ...files import GeneratedImageFile
from ...generatedfiles import GeneratedImageFile
from django.db.models.fields.files import ImageField

View file

@ -54,8 +54,8 @@ class GeneratorRegistry(object):
class SourceGroupRegistry(object):
"""
The source group registry is responsible for listening to source_* signals
on source groups, and relaying them to the image generator strategies of the
appropriate generators.
on source groups, and relaying them to the image generated file strategies
of the appropriate generators.
In addition, registering a new source group also registers its generated
files with that registry.
@ -92,7 +92,7 @@ class SourceGroupRegistry(object):
Relay source group signals to the appropriate spec strategy.
"""
from .files import GeneratedImageFile
from .generatedfiles import GeneratedImageFile
source_group = sender
# Ignore signals from unregistered groups.

View file

@ -3,8 +3,8 @@ from django.db.models.fields.files import ImageFieldFile
from hashlib import md5
import os
import pickle
from ..generators.filebackends import get_default_generatedfile_backend
from ..generators.strategies import StrategyWrapper
from ..generatedfiles.backends import get_default_generatedfile_backend
from ..generatedfiles.strategies import StrategyWrapper
from ..processors import ProcessorPipeline
from ..utils import open_image, img_to_fobj, suggest_extension
from ..registry import generator_registry, register
@ -27,17 +27,17 @@ class BaseImageSpec(object):
"""
generator_strategy = settings.IMAGEKIT_DEFAULT_IMAGE_GENERATOR_STRATEGY
generatedfile_strategy = settings.IMAGEKIT_DEFAULT_GENERATEDFILE_STRATEGY
"""
A dictionary containing callbacks that allow you to customize how and when
the image file is created. Defaults to
``IMAGEKIT_DEFAULT_IMAGE_GENERATOR_STRATEGY``.
``IMAGEKIT_DEFAULT_GENERATEDFILE_STRATEGY``.
"""
def __init__(self):
self.generatedfile_backend = self.generatedfile_backend or get_default_generatedfile_backend()
self.generator_strategy = StrategyWrapper(self.generator_strategy)
self.generatedfile_strategy = StrategyWrapper(self.generatedfile_strategy)
def generate(self):
raise NotImplementedError

View file

@ -3,7 +3,7 @@ Source groups are the means by which image spec sources are identified. They
have two responsibilities:
1. To dispatch ``source_created``, ``source_changed``, and ``source_deleted``
signals. (These will be relayed to the corresponding specs' generator
signals. (These will be relayed to the corresponding specs' generated file
strategies.)
2. To provide the source files that they represent, via a generator method named
``files()``. (This is used by the generateimages management command for
@ -13,7 +13,7 @@ have two responsibilities:
from django.db.models.signals import post_init, post_save, post_delete
from django.utils.functional import wraps
from ..files import LazyGeneratedImageFile
from ..generatedfiles import LazyGeneratedImageFile
from ..signals import source_created, source_changed, source_deleted

View file

@ -2,7 +2,7 @@ from django import template
from django.utils.html import escape
from django.utils.safestring import mark_safe
from .compat import parse_bits
from ..files import GeneratedImageFile
from ..generatedfiles import GeneratedImageFile
from ..registry import generator_registry

View file

@ -425,7 +425,7 @@ def generate(generator):
def call_strategy_method(generator, method_name, *args, **kwargs):
strategy = getattr(generator, 'generator_strategy', None)
strategy = getattr(generator, 'generatedfile_strategy', None)
fn = getattr(strategy, method_name, None)
if fn is not None:
fn(*args, **kwargs)