diff --git a/imagekit/models/fields/__init__.py b/imagekit/models/fields/__init__.py index 92a25d3..517c94e 100644 --- a/imagekit/models/fields/__init__.py +++ b/imagekit/models/fields/__init__.py @@ -1,11 +1,11 @@ import os from django.db import models -from ..files import ProcessedImageFieldFile +from .files import ProcessedImageFieldFile from .utils import ImageSpecFileDescriptor -from ..receivers import configure_receivers +from ... import specs from ...utils import suggest_extension -from ...specs import SpecHost, spec_registry +from ...specs import SpecHost from ...specs.sources import ImageFieldSpecSource @@ -52,9 +52,9 @@ class ImageSpecField(SpecHost): # later, from outside of the model definition. self.set_spec_id(self.spec_id) - # Register the model and field as a source for this spec id - spec_registry.add_source(self.spec_id, - ImageFieldSpecSource(cls, self.image_field)) + # Add the model and field as a source for this spec id + specs.registry.add_source(ImageFieldSpecSource(cls, self.image_field), + self.spec_id) class ProcessedImageField(models.ImageField, SpecHost): @@ -97,6 +97,3 @@ except ImportError: pass else: add_introspection_rules([], [r'^imagekit\.models\.fields\.ProcessedImageField$']) - - -configure_receivers() diff --git a/imagekit/specs/__init__.py b/imagekit/specs/__init__.py index 160612f..eb98975 100644 --- a/imagekit/specs/__init__.py +++ b/imagekit/specs/__init__.py @@ -1,44 +1,35 @@ -from collections import defaultdict from django.conf import settings from hashlib import md5 import os import pickle -from .exceptions import UnknownExtensionError, AlreadyRegistered, NotRegistered -from .imagecache.backends import get_default_image_cache_backend -from .imagecache.strategies import StrategyWrapper -from .lib import StringIO -from .processors import ProcessorPipeline from .signals import source_created, source_changed, source_deleted -from .utils import (open_image, extension_to_format, IKContentFile, img_to_fobj, - suggest_extension) +from ..exceptions import UnknownExtensionError, AlreadyRegistered, NotRegistered +from ..imagecache.backends import get_default_image_cache_backend +from ..imagecache.strategies import StrategyWrapper +from ..lib import StringIO +from ..processors import ProcessorPipeline +from ..utils import (open_image, extension_to_format, IKContentFile, + img_to_fobj, suggest_extension) class SpecRegistry(object): + signals = { + source_created: 'source_created', + source_changed: 'source_changed', + source_deleted: 'source_deleted', + } + def __init__(self): self._specs = {} - self._sources = defaultdict(list) + self._sources = {} + for signal in self.signals.keys(): + signal.connect(lambda *a, **k: self.source_receiver(signal, *a, **k)) def register(self, id, spec): if id in self._specs: raise AlreadyRegistered('The spec with id %s is already registered' % id) self._specs[id] = spec - def add_source(self, id, source): - self._sources[id].append(source) - source_created.connect(receiver, sender, weak, dispatch_uid) - source_changed.connect(receiver, sender, weak, dispatch_uid) - source_deleted.connect(receiver, sender, weak, dispatch_uid) - - def source_receiver(self, source, source_file): - # Get a list of specs that use this source. - ids = (k for k, v in self._sources.items() if source in v) - specs = (self.get_spec(id) for id in ids) - for spec in specs: - spec.image_cache_strategy.invoke_callback(..., source_file) - - def get_sources(self, id): - return self._sources[id] - def unregister(self, id, spec): try: del self._specs[id] @@ -51,8 +42,22 @@ class SpecRegistry(object): except KeyError: raise NotRegistered('The spec with id %s is not registered' % id) + def add_source(self, source, spec_id): + """ + Associates a source with a spec id -spec_registry = SpecRegistry() + """ + if source not in self._sources: + self._sources[source] = set() + self._sources[source].add(spec_id) + + def source_receiver(self, signal, source, source_file): + if source not in self._sources: + return + + callback_name = self._signals[signal] + for spec in (self.get_spec(id) for id in self._sources[source]): + spec.image_cache_strategy.invoke_callback(callback_name, source_file) class BaseImageSpec(object): @@ -227,7 +232,7 @@ class SpecHost(object): """ self.spec_id = id - spec_registry.register(id, self._original_spec) + registry.register(id, self._original_spec) @property def spec(self): @@ -240,4 +245,7 @@ class SpecHost(object): """ if not getattr(self, 'spec_id', None): raise Exception('Object %s has no spec id.' % self) - return spec_registry.get_spec(self.spec_id) + return registry.get_spec(self.spec_id) + + +registry = SpecRegistry() diff --git a/imagekit/specs/sources.py b/imagekit/specs/sources.py index 88e6156..82b118b 100644 --- a/imagekit/specs/sources.py +++ b/imagekit/specs/sources.py @@ -12,7 +12,7 @@ def ik_model_receiver(fn): @wraps(fn) def receiver(self, sender, **kwargs): if sender in (src.model_class for src in self._sources): - fn(sender, **kwargs) + fn(self, sender=sender, **kwargs) return receiver @@ -38,8 +38,8 @@ class ModelSignalRouter(object): """ self.init_instance(instance) - instance._ik['source_hashes'] = dict((k, hash(v.source_file)) - for k, v in self.get_field_dict(instance).items()) + instance._ik['source_hashes'] = dict((attname, hash(file_field)) + for attname, file_field in self.get_field_dict(instance).items()) return instance._ik['source_hashes'] def get_field_dict(self, instance): @@ -68,9 +68,8 @@ class ModelSignalRouter(object): for attname, file in self.get_field_dict(instance): self.dispatch_signal(source_deleted, sender, file) - @classmethod @ik_model_receiver - def post_init_receiver(self, sender, instance, **kwargs): + def post_init_receiver(self, sender, instance=None, **kwargs): self.update_source_hashes(instance) def dispatch_signal(self, signal, model_class, file):