Use platform independant hashing for transformations.
Signed-off-by: Roberto Rosario <roberto.rosario.gonzalez@gmail.com>
This commit is contained in:
@@ -91,6 +91,7 @@
|
||||
DOCUMENTS_RECENT_COUNT has been renamed to
|
||||
DOCUMENTS_RECENT_ACCESS_COUNT. New setting
|
||||
DOCUMENTS_RECENT_ADDED_COUNT added.
|
||||
- Use platform independant hashing for transformations.
|
||||
|
||||
3.0.3 (2018-08-17)
|
||||
==================
|
||||
|
||||
@@ -2,3 +2,14 @@ from __future__ import unicode_literals
|
||||
|
||||
TEST_TRANSFORMATION_NAME = 'rotate'
|
||||
TEST_TRANSFORMATION_ARGUMENT = 'degrees: 180'
|
||||
TEST_TRANSFORMATION_COMBINED_CACHE_HASH = '384bf78014d2aed7255d9e548a0694c70af0b22545653214bcceb1ac6286b5f7'
|
||||
TEST_TRANSFORMATION_RESIZE_CACHE_HASH = '4aa319f5a6950985a19380a1f279a66769d04138bd1583844270fe8c269260fc'
|
||||
TEST_TRANSFORMATION_RESIZE_CACHE_HASH_2 = 'cc8d220d40e810b995181c0c69b44b7a61c3bb039c0be96a5465fcaf698ca99a'
|
||||
TEST_TRANSFORMATION_RESIZE_HEIGHT = 528
|
||||
TEST_TRANSFORMATION_RESIZE_HEIGHT_2 = 529
|
||||
TEST_TRANSFORMATION_RESIZE_WIDTH = 123
|
||||
TEST_TRANSFORMATION_RESIZE_WIDTH_2 = 124
|
||||
TEST_TRANSFORMATION_ROTATE_CACHE_HASH = 'df6a5854fccdd3a56145fcd7f7bf52bdf95fe940d6611d435e80dfcaca3b61ac'
|
||||
TEST_TRANSFORMATION_ROTATE_DEGRESS = 34
|
||||
TEST_TRANSFORMATION_ZOOM_CACHE_HASH = 'ac7a864de6a95889d5892301e142f8cdc5808f55010c0b820ed056902fc25a73'
|
||||
TEST_TRANSFORMATION_ZOOM_PERCENT = 49
|
||||
|
||||
@@ -10,17 +10,19 @@ from ..transformations import (
|
||||
TransformationRotate, TransformationZoom
|
||||
)
|
||||
|
||||
TRANSFORMATION_RESIZE_WIDTH = 123
|
||||
TRANSFORMATION_RESIZE_HEIGHT = 528
|
||||
TRANSFORMATION_RESIZE_CACHE_HASH = '348d60cb7c028c95'
|
||||
TRANSFORMATION_RESIZE_WIDTH_2 = 124
|
||||
TRANSFORMATION_RESIZE_HEIGHT_2 = 529
|
||||
TRANSFORMATION_RESIZE_CACHE_HASH_2 = '348d78cb5709c1bf'
|
||||
TRANSFORMATION_ROTATE_DEGRESS = 34
|
||||
TRANSFORMATION_ROTATE_CACHE_HASH = '45148f480ad5f8bd'
|
||||
TRANSFORMATION_COMBINED_CACHE_HASH = '1267dbe78a1759da'
|
||||
TRANSFORMATION_ZOOM_PERCENT = 49
|
||||
TRANSFORMATION_ZOOM_CACHE_HASH = '1b333603674469e0'
|
||||
from .literals import (
|
||||
TEST_TRANSFORMATION_COMBINED_CACHE_HASH,
|
||||
TEST_TRANSFORMATION_RESIZE_CACHE_HASH,
|
||||
TEST_TRANSFORMATION_RESIZE_CACHE_HASH_2,
|
||||
TEST_TRANSFORMATION_RESIZE_HEIGHT,
|
||||
TEST_TRANSFORMATION_RESIZE_HEIGHT_2,
|
||||
TEST_TRANSFORMATION_RESIZE_WIDTH,
|
||||
TEST_TRANSFORMATION_RESIZE_WIDTH_2,
|
||||
TEST_TRANSFORMATION_ROTATE_CACHE_HASH,
|
||||
TEST_TRANSFORMATION_ROTATE_DEGRESS,
|
||||
TEST_TRANSFORMATION_ZOOM_CACHE_HASH,
|
||||
TEST_TRANSFORMATION_ZOOM_PERCENT,
|
||||
)
|
||||
|
||||
|
||||
class TransformationBaseTestCase(TestCase):
|
||||
@@ -45,64 +47,65 @@ class TransformationBaseTestCase(TestCase):
|
||||
def test_resize_cache_hashing(self):
|
||||
# Test if the hash is being generated correctly
|
||||
transformation = TransformationResize(
|
||||
width=TRANSFORMATION_RESIZE_WIDTH,
|
||||
height=TRANSFORMATION_RESIZE_HEIGHT
|
||||
width=TEST_TRANSFORMATION_RESIZE_WIDTH,
|
||||
height=TEST_TRANSFORMATION_RESIZE_HEIGHT
|
||||
)
|
||||
|
||||
self.assertEqual(
|
||||
transformation.cache_hash(), TRANSFORMATION_RESIZE_CACHE_HASH
|
||||
transformation.cache_hash(), TEST_TRANSFORMATION_RESIZE_CACHE_HASH
|
||||
)
|
||||
|
||||
# Test if the hash is being alternated correctly
|
||||
transformation = TransformationResize(
|
||||
width=TRANSFORMATION_RESIZE_WIDTH_2,
|
||||
height=TRANSFORMATION_RESIZE_HEIGHT_2
|
||||
width=TEST_TRANSFORMATION_RESIZE_WIDTH_2,
|
||||
height=TEST_TRANSFORMATION_RESIZE_HEIGHT_2
|
||||
)
|
||||
|
||||
self.assertEqual(
|
||||
transformation.cache_hash(), TRANSFORMATION_RESIZE_CACHE_HASH_2
|
||||
transformation.cache_hash(),
|
||||
TEST_TRANSFORMATION_RESIZE_CACHE_HASH_2
|
||||
)
|
||||
|
||||
def test_rotate_cache_hashing(self):
|
||||
# Test if the hash is being generated correctly
|
||||
transformation = TransformationRotate(
|
||||
degrees=TRANSFORMATION_ROTATE_DEGRESS
|
||||
degrees=TEST_TRANSFORMATION_ROTATE_DEGRESS
|
||||
)
|
||||
|
||||
self.assertEqual(
|
||||
transformation.cache_hash(), TRANSFORMATION_ROTATE_CACHE_HASH
|
||||
transformation.cache_hash(), TEST_TRANSFORMATION_ROTATE_CACHE_HASH
|
||||
)
|
||||
|
||||
def test_rotate_zoom_hashing(self):
|
||||
# Test if the hash is being generated correctly
|
||||
transformation = TransformationZoom(
|
||||
percent=TRANSFORMATION_ZOOM_PERCENT
|
||||
percent=TEST_TRANSFORMATION_ZOOM_PERCENT
|
||||
)
|
||||
|
||||
self.assertEqual(
|
||||
transformation.cache_hash(), TRANSFORMATION_ZOOM_CACHE_HASH
|
||||
transformation.cache_hash(), TEST_TRANSFORMATION_ZOOM_CACHE_HASH
|
||||
)
|
||||
|
||||
def test_cache_hash_combining(self):
|
||||
# Test magic method and hash combining
|
||||
|
||||
transformation_resize = TransformationResize(
|
||||
width=TRANSFORMATION_RESIZE_WIDTH,
|
||||
height=TRANSFORMATION_RESIZE_HEIGHT
|
||||
width=TEST_TRANSFORMATION_RESIZE_WIDTH,
|
||||
height=TEST_TRANSFORMATION_RESIZE_HEIGHT
|
||||
)
|
||||
|
||||
transformation_rotate = TransformationRotate(
|
||||
degrees=TRANSFORMATION_ROTATE_DEGRESS
|
||||
degrees=TEST_TRANSFORMATION_ROTATE_DEGRESS
|
||||
)
|
||||
|
||||
transformation_zoom = TransformationZoom(
|
||||
percent=TRANSFORMATION_ZOOM_PERCENT
|
||||
percent=TEST_TRANSFORMATION_ZOOM_PERCENT
|
||||
)
|
||||
|
||||
self.assertEqual(
|
||||
BaseTransformation.combine(
|
||||
(transformation_rotate, transformation_resize, transformation_zoom)
|
||||
), TRANSFORMATION_COMBINED_CACHE_HASH
|
||||
), TEST_TRANSFORMATION_COMBINED_CACHE_HASH
|
||||
)
|
||||
|
||||
|
||||
|
||||
@@ -1,11 +1,12 @@
|
||||
from __future__ import unicode_literals
|
||||
|
||||
import hashlib
|
||||
import logging
|
||||
|
||||
from PIL import Image, ImageColor, ImageFilter
|
||||
|
||||
from django.utils.six import text_type
|
||||
from django.utils.translation import string_concat, ugettext_lazy as _
|
||||
from django.utils.encoding import force_text
|
||||
|
||||
logger = logging.getLogger(__name__)
|
||||
|
||||
@@ -19,25 +20,17 @@ class BaseTransformation(object):
|
||||
name = 'base_transformation'
|
||||
_registry = {}
|
||||
|
||||
@staticmethod
|
||||
def encode_hash(decoded_value):
|
||||
return hex(abs(decoded_value))[2:]
|
||||
|
||||
@staticmethod
|
||||
def decode_hash(encoded_value):
|
||||
return int(encoded_value, 16)
|
||||
|
||||
@staticmethod
|
||||
def combine(transformations):
|
||||
result = None
|
||||
|
||||
for index, transformation in enumerate(transformations):
|
||||
for transformation in transformations:
|
||||
if not result:
|
||||
result = hash((BaseTransformation.decode_hash(transformation.cache_hash()), index))
|
||||
result = hashlib.sha256(transformation.cache_hash())
|
||||
else:
|
||||
result ^= hash((BaseTransformation.decode_hash(transformation.cache_hash()), index))
|
||||
result.update(transformation.cache_hash())
|
||||
|
||||
return BaseTransformation.encode_hash(result)
|
||||
return result.hexdigest()
|
||||
|
||||
@classmethod
|
||||
def register(cls, transformation):
|
||||
@@ -69,11 +62,14 @@ class BaseTransformation(object):
|
||||
self.kwargs[argument_name] = kwargs.get(argument_name)
|
||||
|
||||
def cache_hash(self):
|
||||
result = text_type.__hash__(self.name)
|
||||
for index, (key, value) in enumerate(self.kwargs.items()):
|
||||
result ^= hash((key, index)) ^ hash((value, index))
|
||||
result = hashlib.sha256(self.name)
|
||||
|
||||
return BaseTransformation.encode_hash(result)
|
||||
# Sort arguments for guaranteed repeatability
|
||||
for key, value in sorted(self.kwargs.items()):
|
||||
result.update(force_text(key))
|
||||
result.update(force_text(value))
|
||||
|
||||
return result.hexdigest()
|
||||
|
||||
def execute_on(self, image):
|
||||
self.image = image
|
||||
|
||||
Reference in New Issue
Block a user