Canonicalize sets and dicts before hashing

This commit is contained in:
Matthew Tretter 2013-04-25 02:29:27 -04:00
parent 3e019f5dac
commit f5b171979b
2 changed files with 34 additions and 4 deletions

31
imagekit/hashers.py Normal file
View file

@ -0,0 +1,31 @@
from copy import copy
from hashlib import md5
from pickle import Pickler, MARK, DICT
from types import DictionaryType
from .lib import StringIO
class CanonicalizingPickler(Pickler):
dispatch = copy(Pickler.dispatch)
def save_set(self, obj):
rv = obj.__reduce_ex__(0)
rv = (rv[0], (sorted(rv[1][0]),), rv[2])
self.save_reduce(obj=obj, *rv)
dispatch[set] = save_set
def save_dict(self, obj):
write = self.write
write(MARK + DICT)
self.memoize(obj)
self._batch_setitems(sorted(obj.iteritems()))
dispatch[DictionaryType] = save_dict
def pickle(obj):
file = StringIO()
CanonicalizingPickler(file, 0).dump(obj)
return md5(file.getvalue()).hexdigest()

View file

@ -1,9 +1,8 @@
from django.conf import settings
from django.db.models.fields.files import ImageFieldFile
from hashlib import md5
import pickle
from ..cachefiles.backends import get_default_cachefile_backend
from ..cachefiles.strategies import StrategyWrapper
from .. import hashers
from ..exceptions import AlreadyRegistered, MissingSource
from ..processors import ProcessorPipeline
from ..utils import open_image, img_to_fobj, get_by_qname
@ -115,13 +114,13 @@ class ImageSpec(BaseImageSpec):
self.source = getattr(field_data['instance'], field_data['attname'])
def get_hash(self):
return md5(pickle.dumps([
return hashers.pickle([
self.source.name,
self.processors,
self.format,
self.options,
self.autoconvert,
])).hexdigest()
])
def generate(self):
if not self.source: