From f8241a8eb37c7a88ec25e950a0ccad3a5598b3a1 Mon Sep 17 00:00:00 2001
From: rristow
Date: Tue, 18 Feb 2014 11:13:09 +0100
Subject: [PATCH 01/37] Avoid browser cache (Return code 304 Not Modified)
---
src/plone/app/imagecropping/browser/editor.py | 4 +++-
1 file changed, 3 insertions(+), 1 deletion(-)
diff --git a/src/plone/app/imagecropping/browser/editor.py b/src/plone/app/imagecropping/browser/editor.py
index 7ce71389..8eeaeabd 100644
--- a/src/plone/app/imagecropping/browser/editor.py
+++ b/src/plone/app/imagecropping/browser/editor.py
@@ -1,4 +1,5 @@
# -*- coding: utf-8 -*-
+from DateTime.DateTime import DateTime
from Products.ATContentTypes.interfaces.interfaces import IATContentType
from Products.Five.browser import BrowserView
from Products.Five.browser.pagetemplatefile import ViewPageTemplateFile
@@ -12,7 +13,6 @@
from zope.component._api import getUtility
import json
-
JS_MESSAGES = """\
if(typeof(imagecropping) != "undefined") {
imagecropping.i18n_message_ids = {
@@ -157,6 +157,8 @@ def __call__(self):
x2 = int(round(float(self.request.form.get('x2'))))
y2 = int(round(float(self.request.form.get('y2'))))
scale_name = self.request.form.get('scalename')
+ # Avoid browser cache
+ self.context.setModificationDate(DateTime())
cropping_util._crop(fieldname=self.fieldname,
scale=scale_name,
box=(x1, y1, x2, y2),
From 15d680e9c2fe240a4008f3546c89d6121d5c204d Mon Sep 17 00:00:00 2001
From: Tom Gross
Date: Wed, 19 Feb 2014 21:24:06 +0100
Subject: [PATCH 02/37] simplified code a little bit
---
src/plone/app/imagecropping/browser/editor.py | 7 ++++---
1 file changed, 4 insertions(+), 3 deletions(-)
diff --git a/src/plone/app/imagecropping/browser/editor.py b/src/plone/app/imagecropping/browser/editor.py
index 8eeaeabd..a5d9c9b5 100644
--- a/src/plone/app/imagecropping/browser/editor.py
+++ b/src/plone/app/imagecropping/browser/editor.py
@@ -1,5 +1,4 @@
# -*- coding: utf-8 -*-
-from DateTime.DateTime import DateTime
from Products.ATContentTypes.interfaces.interfaces import IATContentType
from Products.Five.browser import BrowserView
from Products.Five.browser.pagetemplatefile import ViewPageTemplateFile
@@ -157,12 +156,14 @@ def __call__(self):
x2 = int(round(float(self.request.form.get('x2'))))
y2 = int(round(float(self.request.form.get('y2'))))
scale_name = self.request.form.get('scalename')
- # Avoid browser cache
- self.context.setModificationDate(DateTime())
cropping_util._crop(fieldname=self.fieldname,
scale=scale_name,
box=(x1, y1, x2, y2),
interface=self.interface)
+ # Avoid browser cache
+ # an empty call of setModificationDate uses current timestamp
+ self.context.setModificationDate()
+ self.context.reindexObject()
IStatusMessage(self.request).add(
_(u"Successfully saved cropped area"))
From f7a02373e659a497a873e8b78840a1ffec6b9c75 Mon Sep 17 00:00:00 2001
From: Tom Gross
Date: Wed, 19 Feb 2014 21:32:37 +0100
Subject: [PATCH 03/37] factored out cropping for better testability
---
src/plone/app/imagecropping/browser/editor.py | 37 ++++++++++---------
1 file changed, 20 insertions(+), 17 deletions(-)
diff --git a/src/plone/app/imagecropping/browser/editor.py b/src/plone/app/imagecropping/browser/editor.py
index a5d9c9b5..83cd4b9a 100644
--- a/src/plone/app/imagecropping/browser/editor.py
+++ b/src/plone/app/imagecropping/browser/editor.py
@@ -142,28 +142,31 @@ def image_url(self, fieldname="image"):
height=int(self.default_editor_size[1]))
return scaled_img and scaled_img.url or ''
- def __call__(self):
- form = self.request.form
+ def _crop(self):
+ coordinate = lambda x: int(round(float(self.request.form.get(x))))
+ x1 = coordinate('x1')
+ y1 = coordinate('y1')
+ x2 = coordinate('x2')
+ y2 = coordinate('y2')
+ scale_name = self.request.form.get('scalename')
cropping_util = self.context.restrictedTraverse('@@crop-image')
+ cropping_util._crop(fieldname=self.fieldname,
+ scale=scale_name,
+ box=(x1, y1, x2, y2),
+ interface=self.interface)
+ # Avoid browser cache
+ # an empty call of setModificationDate uses current timestamp
+ self.context.setModificationDate()
+ self.context.reindexObject()
+ def __call__(self):
+ form = self.request.form
if form.get('form.button.Delete', None) is not None:
- cropping_util._remove(self.fieldname,
- self.request.form.get('scalename'))
+ cropping_util = self.context.restrictedTraverse('@@crop-image')
+ cropping_util._remove(self.fieldname, form.get('scalename'))
IStatusMessage(self.request).add(_(u"Cropping area deleted"))
if form.get('form.button.Save', None) is not None:
- x1 = int(round(float(self.request.form.get('x1'))))
- y1 = int(round(float(self.request.form.get('y1'))))
- x2 = int(round(float(self.request.form.get('x2'))))
- y2 = int(round(float(self.request.form.get('y2'))))
- scale_name = self.request.form.get('scalename')
- cropping_util._crop(fieldname=self.fieldname,
- scale=scale_name,
- box=(x1, y1, x2, y2),
- interface=self.interface)
- # Avoid browser cache
- # an empty call of setModificationDate uses current timestamp
- self.context.setModificationDate()
- self.context.reindexObject()
+ self._crop()
IStatusMessage(self.request).add(
_(u"Successfully saved cropped area"))
From 49ee3050789548165d98b9f5af85cdeb169f924e Mon Sep 17 00:00:00 2001
From: Tom Gross
Date: Thu, 20 Feb 2014 05:44:08 +0100
Subject: [PATCH 04/37] use Plone 4.3 for default buildout
---
buildout.cfg | 6 ++----
travis.cfg | 11 +++++------
2 files changed, 7 insertions(+), 10 deletions(-)
diff --git a/buildout.cfg b/buildout.cfg
index 8b186510..bc71374c 100644
--- a/buildout.cfg
+++ b/buildout.cfg
@@ -1,12 +1,10 @@
[buildout]
extends =
- https://raw.github.com/collective/buildout.plonetest/master/test-4.2.x.cfg
+ https://raw.github.com/collective/buildout.plonetest/master/test-4.3.x.cfg
package-name = plone.app.imagecropping
package-extras = [test]
-#index = http://c.pypi.python.org
-
parts +=
omelette
i18ndude
@@ -54,4 +52,4 @@ input = inline:
mode = 755
[versions]
-plone.app.collection = 2.0b5
+plone.app.contenttypes = 1.0
diff --git a/travis.cfg b/travis.cfg
index bbb27a60..d16dc14f 100644
--- a/travis.cfg
+++ b/travis.cfg
@@ -10,10 +10,9 @@ allow-hosts +=
code.google.com
robotframework.googlecode.com
-[versions]
-plone.app.collection = 2.0b5
-plone.app.testing = >=4.2.2
-docutils = >=0.8.1
-plone.namedfile = >=2.0
-plone.dexterity = >=2.0
+#[versions]
+#plone.app.testing = >=4.2.2
+#docutils = >=0.8.1
+#plone.namedfile = >=2.0
+#plone.dexterity = >=2.0
From 24c8e3aec9951b464f90c0a0dac953e8dd0a17c6 Mon Sep 17 00:00:00 2001
From: Tom Gross
Date: Thu, 20 Feb 2014 05:45:00 +0100
Subject: [PATCH 05/37] started test for crop-view
---
src/plone/app/imagecropping/tests/test_editor.py | 16 +++++++++++-----
1 file changed, 11 insertions(+), 5 deletions(-)
diff --git a/src/plone/app/imagecropping/tests/test_editor.py b/src/plone/app/imagecropping/tests/test_editor.py
index e3a0ebbb..4917e819 100644
--- a/src/plone/app/imagecropping/tests/test_editor.py
+++ b/src/plone/app/imagecropping/tests/test_editor.py
@@ -5,7 +5,6 @@
from plone.app.testing import TEST_USER_NAME
from plone.app.testing import TEST_USER_PASSWORD
from plone.testing.z2 import Browser
-from Products.CMFPlone.utils import _createObjectByType
import transaction
import unittest2 as unittest
@@ -24,21 +23,22 @@ def setUp(self):
self.browser.handleErrors = False
self.browser.addHeader('Authorization', 'Basic %s:%s' % (
TEST_USER_NAME, TEST_USER_PASSWORD,))
+ self.createSingleImageType()
def createSingleImageType(self):
# create test image as testuser
- _createObjectByType('Image', self.portal, 'testimage',
- title=u"I'm a testing Image")
+ self.portal.invokeFactory('Image', 'testimage',
+ title=u"I'm a testing Image")
+ self.img = self.portal['testimage']
+ self.img.reindexObject()
transaction.commit()
- self.img = self.portal.testimage
f = file(join(dirname(tests.__file__), 'plone-logo.png'))
self.img.setImage(f)
f.close()
def test_singleimage_editorview(self):
""" """
- self.createSingleImageType()
# is there the cropping action tab
self.browser.open("%s/view" % self.img.absolute_url())
self.assertIn("Cropping", self.browser.contents)
@@ -56,5 +56,11 @@ def test_singleimage_editorview(self):
self.assertIn(u"Save cropping information", self.browser.contents)
self.assertIn(u"Remove cropping information", self.browser.contents)
+ def test_editview_crop(self):
+ request = self.layer['request']
+ request.form.update({'x1': 1.0, 'y1': 2.7, 'x2': 10.6, 'y2': 8.4})
+ cropview = self.img.restrictedTraverse('@@croppingeditor')
+ cropview._crop()
+
def tearDown(self):
self.portal.manage_delObjects(['testimage', ])
From ab47688609a808090e339a5707325ed1c8c7998e Mon Sep 17 00:00:00 2001
From: Tom Gross
Date: Wed, 26 Feb 2014 22:32:05 +0100
Subject: [PATCH 06/37] override scaling view to keep crops on metadata change
---
buildout.cfg | 3 +++
.../app/imagecropping/browser/configure.zcml | 9 ++++++++
src/plone/app/imagecropping/browser/crop.py | 3 +--
src/plone/app/imagecropping/browser/editor.py | 4 ----
.../app/imagecropping/browser/scaling.py | 17 +++++++++++++++
src/plone/app/imagecropping/interfaces.py | 2 +-
.../app/imagecropping/tests/test_cropping.py | 21 +++++++++++++++++++
.../app/imagecropping/tests/test_editor.py | 3 ++-
src/plone/app/imagecropping/utils.py | 10 +++++++--
9 files changed, 62 insertions(+), 10 deletions(-)
create mode 100644 src/plone/app/imagecropping/browser/scaling.py
diff --git a/buildout.cfg b/buildout.cfg
index bc71374c..2cb1449b 100644
--- a/buildout.cfg
+++ b/buildout.cfg
@@ -24,6 +24,9 @@ test-eggs +=
versions = versions
+[versions]
+Pillow = 2.3.0
+
[omelette]
recipe = collective.recipe.omelette
eggs = ${instance:eggs} ${buildout:test-eggs}
diff --git a/src/plone/app/imagecropping/browser/configure.zcml b/src/plone/app/imagecropping/browser/configure.zcml
index e910f9d7..80418eb3 100644
--- a/src/plone/app/imagecropping/browser/configure.zcml
+++ b/src/plone/app/imagecropping/browser/configure.zcml
@@ -2,6 +2,7 @@
xmlns="http://namespaces.zope.org/zope"
xmlns:browser="http://namespaces.zope.org/browser"
xmlns:i18n="http://xml.zope.org/namespaces/i18n"
+ xmlns:zcml="http://namespaces.zope.org/zcml"
i18n_domain="plone">
@@ -43,4 +44,12 @@
permission="cmf.ModifyPortalContent"
/>
+
+
diff --git a/src/plone/app/imagecropping/browser/crop.py b/src/plone/app/imagecropping/browser/crop.py
index b18e61ac..ec77c013 100644
--- a/src/plone/app/imagecropping/browser/crop.py
+++ b/src/plone/app/imagecropping/browser/crop.py
@@ -25,7 +25,6 @@ def _crop(self, fieldname, scale, box, interface=None):
"""switch between dexterity and Archetypes
"""
croputils = IImageCroppingUtils(self.context)
- field = croputils.get_image_field(fieldname)
data = croputils.get_image_data(fieldname)
original_file = StringIO(data)
@@ -38,7 +37,7 @@ def _crop(self, fieldname, scale, box, interface=None):
cropped_image_file.seek(0)
croputils.save_cropped(
- fieldname, field, scale, cropped_image_file, interface)
+ fieldname, scale, cropped_image_file, interface)
# store crop information in annotations
self._store(fieldname, scale, box)
diff --git a/src/plone/app/imagecropping/browser/editor.py b/src/plone/app/imagecropping/browser/editor.py
index 83cd4b9a..31406097 100644
--- a/src/plone/app/imagecropping/browser/editor.py
+++ b/src/plone/app/imagecropping/browser/editor.py
@@ -154,10 +154,6 @@ def _crop(self):
scale=scale_name,
box=(x1, y1, x2, y2),
interface=self.interface)
- # Avoid browser cache
- # an empty call of setModificationDate uses current timestamp
- self.context.setModificationDate()
- self.context.reindexObject()
def __call__(self):
form = self.request.form
diff --git a/src/plone/app/imagecropping/browser/scaling.py b/src/plone/app/imagecropping/browser/scaling.py
new file mode 100644
index 00000000..46132f98
--- /dev/null
+++ b/src/plone/app/imagecropping/browser/scaling.py
@@ -0,0 +1,17 @@
+from zope.annotation.interfaces import IAnnotations
+
+from plone.app.imagecropping import PAI_STORAGE_KEY
+from plone.app.imaging.scaling import ImageScaling as BaseImageScaling
+
+
+class ImageScaling(BaseImageScaling):
+
+ def modified(self):
+ cropped = IAnnotations(self.context).get(PAI_STORAGE_KEY)
+ if not cropped:
+ return super(ImageScaling, self).modified()
+ else:
+ return 1
+
+
+# XXX need this for plone.namedfile and NEWSItem too
diff --git a/src/plone/app/imagecropping/interfaces.py b/src/plone/app/imagecropping/interfaces.py
index 9b22f993..8882a0d7 100644
--- a/src/plone/app/imagecropping/interfaces.py
+++ b/src/plone/app/imagecropping/interfaces.py
@@ -30,7 +30,7 @@ def get_image_size(fieldname, interface):
(100, 200)
"""
- def save_cropped(fieldname, field, scale, image_file, interface=None):
+ def save_cropped(fieldname, scale, image_file, interface=None):
""" Save the cropped iamge under the name of the selected scale in
plone.scale.storage.AnnotationStorage, so that it is available
in plone.app.imaging @@images view
diff --git a/src/plone/app/imagecropping/tests/test_cropping.py b/src/plone/app/imagecropping/tests/test_cropping.py
index 36dfc731..bd019ae8 100644
--- a/src/plone/app/imagecropping/tests/test_cropping.py
+++ b/src/plone/app/imagecropping/tests/test_cropping.py
@@ -117,3 +117,24 @@ def test_image_formats(self):
# XXX: fixme
# self.assertEqual(open(croppedData).format, 'JPEG',
# "cropped scale does not have same format as the original")
+
+ def test_modify_context(self):
+ """ See https://github.com/collective/plone.app.imagecropping/issues/21
+ """
+
+ view = self.img.restrictedTraverse('@@crop-image')
+ traverse = self.portal.REQUEST.traverseName
+ scales = traverse(self.img, '@@images')
+ unscaled_thumb = scales.scale('image', 'thumb')
+
+ # store cropped version for thumb and check if the result
+ # is a square now
+ view._crop(fieldname='image', scale='thumb', box=(14, 14, 218, 218))
+ thumb = scales.scale('image', 'thumb')
+ self.failIfEqual(thumb.data, unscaled_thumb.data)
+
+ self.img.setTitle('A new title')
+ self.img.reindexObject()
+
+ thumb2 = scales.scale('image', 'thumb')
+ self.assertEqual(thumb.data, thumb2.data)
diff --git a/src/plone/app/imagecropping/tests/test_editor.py b/src/plone/app/imagecropping/tests/test_editor.py
index 4917e819..4c439014 100644
--- a/src/plone/app/imagecropping/tests/test_editor.py
+++ b/src/plone/app/imagecropping/tests/test_editor.py
@@ -58,7 +58,8 @@ def test_singleimage_editorview(self):
def test_editview_crop(self):
request = self.layer['request']
- request.form.update({'x1': 1.0, 'y1': 2.7, 'x2': 10.6, 'y2': 8.4})
+ request.form.update({'x1': 1.0, 'y1': 2.7, 'x2': 10.6, 'y2': 8.4,
+ 'scalename': 'mini'})
cropview = self.img.restrictedTraverse('@@croppingeditor')
cropview._crop()
diff --git a/src/plone/app/imagecropping/utils.py b/src/plone/app/imagecropping/utils.py
index bd812913..203acbd2 100644
--- a/src/plone/app/imagecropping/utils.py
+++ b/src/plone/app/imagecropping/utils.py
@@ -82,9 +82,10 @@ def get_image_size(self, fieldname, interface=None):
return image_size
def save_cropped(
- self, fieldname, field, scale, image_file, interface=None):
+ self, fieldname, scale, image_file, interface=None):
""" see interface
"""
+ field = self.get_image_field(fieldname)
handler = IImageScaleHandler(field)
sizes = field.getAvailableSizes(self.context)
w, h = sizes[scale]
@@ -104,6 +105,10 @@ def crop_factory(fieldname, direction='keep', **parameters):
result.close()
return blob, image_format, dimensions
+ # Avoid browser cache
+ # calling reindexObject updates the modified metadate too
+ self.context.reindexObject()
+
# call storage with actual time in milliseconds
# this always invalidates old scales
storage = AnnotationStorage(self.context, self.now_millis)
@@ -162,7 +167,7 @@ def get_image_size(self, fieldname, interface=None):
return image_size
def save_cropped(
- self, fieldname, field, scale, image_file, interface=None):
+ self, fieldname, scale, image_file, interface=None):
""" see interface
"""
sizes = getAllowedSizes()
@@ -173,6 +178,7 @@ def crop_factory(fieldname, **parameters):
if result is not None:
data, format, dimensions = result
mimetype = 'image/%s' % format.lower()
+ field = self.get_image_field(fieldname)
value = field.__class__(
data,
contentType=mimetype,
From 362674ff33c9fb15bf258cd7c4fa37926ef5c237 Mon Sep 17 00:00:00 2001
From: Tom Gross
Date: Wed, 5 Mar 2014 22:15:15 +0100
Subject: [PATCH 07/37] implement scaling for plone.namedfile
---
buildout.cfg | 1 +
.../app/imagecropping/browser/configure.zcml | 16 ++++++
.../app/imagecropping/browser/scaling.py | 54 +++++++++++++++++--
3 files changed, 68 insertions(+), 3 deletions(-)
diff --git a/buildout.cfg b/buildout.cfg
index 2cb1449b..b7145713 100644
--- a/buildout.cfg
+++ b/buildout.cfg
@@ -26,6 +26,7 @@ versions = versions
[versions]
Pillow = 2.3.0
+selenium = 2.40.0
[omelette]
recipe = collective.recipe.omelette
diff --git a/src/plone/app/imagecropping/browser/configure.zcml b/src/plone/app/imagecropping/browser/configure.zcml
index 80418eb3..bc3d5042 100644
--- a/src/plone/app/imagecropping/browser/configure.zcml
+++ b/src/plone/app/imagecropping/browser/configure.zcml
@@ -52,4 +52,20 @@
allowed_interface="plone.app.imaging.interfaces.IImageScaling"
permission="zope2.View" />
+
+
+
+
diff --git a/src/plone/app/imagecropping/browser/scaling.py b/src/plone/app/imagecropping/browser/scaling.py
index 46132f98..6107e876 100644
--- a/src/plone/app/imagecropping/browser/scaling.py
+++ b/src/plone/app/imagecropping/browser/scaling.py
@@ -6,12 +6,60 @@
class ImageScaling(BaseImageScaling):
+ _rescale = True
+
def modified(self):
- cropped = IAnnotations(self.context).get(PAI_STORAGE_KEY)
- if not cropped:
+ if self._rescale:
return super(ImageScaling, self).modified()
else:
return 1
+
+ def scale(self,
+ fieldname=None,
+ scale=None,
+ height=None,
+ width=None,
+ **parameters):
+ cropped = IAnnotations(self.context).get(PAI_STORAGE_KEY)
+ if '%s_%s' % (fieldname, scale) in cropped:
+ self._rescale = False
+ else:
+ self._rescale = True
+ return super(ImageScaling, self).scale(fieldname, scale, height, width, **parameters)
+
+
+try:
+ from plone.namedfile.scaling import ImageScaling as NFImageScaling
+
+ from plone.namedfile.interfaces import IImageScaleTraversable
+ from plone.app.imagecropping.interfaces import IImageCropping
+
+ class IImageCroppingScale(IImageScaleTraversable, IImageCropping):
+ pass
+
+ class NamedfileImageScaling(NFImageScaling):
+
+ _rescale = True
+
+ def modified(self):
+ if self._rescale:
+ return super(ImageScaling, self).modified()
+ else:
+ return 1
+ def scale(self,
+ fieldname=None,
+ scale=None,
+ height=None,
+ width=None,
+ direction='thumbnail',
+ **parameters):
+ cropped = IAnnotations(self.context).get(PAI_STORAGE_KEY)
+ if '%s_%s' % (fieldname, scale) in cropped:
+ self._rescale = False
+ else:
+ self._rescale = True
+ return super(ImageScaling, self).scale(fieldname, scale, height, width, direction, **parameters)
-# XXX need this for plone.namedfile and NEWSItem too
+except ImportError:
+ pass
From ea7dc0b9082167feefd2c571125c74d230145df1 Mon Sep 17 00:00:00 2001
From: tomgross
Date: Mon, 10 Mar 2014 21:18:22 +0100
Subject: [PATCH 08/37] Remove commented out version pins
---
travis.cfg | 7 -------
1 file changed, 7 deletions(-)
diff --git a/travis.cfg b/travis.cfg
index d16dc14f..4547045a 100644
--- a/travis.cfg
+++ b/travis.cfg
@@ -9,10 +9,3 @@ package-extras = [test]
allow-hosts +=
code.google.com
robotframework.googlecode.com
-
-#[versions]
-#plone.app.testing = >=4.2.2
-#docutils = >=0.8.1
-#plone.namedfile = >=2.0
-#plone.dexterity = >=2.0
-
From 300a3c62ea55ff70417e2da94a2055b738151b35 Mon Sep 17 00:00:00 2001
From: Tom Gross
Date: Tue, 11 Mar 2014 22:05:45 +0100
Subject: [PATCH 09/37] fixed case where cropping annotation is none
---
src/plone/app/imagecropping/browser/scaling.py | 9 +++++----
1 file changed, 5 insertions(+), 4 deletions(-)
diff --git a/src/plone/app/imagecropping/browser/scaling.py b/src/plone/app/imagecropping/browser/scaling.py
index 6107e876..79e68ef9 100644
--- a/src/plone/app/imagecropping/browser/scaling.py
+++ b/src/plone/app/imagecropping/browser/scaling.py
@@ -21,7 +21,7 @@ def scale(self,
width=None,
**parameters):
cropped = IAnnotations(self.context).get(PAI_STORAGE_KEY)
- if '%s_%s' % (fieldname, scale) in cropped:
+ if cropped and '%s_%s' % (fieldname, scale) in cropped:
self._rescale = False
else:
self._rescale = True
@@ -43,7 +43,7 @@ class NamedfileImageScaling(NFImageScaling):
def modified(self):
if self._rescale:
- return super(ImageScaling, self).modified()
+ return super(NamedfileImageScaling, self).modified()
else:
return 1
@@ -55,11 +55,12 @@ def scale(self,
direction='thumbnail',
**parameters):
cropped = IAnnotations(self.context).get(PAI_STORAGE_KEY)
- if '%s_%s' % (fieldname, scale) in cropped:
+ if cropped and '%s_%s' % (fieldname, scale) in cropped:
self._rescale = False
else:
self._rescale = True
- return super(ImageScaling, self).scale(fieldname, scale, height, width, direction, **parameters)
+ return super(NamedfileImageScaling, self).scale(
+ fieldname, scale, height, width, direction, **parameters)
except ImportError:
pass
From 1cbe543a0d2418a223ab562875a3141d4b96a41b Mon Sep 17 00:00:00 2001
From: Tom Gross
Date: Tue, 11 Mar 2014 22:24:30 +0100
Subject: [PATCH 10/37] we depend on plone.namedfile >= 2.0.1
---
test-4.2.cfg | 3 +++
1 file changed, 3 insertions(+)
diff --git a/test-4.2.cfg b/test-4.2.cfg
index 9dc5a085..61c06f6c 100644
--- a/test-4.2.cfg
+++ b/test-4.2.cfg
@@ -2,3 +2,6 @@
extends = https://raw.github.com/collective/buildout.plonetest/master/test-4.2.x.cfg
package-name = plone.app.imagecropping
package-extras = [test]
+
+[versions]
+plone.namedfile = 2.0.1
From f36fcaad7b75ab9aeb6353d9b1a1a420137ad258 Mon Sep 17 00:00:00 2001
From: Tom Gross
Date: Tue, 11 Mar 2014 22:47:59 +0100
Subject: [PATCH 11/37] document changes
---
CHANGES.txt | 5 ++++-
1 file changed, 4 insertions(+), 1 deletion(-)
diff --git a/CHANGES.txt b/CHANGES.txt
index 87ba8470..7220ac80 100644
--- a/CHANGES.txt
+++ b/CHANGES.txt
@@ -5,7 +5,7 @@ Changelog
-------------------
- Check for plone.namedfile not Dexterity. It can be used seperately
- [tom_gross]
+ [tomgross]
- Rename ``imagecropping_keywords.txt`` to ``keywords.robot`` to allow simple
reusage in ``plone.app.robotframework``.
@@ -20,6 +20,9 @@ Changelog
- Prevent fieldname loosing for for current field
[bogdangi]
+- Fixed #21 (cropping was reset on modifying image)
+ [tomgross]
+
0.1rc2 (2013-05-03)
-------------------
From 204339d2771635d17d1ed29ce42125980c020763 Mon Sep 17 00:00:00 2001
From: Tom Gross
Date: Wed, 12 Mar 2014 07:21:07 +0100
Subject: [PATCH 12/37] adjust schema of test content so tests pass on 4.2 and
4.3
---
.../types/dexterity_content_type_with_two_image_fields.xml | 1 -
1 file changed, 1 deletion(-)
diff --git a/src/plone/app/imagecropping/profiles/testing/types/dexterity_content_type_with_two_image_fields.xml b/src/plone/app/imagecropping/profiles/testing/types/dexterity_content_type_with_two_image_fields.xml
index a819cd45..cbac35a0 100644
--- a/src/plone/app/imagecropping/profiles/testing/types/dexterity_content_type_with_two_image_fields.xml
+++ b/src/plone/app/imagecropping/profiles/testing/types/dexterity_content_type_with_two_image_fields.xml
@@ -42,7 +42,6 @@
</schema>
</model>
- dexterity
From 1588cd7a902d4f8a433eefb4e38dc9db3484ad07 Mon Sep 17 00:00:00 2001
From: Tom Gross
Date: Wed, 12 Mar 2014 07:22:04 +0100
Subject: [PATCH 13/37] use latest seleium
---
test-4.2.cfg | 1 +
test-4.3.cfg | 3 +++
2 files changed, 4 insertions(+)
diff --git a/test-4.2.cfg b/test-4.2.cfg
index 61c06f6c..67bde107 100644
--- a/test-4.2.cfg
+++ b/test-4.2.cfg
@@ -5,3 +5,4 @@ package-extras = [test]
[versions]
plone.namedfile = 2.0.1
+selenium = 2.40.0
diff --git a/test-4.3.cfg b/test-4.3.cfg
index a67d3d88..f8a8d299 100644
--- a/test-4.3.cfg
+++ b/test-4.3.cfg
@@ -2,3 +2,6 @@
extends = https://raw.github.com/collective/buildout.plonetest/master/test-4.3.x.cfg
package-name = plone.app.imagecropping
package-extras = [test]
+
+[versions]
+selenium = 2.40.0
From 791f64a1502bedda2a81339da82dcae6a059e601 Mon Sep 17 00:00:00 2001
From: Tom Gross
Date: Wed, 12 Mar 2014 07:35:13 +0100
Subject: [PATCH 14/37] specify version pinned egg plone.namedfile as test
dependency
---
setup.py | 1 +
1 file changed, 1 insertion(+)
diff --git a/setup.py b/setup.py
index ab4fe40a..382750a0 100644
--- a/setup.py
+++ b/setup.py
@@ -56,6 +56,7 @@
'test': [
'plone.app.testing[robot]>=4.2.2',
'plone.app.dexterity',
+ 'plone.namedfile>=2.0.1'
],
},
entry_points="""
From f44cce0d683b3dbf7d66061144b6ef9712ed4705 Mon Sep 17 00:00:00 2001
From: Tom Gross
Date: Thu, 13 Mar 2014 20:15:12 +0100
Subject: [PATCH 15/37] added test for plone 5.0
---
.travis.yml | 16 ++++------------
travis.cfg => test-5.0.cfg | 10 +++-------
2 files changed, 7 insertions(+), 19 deletions(-)
rename travis.cfg => test-5.0.cfg (51%)
diff --git a/.travis.yml b/.travis.yml
index 25238db9..9742c434 100644
--- a/.travis.yml
+++ b/.travis.yml
@@ -3,21 +3,13 @@ python: 2.7
env:
- PLONE_VERSION=4.2
- PLONE_VERSION=4.3
-matrix:
- include:
- - python: 2.6
- env: PLONE_VERSION=4.1
- allow_failures:
- - python: 2.6
- env: PLONE_VERSION=4.1
before_install:
- sudo apt-get install -y libjpeg-dev libgif-dev libpng-dev libz-dev
-install:
- - sed -ie "s#travis-4.x.cfg#travis-$PLONE_VERSION.x.cfg#" travis.cfg
- mkdir -p buildout-cache/downloads
- - python bootstrap.py -c travis.cfg
- - bin/buildout -c travis.cfg annotate
- - bin/buildout -c travis.cfg -N -q
+ - mkdir -p buildout-cache/eggs
+install:
+ - python bootstrap.py -c test-$PLONE_VERSION.cfg
+ - bin/buildout -t 5 -Nc test-$PLONE_VERSION.cfg
before_script:
- "export DISPLAY=:99.0"
- "sh -e /etc/init.d/xvfb start"
diff --git a/travis.cfg b/test-5.0.cfg
similarity index 51%
rename from travis.cfg
rename to test-5.0.cfg
index 4547045a..12248bbb 100644
--- a/travis.cfg
+++ b/test-5.0.cfg
@@ -1,11 +1,7 @@
[buildout]
-extends = https://raw.github.com/collective/buildout.plonetest/master/travis-4.x.cfg
-test-eggs =
- decorator
- selenium
+extends = https://raw.github.com/collective/buildout.plonetest/master/test-5.0.x.cfg
package-name = plone.app.imagecropping
package-extras = [test]
-allow-hosts +=
- code.google.com
- robotframework.googlecode.com
+[versions]
+selenium = 2.40.0
From c6f57c1e43e0145108abb1e8fad9fb3de7b7e6e9 Mon Sep 17 00:00:00 2001
From: Tom Gross
Date: Fri, 14 Mar 2014 06:38:29 +0100
Subject: [PATCH 16/37] buildout and egg hygiene
---
buildout.cfg | 5 ++---
setup.py | 15 ++++++++++-----
src/plone/app/imagecropping/__init__.py | 3 ---
src/plone/app/imagecropping/configure.zcml | 2 +-
4 files changed, 13 insertions(+), 12 deletions(-)
diff --git a/buildout.cfg b/buildout.cfg
index b7145713..d2e06f88 100644
--- a/buildout.cfg
+++ b/buildout.cfg
@@ -26,7 +26,8 @@ versions = versions
[versions]
Pillow = 2.3.0
-selenium = 2.40.0
+selenium = 2.40.0
+plone.app.contenttypes = 1.0
[omelette]
recipe = collective.recipe.omelette
@@ -55,5 +56,3 @@ input = inline:
cd -
mode = 755
-[versions]
-plone.app.contenttypes = 1.0
diff --git a/setup.py b/setup.py
index 382750a0..578eb00f 100644
--- a/setup.py
+++ b/setup.py
@@ -1,8 +1,17 @@
from setuptools import setup, find_packages
import os
+import pkg_resources
version = '0.1rc3.dev0'
+
+test_requires = [
+ 'plone.app.testing[robot]>=4.2.2',
+ ]
+
+if pkg_resources.get_distribution('Products.CMFPlone').version >= '4.2':
+ test_requires.append('plone.app.dexterity')
+
long_description = (
open('README.rst').read()
+ '\n' +
@@ -53,11 +62,7 @@
'Products.CMFPlone>=4.1'
],
extras_require={
- 'test': [
- 'plone.app.testing[robot]>=4.2.2',
- 'plone.app.dexterity',
- 'plone.namedfile>=2.0.1'
- ],
+ 'test': test_requires,
},
entry_points="""
# -*- Entry points: -*-
diff --git a/src/plone/app/imagecropping/__init__.py b/src/plone/app/imagecropping/__init__.py
index 098ed596..c245064e 100644
--- a/src/plone/app/imagecropping/__init__.py
+++ b/src/plone/app/imagecropping/__init__.py
@@ -14,6 +14,3 @@
imagecroppingMessageFactory = MessageFactory("plone.app.imagecropping")
PRODUCT_NAME = PAI_STORAGE_KEY = "plone.app.imagecropping"
-
-def initialize(context):
- """Initializer called when used as a Zope 2 product."""
diff --git a/src/plone/app/imagecropping/configure.zcml b/src/plone/app/imagecropping/configure.zcml
index 62241625..910d3df5 100644
--- a/src/plone/app/imagecropping/configure.zcml
+++ b/src/plone/app/imagecropping/configure.zcml
@@ -6,7 +6,7 @@
xmlns:zcml="http://namespaces.zope.org/zcml"
i18n_domain="plone.app.imagecropping">
-
+
Date: Fri, 14 Mar 2014 06:39:01 +0100
Subject: [PATCH 17/37] remove buildout config which is a duplicate of
buildout.cfg
---
instance-4.3.cfg | 60 ------------------------------------------------
1 file changed, 60 deletions(-)
delete mode 100644 instance-4.3.cfg
diff --git a/instance-4.3.cfg b/instance-4.3.cfg
deleted file mode 100644
index cfc15f45..00000000
--- a/instance-4.3.cfg
+++ /dev/null
@@ -1,60 +0,0 @@
-[buildout]
-extensions = mr.developer
-
-extends =
- https://raw.github.com/collective/buildout.plonetest/master/test-4.3.x.cfg
-
-package-name = plone.app.imagecropping
-package-extras = [test]
-
-#index = http://c.pypi.python.org
-
-parts +=
- omelette
- i18ndude
- rebuild_pot
-
-eggs +=
- plone.app.dexterity [grok]
- plone.app.contenttypes
- plone.reload
-
-test-eggs +=
- Products.ATContentTypes [test]
- plone.app.contenttypes [test]
- plone.app.dexterity [test]
-
-versions = versions
-
-[test]
-defaults = ['-s', '${buildout:package-name}', '--auto-color', '--auto-progress']
-
-[omelette]
-recipe = collective.recipe.omelette
-eggs = ${instance:eggs} ${buildout:test-eggs}
-
-[i18ndude]
-recipe = zc.recipe.egg
-eggs = i18ndude
-
-[rebuild_pot]
-recipe = collective.recipe.template
-output = ${buildout:directory}/bin/rebuild_pot
-input = inline:
- #!/bin/bash
- DOMAIN="plone.app.imagecropping"
- BASE_PATH=${buildout:directory}/src/plone/app/imagecropping
- touch $BASE_PATH/locales/$DOMAIN.pot
- ${buildout:directory}/bin/i18ndude rebuild-pot --pot $BASE_PATH/locales/$DOMAIN.pot --create $DOMAIN ${buildout:directory}/src/
-
- cd $BASE_PATH
- # sync all locales
- find locales -maxdepth 1 -mindepth 1 -type d \
- | grep -v .svn \
- | sed -e "s/locales\/\(.*\)$/\1/" \
- | xargs -I % ${buildout:directory}/bin/i18ndude sync --pot $BASE_PATH/locales/$DOMAIN.pot $BASE_PATH/locales/%/LC_MESSAGES/$DOMAIN.po
- cd -
-mode = 755
-
-[versions]
-plone.app.collection = 2.0b5
From 81bf404401718c95b047bf31b7d06ddf0733b0c0 Mon Sep 17 00:00:00 2001
From: Tom Gross
Date: Fri, 14 Mar 2014 07:48:37 +0100
Subject: [PATCH 18/37] don't depend on plone.namedfile >= 2.0.1
---
.travis.yml | 13 +++-
setup.py | 9 ++-
.../app/imagecropping/browser/scaling.py | 73 +++++++++++--------
test-4.2.cfg | 1 -
4 files changed, 61 insertions(+), 35 deletions(-)
diff --git a/.travis.yml b/.travis.yml
index 9742c434..d1439c50 100644
--- a/.travis.yml
+++ b/.travis.yml
@@ -1,8 +1,19 @@
language: python
-python: 2.7
+python:
+ - 2.6
+ - 2.7
env:
+ - PLONE_VERSION=4.1
- PLONE_VERSION=4.2
- PLONE_VERSION=4.3
+matrix:
+ exclude:
+ - python: 2.7
+ env: PLONE=4.1
+ - python: 2.6
+ env: PLONE=4.2
+ - python: 2.6
+ env: PLONE=4.3
before_install:
- sudo apt-get install -y libjpeg-dev libgif-dev libpng-dev libz-dev
- mkdir -p buildout-cache/downloads
diff --git a/setup.py b/setup.py
index 578eb00f..54af7a4d 100644
--- a/setup.py
+++ b/setup.py
@@ -1,16 +1,17 @@
from setuptools import setup, find_packages
import os
import pkg_resources
+from distutils.version import LooseVersion
-version = '0.1rc3.dev0'
-
+version = '1.0.dev0'
test_requires = [
'plone.app.testing[robot]>=4.2.2',
]
-if pkg_resources.get_distribution('Products.CMFPlone').version >= '4.2':
- test_requires.append('plone.app.dexterity')
+plone_version = pkg_resources.get_distribution('Products.CMFPlone').version
+if LooseVersion(plone_version) >= LooseVersion('4.2'):
+ test_requires.append('plone.app.contenttypes')
long_description = (
open('README.rst').read()
diff --git a/src/plone/app/imagecropping/browser/scaling.py b/src/plone/app/imagecropping/browser/scaling.py
index 79e68ef9..54e64748 100644
--- a/src/plone/app/imagecropping/browser/scaling.py
+++ b/src/plone/app/imagecropping/browser/scaling.py
@@ -3,8 +3,10 @@
from plone.app.imagecropping import PAI_STORAGE_KEY
from plone.app.imaging.scaling import ImageScaling as BaseImageScaling
+import pkg_resources
+from distutils.version import LooseVersion
-class ImageScaling(BaseImageScaling):
+class ScalingOverrides(object):
_rescale = True
@@ -13,54 +15,67 @@ def modified(self):
return super(ImageScaling, self).modified()
else:
return 1
-
+
+ def need_rescale(self, fieldname, scale):
+ cropped = IAnnotations(self.context).get(PAI_STORAGE_KEY)
+ if cropped and '%s_%s' % (fieldname, scale) in cropped:
+ self._rescale = False
+ else:
+ self._rescale = True
+
+
+
+class ImageScaling(ScalingOverrides, BaseImageScaling):
+
def scale(self,
fieldname=None,
scale=None,
height=None,
width=None,
**parameters):
- cropped = IAnnotations(self.context).get(PAI_STORAGE_KEY)
- if cropped and '%s_%s' % (fieldname, scale) in cropped:
- self._rescale = False
- else:
- self._rescale = True
+ self.need_rescale(fieldname, scale)
return super(ImageScaling, self).scale(fieldname, scale, height, width, **parameters)
-
try:
from plone.namedfile.scaling import ImageScaling as NFImageScaling
from plone.namedfile.interfaces import IImageScaleTraversable
from plone.app.imagecropping.interfaces import IImageCropping
+ plone_namedfile_version = pkg_resources.get_distribution('plone_namedfile').version
+
class IImageCroppingScale(IImageScaleTraversable, IImageCropping):
pass
- class NamedfileImageScaling(NFImageScaling):
-
- _rescale = True
+ class NamedfileImageScaling(ScalingOverrides, NFImageScaling):
+ """ Override plone.namedfile scaling view
- def modified(self):
- if self._rescale:
- return super(NamedfileImageScaling, self).modified()
- else:
- return 1
+ This view checks, if image crops are available and
+ prevents rescaling in this case.
+ """
- def scale(self,
- fieldname=None,
- scale=None,
- height=None,
- width=None,
+ if LooseVersion(plone_namedfile_version) >= LooseVersion('2.0.1'):
+ def scale(self,
+ fieldname=None,
+ scale=None,
+ height=None,
+ width=None,
direction='thumbnail',
- **parameters):
- cropped = IAnnotations(self.context).get(PAI_STORAGE_KEY)
- if cropped and '%s_%s' % (fieldname, scale) in cropped:
- self._rescale = False
- else:
- self._rescale = True
- return super(NamedfileImageScaling, self).scale(
- fieldname, scale, height, width, direction, **parameters)
+ **parameters):
+ self.need_rescale(fieldname, scale)
+ return super(NamedfileImageScaling, self).scale(
+ fieldname, scale, height, width, direction, **parameters)
+ else:
+ def scale(self,
+ fieldname=None,
+ scale=None,
+ height=None,
+ width=None,
+ **parameters):
+ self.need_rescale(fieldname, scale)
+ return super(NamedfileImageScaling, self).scale(
+ fieldname, scale, height, width, **parameters)
+
except ImportError:
pass
diff --git a/test-4.2.cfg b/test-4.2.cfg
index 67bde107..20555b64 100644
--- a/test-4.2.cfg
+++ b/test-4.2.cfg
@@ -4,5 +4,4 @@ package-name = plone.app.imagecropping
package-extras = [test]
[versions]
-plone.namedfile = 2.0.1
selenium = 2.40.0
From 64054d98e32be017d802432989937aba3586b9da Mon Sep 17 00:00:00 2001
From: Tom Gross
Date: Fri, 14 Mar 2014 08:09:11 +0100
Subject: [PATCH 19/37] fix test buildouts
---
setup.py | 15 ++++-----------
1 file changed, 4 insertions(+), 11 deletions(-)
diff --git a/setup.py b/setup.py
index 54af7a4d..c5be6625 100644
--- a/setup.py
+++ b/setup.py
@@ -5,14 +5,6 @@
version = '1.0.dev0'
-test_requires = [
- 'plone.app.testing[robot]>=4.2.2',
- ]
-
-plone_version = pkg_resources.get_distribution('Products.CMFPlone').version
-if LooseVersion(plone_version) >= LooseVersion('4.2'):
- test_requires.append('plone.app.contenttypes')
-
long_description = (
open('README.rst').read()
+ '\n' +
@@ -33,7 +25,6 @@
"Development Status :: 5 - Production/Stable",
"Environment :: Web Environment",
"Framework :: Plone",
- "Framework :: Plone :: 4.1",
"Framework :: Plone :: 4.2",
"Framework :: Plone :: 4.3",
"Intended Audience :: End Users/Desktop",
@@ -41,7 +32,6 @@
"Operating System :: OS Independent",
"Programming Language :: JavaScript",
"Programming Language :: Python",
- "Programming Language :: Python :: 2.6",
"Programming Language :: Python :: 2.7",
"Topic :: Software Development :: Libraries :: Python Modules",
],
@@ -63,7 +53,10 @@
'Products.CMFPlone>=4.1'
],
extras_require={
- 'test': test_requires,
+ 'test': [
+ 'plone.app.testing[robot]>=4.2.2',
+ 'plone.app.dexterity',
+ ],
},
entry_points="""
# -*- Entry points: -*-
From 7b134d4f12f5e85571a5592ac144e9a7d0566de0 Mon Sep 17 00:00:00 2001
From: Tom Gross
Date: Fri, 14 Mar 2014 08:11:02 +0100
Subject: [PATCH 20/37] reduce travis test variants
---
.travis.yml | 13 +------------
1 file changed, 1 insertion(+), 12 deletions(-)
diff --git a/.travis.yml b/.travis.yml
index d1439c50..9742c434 100644
--- a/.travis.yml
+++ b/.travis.yml
@@ -1,19 +1,8 @@
language: python
-python:
- - 2.6
- - 2.7
+python: 2.7
env:
- - PLONE_VERSION=4.1
- PLONE_VERSION=4.2
- PLONE_VERSION=4.3
-matrix:
- exclude:
- - python: 2.7
- env: PLONE=4.1
- - python: 2.6
- env: PLONE=4.2
- - python: 2.6
- env: PLONE=4.3
before_install:
- sudo apt-get install -y libjpeg-dev libgif-dev libpng-dev libz-dev
- mkdir -p buildout-cache/downloads
From 4fc6094519ad2965185567dda87cc8f1ed898358 Mon Sep 17 00:00:00 2001
From: Tom Gross
Date: Fri, 14 Mar 2014 08:31:42 +0100
Subject: [PATCH 21/37] fixed typo
---
.travis.yml | 2 +-
src/plone/app/imagecropping/browser/scaling.py | 2 +-
2 files changed, 2 insertions(+), 2 deletions(-)
diff --git a/.travis.yml b/.travis.yml
index 9742c434..fffe5c3f 100644
--- a/.travis.yml
+++ b/.travis.yml
@@ -9,7 +9,7 @@ before_install:
- mkdir -p buildout-cache/eggs
install:
- python bootstrap.py -c test-$PLONE_VERSION.cfg
- - bin/buildout -t 5 -Nc test-$PLONE_VERSION.cfg
+ - bin/buildout -t 10 -Nc test-$PLONE_VERSION.cfg
before_script:
- "export DISPLAY=:99.0"
- "sh -e /etc/init.d/xvfb start"
diff --git a/src/plone/app/imagecropping/browser/scaling.py b/src/plone/app/imagecropping/browser/scaling.py
index 54e64748..9cf5bf75 100644
--- a/src/plone/app/imagecropping/browser/scaling.py
+++ b/src/plone/app/imagecropping/browser/scaling.py
@@ -42,7 +42,7 @@ def scale(self,
from plone.namedfile.interfaces import IImageScaleTraversable
from plone.app.imagecropping.interfaces import IImageCropping
- plone_namedfile_version = pkg_resources.get_distribution('plone_namedfile').version
+ plone_namedfile_version = pkg_resources.get_distribution('plone.namedfile').version
class IImageCroppingScale(IImageScaleTraversable, IImageCropping):
pass
From 79b45a2c14371fae77fabb52a9428e98dd2cd7af Mon Sep 17 00:00:00 2001
From: Tom Gross
Date: Fri, 14 Mar 2014 08:57:14 +0100
Subject: [PATCH 22/37] reverted over optimization
---
.../app/imagecropping/browser/scaling.py | 20 ++++++++++++-------
1 file changed, 13 insertions(+), 7 deletions(-)
diff --git a/src/plone/app/imagecropping/browser/scaling.py b/src/plone/app/imagecropping/browser/scaling.py
index 9cf5bf75..459dd8fc 100644
--- a/src/plone/app/imagecropping/browser/scaling.py
+++ b/src/plone/app/imagecropping/browser/scaling.py
@@ -6,16 +6,11 @@
import pkg_resources
from distutils.version import LooseVersion
+
class ScalingOverrides(object):
_rescale = True
- def modified(self):
- if self._rescale:
- return super(ImageScaling, self).modified()
- else:
- return 1
-
def need_rescale(self, fieldname, scale):
cropped = IAnnotations(self.context).get(PAI_STORAGE_KEY)
if cropped and '%s_%s' % (fieldname, scale) in cropped:
@@ -24,9 +19,14 @@ def need_rescale(self, fieldname, scale):
self._rescale = True
-
class ImageScaling(ScalingOverrides, BaseImageScaling):
+ def modified(self):
+ if self._rescale:
+ return super(ImageScaling, self).modified()
+ else:
+ return 1
+
def scale(self,
fieldname=None,
scale=None,
@@ -54,6 +54,12 @@ class NamedfileImageScaling(ScalingOverrides, NFImageScaling):
prevents rescaling in this case.
"""
+ def modified(self):
+ if self._rescale:
+ return super(NamedfileImageScaling, self).modified()
+ else:
+ return 1
+
if LooseVersion(plone_namedfile_version) >= LooseVersion('2.0.1'):
def scale(self,
fieldname=None,
From 02f521ca485f006940e63d390ee247f516617b25 Mon Sep 17 00:00:00 2001
From: Tom Gross
Date: Fri, 14 Mar 2014 10:11:30 +0100
Subject: [PATCH 23/37] added z3c.blobfile to eggs to activate plone.supermodel
handler
---
test-4.2.cfg | 4 ++++
1 file changed, 4 insertions(+)
diff --git a/test-4.2.cfg b/test-4.2.cfg
index 20555b64..780e9d5c 100644
--- a/test-4.2.cfg
+++ b/test-4.2.cfg
@@ -5,3 +5,7 @@ package-extras = [test]
[versions]
selenium = 2.40.0
+
+[test]
+eggs +=
+ z3c.blobfile
From 6120df2c2039317197cf5dc9f3e969ee44d68b53 Mon Sep 17 00:00:00 2001
From: Tom Gross
Date: Fri, 14 Mar 2014 13:53:17 +0100
Subject: [PATCH 24/37] use bugfix version of plone.app.z3cform
---
test-4.2.cfg | 1 +
1 file changed, 1 insertion(+)
diff --git a/test-4.2.cfg b/test-4.2.cfg
index 780e9d5c..8ab9bd5c 100644
--- a/test-4.2.cfg
+++ b/test-4.2.cfg
@@ -5,6 +5,7 @@ package-extras = [test]
[versions]
selenium = 2.40.0
+plone.app.z3cform = 0.7.0
[test]
eggs +=
From 75ee18b55217224d4b3926db0e0070184fb8105d Mon Sep 17 00:00:00 2001
From: Tom Gross
Date: Sat, 15 Mar 2014 06:44:12 +0100
Subject: [PATCH 25/37] remove plone.namedfile switch. we depend on
plone.namedfile >= 2.0.1
---
setup.py | 1 +
.../app/imagecropping/browser/scaling.py | 35 ++++++-------------
test-4.2.cfg | 5 +--
3 files changed, 12 insertions(+), 29 deletions(-)
diff --git a/setup.py b/setup.py
index c5be6625..39c5ca9c 100644
--- a/setup.py
+++ b/setup.py
@@ -56,6 +56,7 @@
'test': [
'plone.app.testing[robot]>=4.2.2',
'plone.app.dexterity',
+ 'plone.namedfile>=2.0.1',
],
},
entry_points="""
diff --git a/src/plone/app/imagecropping/browser/scaling.py b/src/plone/app/imagecropping/browser/scaling.py
index 459dd8fc..5f9d69c5 100644
--- a/src/plone/app/imagecropping/browser/scaling.py
+++ b/src/plone/app/imagecropping/browser/scaling.py
@@ -3,9 +3,6 @@
from plone.app.imagecropping import PAI_STORAGE_KEY
from plone.app.imaging.scaling import ImageScaling as BaseImageScaling
-import pkg_resources
-from distutils.version import LooseVersion
-
class ScalingOverrides(object):
@@ -42,7 +39,6 @@ def scale(self,
from plone.namedfile.interfaces import IImageScaleTraversable
from plone.app.imagecropping.interfaces import IImageCropping
- plone_namedfile_version = pkg_resources.get_distribution('plone.namedfile').version
class IImageCroppingScale(IImageScaleTraversable, IImageCropping):
pass
@@ -60,27 +56,16 @@ def modified(self):
else:
return 1
- if LooseVersion(plone_namedfile_version) >= LooseVersion('2.0.1'):
- def scale(self,
- fieldname=None,
- scale=None,
- height=None,
- width=None,
- direction='thumbnail',
- **parameters):
- self.need_rescale(fieldname, scale)
- return super(NamedfileImageScaling, self).scale(
- fieldname, scale, height, width, direction, **parameters)
- else:
- def scale(self,
- fieldname=None,
- scale=None,
- height=None,
- width=None,
- **parameters):
- self.need_rescale(fieldname, scale)
- return super(NamedfileImageScaling, self).scale(
- fieldname, scale, height, width, **parameters)
+ def scale(self,
+ fieldname=None,
+ scale=None,
+ height=None,
+ width=None,
+ direction='thumbnail',
+ **parameters):
+ self.need_rescale(fieldname, scale)
+ return super(NamedfileImageScaling, self).scale(
+ fieldname, scale, height, width, direction, **parameters)
except ImportError:
diff --git a/test-4.2.cfg b/test-4.2.cfg
index 8ab9bd5c..30ecd98e 100644
--- a/test-4.2.cfg
+++ b/test-4.2.cfg
@@ -5,8 +5,5 @@ package-extras = [test]
[versions]
selenium = 2.40.0
-plone.app.z3cform = 0.7.0
+plone.namedfile = 2.0.1
-[test]
-eggs +=
- z3c.blobfile
From 5d79d9b4607994130789a20a312353ecacf4c5e0 Mon Sep 17 00:00:00 2001
From: Tom Gross
Date: Sat, 15 Mar 2014 06:47:14 +0100
Subject: [PATCH 26/37] document changes
---
CHANGES.txt | 5 ++++-
1 file changed, 4 insertions(+), 1 deletion(-)
diff --git a/CHANGES.txt b/CHANGES.txt
index 7220ac80..d028ad38 100644
--- a/CHANGES.txt
+++ b/CHANGES.txt
@@ -4,7 +4,8 @@ Changelog
0.1rc3 (unreleased)
-------------------
-- Check for plone.namedfile not Dexterity. It can be used seperately
+- Check for plone.namedfile not Dexterity. It can be used seperately.
+ *If plone.namedfile is used it needs to be at least version 2.0.1*
[tomgross]
- Rename ``imagecropping_keywords.txt`` to ``keywords.robot`` to allow simple
@@ -23,6 +24,8 @@ Changelog
- Fixed #21 (cropping was reset on modifying image)
[tomgross]
+- Only test Plone 4.2 and 4.3 with Python 2.7 on Travis-CI
+ [tomgross]
0.1rc2 (2013-05-03)
-------------------
From 4868874af33e197690030218b29bdb96b06a6025 Mon Sep 17 00:00:00 2001
From: Harald Friessnegger
Date: Fri, 4 Apr 2014 15:13:43 +0200
Subject: [PATCH 27/37] register customized scale view for all archetypes
---
src/plone/app/imagecropping/browser/configure.zcml | 13 +++----------
1 file changed, 3 insertions(+), 10 deletions(-)
diff --git a/src/plone/app/imagecropping/browser/configure.zcml b/src/plone/app/imagecropping/browser/configure.zcml
index bc3d5042..79036a12 100644
--- a/src/plone/app/imagecropping/browser/configure.zcml
+++ b/src/plone/app/imagecropping/browser/configure.zcml
@@ -45,21 +45,14 @@
/>
-
-
+
Date: Fri, 4 Apr 2014 15:14:52 +0200
Subject: [PATCH 28/37] test scales stored in attributestorage too, and add
test for invalidating scales upon resetting the image
---
.../app/imagecropping/tests/test_cropping.py | 61 ++++++++++++++++---
1 file changed, 54 insertions(+), 7 deletions(-)
diff --git a/src/plone/app/imagecropping/tests/test_cropping.py b/src/plone/app/imagecropping/tests/test_cropping.py
index bd019ae8..a5fc4fc0 100644
--- a/src/plone/app/imagecropping/tests/test_cropping.py
+++ b/src/plone/app/imagecropping/tests/test_cropping.py
@@ -24,6 +24,23 @@ def setUp(self):
f = file(join(dirname(tests.__file__), 'plone-logo.png'))
self.img.setImage(f)
f.close()
+
+
+ def _jpegImage(self):
+ """convert our testimage to jpeg format
+ and return it's data
+ """
+
+ from cStringIO import StringIO
+ from PIL.Image import open
+
+ img = open(file(join(dirname(tests.__file__), 'plone-logo.png')))
+ out = StringIO()
+ img.save(out, format='JPEG', quality=75)
+ out.seek(0)
+ result = out.getvalue()
+ out.close()
+ return result
def test_image_and_annotation(self):
"""check that our cropping view is able to store a cropped image
@@ -96,16 +113,12 @@ def test_image_formats(self):
self.assertEqual(open(croppedData).format, 'PNG',
"cropped scale does not have same format as the original")
- # create a jpeg image out of the png file:
- img = open(file(join(dirname(tests.__file__), 'plone-logo.png')))
- out = StringIO()
- img.save(out, format='JPEG', quality=75)
- out.seek(0)
+ # create a jpeg image out of the png file
# and test if created scale is jpeg too
_createObjectByType('Image', self.portal, 'testjpeg')
jpg = self.portal.testjpeg
- jpg.setImage(out.getvalue())
+ jpg.setImage(self._jpegImage())
org_data = StringIO(jpg.getImage().data)
self.assertEqual(open(org_data).format, 'JPEG')
@@ -130,11 +143,45 @@ def test_modify_context(self):
# store cropped version for thumb and check if the result
# is a square now
view._crop(fieldname='image', scale='thumb', box=(14, 14, 218, 218))
+
+ # images accessed via context/@@images/image/thumb
+ # stored in plone.scale annotation
+ # see https://github.com/plone/plone.scale/pull/3#issuecomment-28597087
thumb = scales.scale('image', 'thumb')
self.failIfEqual(thumb.data, unscaled_thumb.data)
+
+ #images accessed via context/image_thumb
+ #stored in attribute_storage
+ thumb_attr = traverse(self.img, 'image_thumb')
+ self.failIfEqual(thumb_attr.data, unscaled_thumb.data)
+
+ #import pdb;pdb.set_trace()
+ self.assertEqual((thumb.width, thumb.height), (thumb_attr.width, thumb_attr.height))
+
+
self.img.setTitle('A new title')
self.img.reindexObject()
+
thumb2 = scales.scale('image', 'thumb')
- self.assertEqual(thumb.data, thumb2.data)
+ self.assertEqual(thumb.data, thumb2.data, 'context/@@images/image/thumb accessor lost cropped scale')
+
+ thumb2_attr = traverse(self.img, 'image_thumb')
+ self.assertEqual((thumb.width, thumb.height),
+ (thumb2_attr.width, thumb2_attr.height),
+ 'context/image_thumb accessor lost cropped scale')
+
+
+
+ # set a different image, this should invalidate scales
+ self.img.setImage(self._jpegImage())
+
+ jpeg_thumb_attr = traverse(self.img, 'image_thumb')
+ self.failIfEqual((jpeg_thumb_attr.width, jpeg_thumb_attr.height),
+ (128, 128),
+ 'context/image_thumb returns old cropped scale after setting a new image')
+
+ jpeg_thumb = scales.scale('image', 'thumb')
+ self.failIfEqual((jpeg_thumb.width, jpeg_thumb.height), (128, 128),
+ 'context/@@images/image/thumb returns old cropped scale after setting a new image')
From bf34b7db076e50f376b6fc20fbdc7b14aaa8833b Mon Sep 17 00:00:00 2001
From: Tom Gross
Date: Thu, 15 May 2014 13:20:54 +0200
Subject: [PATCH 29/37] remove scales information, if image changes
---
.../app/imagecropping/browser/configure.zcml | 2 +-
src/plone/app/imagecropping/configure.zcml | 3 +++
src/plone/app/imagecropping/utils.py | 19 +++++++++++++++++++
3 files changed, 23 insertions(+), 1 deletion(-)
diff --git a/src/plone/app/imagecropping/browser/configure.zcml b/src/plone/app/imagecropping/browser/configure.zcml
index 79036a12..6a39172e 100644
--- a/src/plone/app/imagecropping/browser/configure.zcml
+++ b/src/plone/app/imagecropping/browser/configure.zcml
@@ -46,7 +46,7 @@
+
+
diff --git a/src/plone/app/imagecropping/utils.py b/src/plone/app/imagecropping/utils.py
index 203acbd2..e1fd31cf 100644
--- a/src/plone/app/imagecropping/utils.py
+++ b/src/plone/app/imagecropping/utils.py
@@ -4,15 +4,23 @@
from Products.ATContentTypes.interfaces.interfaces import IATContentType
from Products.Archetypes.interfaces.field import IImageField
from ZODB.blob import Blob
+from plone.app.blob.config import blobScalesAttr
from plone.app.blob.interfaces import IBlobImageField
+from plone.app.imagecropping import PAI_STORAGE_KEY
+from plone.app.imagecropping.interfaces import IImageCropping
from plone.app.imagecropping.interfaces import IImageCroppingUtils
from plone.app.imaging.interfaces import IImageScaleHandler
+from plone.app.imaging.traverse import ImageTraverser as BaseImageTraverser
from plone.app.imaging.utils import getAllowedSizes
from plone.scale.scale import scaleImage
from plone.scale.storage import AnnotationStorage
+
+from zope.annotation.interfaces import IAnnotations
from zope.component import adapts
from zope.interface import implements
from zope.interface.declarations import providedBy
+from zope.publisher.interfaces import IRequest
+
import time
@@ -204,3 +212,14 @@ def crop_factory(fieldname, **parameters):
width=w,
height=h,
)
+
+
+class ImageTraverser(BaseImageTraverser):
+
+ adapts(IImageCropping, IRequest)
+
+ def publishTraverse(self, request, name):
+ # remove scales information, if image has changed
+ if not hasattr(aq_base(self.context), blobScalesAttr):
+ del IAnnotations(self.context)[PAI_STORAGE_KEY]
+ return super(ImageTraverser, self).publishTraverse(request, name)
From d60b1e2d61365bfff3777bbcc8ee60b45ab0713c Mon Sep 17 00:00:00 2001
From: Tom Gross
Date: Fri, 16 May 2014 16:37:25 +0200
Subject: [PATCH 30/37] fix situation, where no crop information is available
---
.gitignore | 1 +
src/plone/app/imagecropping/utils.py | 5 +++--
2 files changed, 4 insertions(+), 2 deletions(-)
diff --git a/.gitignore b/.gitignore
index 18256b14..f11ce7d9 100644
--- a/.gitignore
+++ b/.gitignore
@@ -38,3 +38,4 @@ lib
# Local development
local.cfg
+*.swp
diff --git a/src/plone/app/imagecropping/utils.py b/src/plone/app/imagecropping/utils.py
index e1fd31cf..617a0285 100644
--- a/src/plone/app/imagecropping/utils.py
+++ b/src/plone/app/imagecropping/utils.py
@@ -220,6 +220,7 @@ class ImageTraverser(BaseImageTraverser):
def publishTraverse(self, request, name):
# remove scales information, if image has changed
- if not hasattr(aq_base(self.context), blobScalesAttr):
- del IAnnotations(self.context)[PAI_STORAGE_KEY]
+ if ((not hasattr(aq_base(self.context), blobScalesAttr)) and
+ (PAI_STORAGE_KEY in IAnnotations(self.context))):
+ del IAnnotations(self.context)[PAI_STORAGE_KEY]
return super(ImageTraverser, self).publishTraverse(request, name)
From bc1001cf154c30acd90813c06b4d44ada6f3ec81 Mon Sep 17 00:00:00 2001
From: Harald Friessnegger
Date: Mon, 19 May 2014 10:16:10 +0200
Subject: [PATCH 31/37] remove todo
---
src/plone/app/imagecropping/browser/editor.pt | 1 -
1 file changed, 1 deletion(-)
diff --git a/src/plone/app/imagecropping/browser/editor.pt b/src/plone/app/imagecropping/browser/editor.pt
index 8d4eacd2..7dc2ffb1 100644
--- a/src/plone/app/imagecropping/browser/editor.pt
+++ b/src/plone/app/imagecropping/browser/editor.pt
@@ -30,7 +30,6 @@
This operation is non-destructive which means, your original image data doesn't get lost when cropping a scale.
By removing a cropping area, the scale gets back to its default functionality: resize, no crop.
- xxx check if self/scales is empty and show a message in this case
Date: Mon, 19 May 2014 13:19:53 +0200
Subject: [PATCH 33/37] our test type needs this interface so
NamedfileImageScaling is looked up for `@@images`
---
CHANGES.txt | 2 +-
src/plone/app/imagecropping/testing.zcml | 1 +
2 files changed, 2 insertions(+), 1 deletion(-)
diff --git a/CHANGES.txt b/CHANGES.txt
index 4b21df48..5e6da55c 100644
--- a/CHANGES.txt
+++ b/CHANGES.txt
@@ -30,7 +30,7 @@ Changelog
[bogdangi]
- Fixed #21 (cropping was reset on modifying image)
- [tomgross]
+ [tomgross, fRiSi]
- Only test Plone 4.2 and 4.3 with Python 2.7 on Travis-CI
[tomgross]
diff --git a/src/plone/app/imagecropping/testing.zcml b/src/plone/app/imagecropping/testing.zcml
index a3aab033..f8d0a9f7 100644
--- a/src/plone/app/imagecropping/testing.zcml
+++ b/src/plone/app/imagecropping/testing.zcml
@@ -15,6 +15,7 @@
+
From 172bfb45348305ee8d799b67455a3e5653a1a92d Mon Sep 17 00:00:00 2001
From: Tom Gross
Date: Fri, 30 May 2014 15:43:21 +0200
Subject: [PATCH 34/37] removed unneeded interface
---
src/plone/app/imagecropping/testing.zcml | 1 -
1 file changed, 1 deletion(-)
diff --git a/src/plone/app/imagecropping/testing.zcml b/src/plone/app/imagecropping/testing.zcml
index f8d0a9f7..012692e1 100644
--- a/src/plone/app/imagecropping/testing.zcml
+++ b/src/plone/app/imagecropping/testing.zcml
@@ -14,7 +14,6 @@
/>
-
From 729c0c5eff39a88b5cf7e43af902eeeec536b04c Mon Sep 17 00:00:00 2001
From: Harald Friessnegger
Date: Fri, 30 May 2014 15:24:30 +0200
Subject: [PATCH 35/37] fix indentation
---
src/plone/app/imagecropping/utils.py | 16 ++++++++--------
1 file changed, 8 insertions(+), 8 deletions(-)
diff --git a/src/plone/app/imagecropping/utils.py b/src/plone/app/imagecropping/utils.py
index 617a0285..131282ae 100644
--- a/src/plone/app/imagecropping/utils.py
+++ b/src/plone/app/imagecropping/utils.py
@@ -216,11 +216,11 @@ def crop_factory(fieldname, **parameters):
class ImageTraverser(BaseImageTraverser):
- adapts(IImageCropping, IRequest)
-
- def publishTraverse(self, request, name):
- # remove scales information, if image has changed
- if ((not hasattr(aq_base(self.context), blobScalesAttr)) and
- (PAI_STORAGE_KEY in IAnnotations(self.context))):
- del IAnnotations(self.context)[PAI_STORAGE_KEY]
- return super(ImageTraverser, self).publishTraverse(request, name)
+ adapts(IImageCropping, IRequest)
+
+ def publishTraverse(self, request, name):
+ # remove scales information, if image has changed
+ if ((not hasattr(aq_base(self.context), blobScalesAttr)) and
+ (PAI_STORAGE_KEY in IAnnotations(self.context))):
+ del IAnnotations(self.context)[PAI_STORAGE_KEY]
+ return super(ImageTraverser, self).publishTraverse(request, name)
From 9e0d4b0d410f6b0abff5775efb54cf9d5db08081 Mon Sep 17 00:00:00 2001
From: Harald Friessnegger
Date: Fri, 30 May 2014 15:29:31 +0200
Subject: [PATCH 36/37] add documenation and try to use meaningful names
---
.../app/imagecropping/browser/scaling.py | 37 ++++++++++++++-----
src/plone/app/imagecropping/utils.py | 4 ++
2 files changed, 32 insertions(+), 9 deletions(-)
diff --git a/src/plone/app/imagecropping/browser/scaling.py b/src/plone/app/imagecropping/browser/scaling.py
index 5f9d69c5..9d5660fe 100644
--- a/src/plone/app/imagecropping/browser/scaling.py
+++ b/src/plone/app/imagecropping/browser/scaling.py
@@ -6,20 +6,33 @@
class ScalingOverrides(object):
- _rescale = True
-
- def need_rescale(self, fieldname, scale):
+ _allow_rescale = True
+
+ def _need_rescale(self, fieldname, scale):
+ """if we've got a cropping annotation for the given fieldname and scale,
+ set self._rescale to False, to prevent plone.app.imaging traverser to
+ overwrite our cropped scale
+
+ since the self.modified() method does not know about the currently
+ requested scale name, we need to use the _rescale property
+ """
cropped = IAnnotations(self.context).get(PAI_STORAGE_KEY)
if cropped and '%s_%s' % (fieldname, scale) in cropped:
- self._rescale = False
+ self._allow_rescale = False
else:
- self._rescale = True
+ self._allow_rescale = True
class ImageScaling(ScalingOverrides, BaseImageScaling):
def modified(self):
- if self._rescale:
+ """we overwrite the default method that would return the modification
+ time of the context,
+ to return a way back modification time in case the currently requested
+ scale is a cropped scale. (so plone.scale does not create a new scale
+ w/o cropping information
+ """
+ if self._allow_rescale:
return super(ImageScaling, self).modified()
else:
return 1
@@ -30,7 +43,7 @@ def scale(self,
height=None,
width=None,
**parameters):
- self.need_rescale(fieldname, scale)
+ self._need_rescale(fieldname, scale)
return super(ImageScaling, self).scale(fieldname, scale, height, width, **parameters)
try:
@@ -51,7 +64,13 @@ class NamedfileImageScaling(ScalingOverrides, NFImageScaling):
"""
def modified(self):
- if self._rescale:
+ """we overwrite the default method that would return the modification
+ time of the context,
+ to return a way back modification time in case the currently requested
+ scale is a cropped scale. (so plone.scale does not create a new scale
+ w/o cropping information
+ """
+ if self._allow_rescale:
return super(NamedfileImageScaling, self).modified()
else:
return 1
@@ -63,7 +82,7 @@ def scale(self,
width=None,
direction='thumbnail',
**parameters):
- self.need_rescale(fieldname, scale)
+ self._need_rescale(fieldname, scale)
return super(NamedfileImageScaling, self).scale(
fieldname, scale, height, width, direction, **parameters)
diff --git a/src/plone/app/imagecropping/utils.py b/src/plone/app/imagecropping/utils.py
index 131282ae..a5b5bd45 100644
--- a/src/plone/app/imagecropping/utils.py
+++ b/src/plone/app/imagecropping/utils.py
@@ -215,6 +215,10 @@ def crop_factory(fieldname, **parameters):
class ImageTraverser(BaseImageTraverser):
+ """extend the standard image traverser to remove our cropping annotations
+ (if present) in case the original image has been removed/replaced
+ (no blobScalesAttr)
+ """
adapts(IImageCropping, IRequest)
From 110cead7bca4f99eb74d7472a7c8a8eb4fa46d84 Mon Sep 17 00:00:00 2001
From: Harald Friessnegger
Date: Fri, 30 May 2014 15:35:03 +0200
Subject: [PATCH 37/37] remove redundant changelog
---
CHANGES.txt | 3 ---
1 file changed, 3 deletions(-)
diff --git a/CHANGES.txt b/CHANGES.txt
index 5e6da55c..5fdf1e3a 100644
--- a/CHANGES.txt
+++ b/CHANGES.txt
@@ -12,9 +12,6 @@ Changelog
in the controlpanel if there are no croppable scales to show.
(previously this caused a `SiteError`)
[fRiSi]
-
-- Check for plone.namedfile not Dexterity. It can be used seperately
- [tom_gross]
- Rename ``imagecropping_keywords.txt`` to ``keywords.robot`` to allow simple
reusage in ``plone.app.robotframework``.