diff --git a/CHANGELOG.txt b/CHANGELOG.txt index 9acd25d25e..3d0886c7b7 100644 --- a/CHANGELOG.txt +++ b/CHANGELOG.txt @@ -9,6 +9,7 @@ Changelog * Rearranged SCSS folder structure to the client folder and split them approximately according to ITCSS. (Naomi Morduch Toubman, Jonny Scholes, Janneke Janssen, Hugo van den Berg) * Fix: ModelAdmin no longer fails when filtering over a foreign key relation (Jason Dilworth, Matt Westcott) * Fix: The Wagtail version number is now visible within the Settings menu (Kevin Howbrook) + * Fix: Scaling images now rounds values to an integer so that images render without errors (Adrian Brunyate) 2.5 (24.04.2019) diff --git a/docs/releases/2.6.rst b/docs/releases/2.6.rst index 6606a34c4d..97b3e5285a 100644 --- a/docs/releases/2.6.rst +++ b/docs/releases/2.6.rst @@ -23,6 +23,7 @@ Bug fixes * ModelAdmin no longer fails when filtering over a foreign key relation (Jason Dilworth, Matt Westcott) * The Wagtail version number is now visible within the Settings menu (Kevin Howbrook) + * Scaling images now rounds values to an integer so that images render without errors (Adrian Brunyate) Upgrade considerations diff --git a/wagtail/images/image_operations.py b/wagtail/images/image_operations.py index 6caaaef978..9964e3d870 100644 --- a/wagtail/images/image_operations.py +++ b/wagtail/images/image_operations.py @@ -225,8 +225,8 @@ class ScaleOperation(Operation): image_width, image_height = willow.get_size() scale = self.percent / 100 - width = float(image_width * scale) - height = float(image_height * scale) + width = int(image_width * scale) + height = int(image_height * scale) return willow.resize((width, height)) diff --git a/wagtail/images/tests/test_image_operations.py b/wagtail/images/tests/test_image_operations.py index a525956dbd..d91ae86ee6 100644 --- a/wagtail/images/tests/test_image_operations.py +++ b/wagtail/images/tests/test_image_operations.py @@ -23,11 +23,20 @@ class WillowOperationRecorder: def __getattr__(self, attr): def operation(*args, **kwargs): + self.validate_operation(attr, args, kwargs) self.ran_operations.append((attr, args, kwargs)) return self return operation + def validate_operation(self, operation, args, kwargs): + """Check if the requested operation is sane and raise an exception if not.""" + # The Willow docs say resize must take integral dimensions. + if operation == "resize": + x, y = args[0] + if x != int(x) or y != int(y): + raise ValueError + def get_size(self): size = self.start_size @@ -46,6 +55,7 @@ class ImageOperationTestCase(TestCase): filter_spec_tests = [] filter_spec_error_tests = [] run_tests = [] + norun_tests = [] @classmethod def make_filter_spec_test(cls, filter_spec, expected_output): @@ -88,6 +98,25 @@ class ImageOperationTestCase(TestCase): test_run.__name__ = str('test_run_%s' % filter_spec) return test_run + @classmethod + def make_norun_test(cls, filter_spec, image_kwargs): + def test_norun(self): + image = Image(**image_kwargs) + + # Make operation + operation = self.operation_class(*filter_spec.split('-')) + + # Make operation recorder + operation_recorder = WillowOperationRecorder((image.width, image.height)) + + # Attempt (and hopefully fail) to run + with self.assertRaises(ValueError): + operation.run(operation_recorder, image, {}) + + test_norun.__name__ = str('test_norun_%s' % filter_spec) + return test_norun + + @classmethod def setup_test_methods(cls): if cls.operation_class is None: @@ -108,6 +137,11 @@ class ImageOperationTestCase(TestCase): run_test = cls.make_run_test(*args) setattr(cls, run_test.__name__, run_test) + # Runtime error tests + for args in cls.norun_tests: + norun_test = cls.make_norun_test(*args) + setattr(cls, norun_test.__name__, norun_test) + class TestDoNothingOperation(ImageOperationTestCase): operation_class = image_operations.DoNothingOperation @@ -388,7 +422,7 @@ class TestScaleOperation(ImageOperationTestCase): ]), # Rounded usage of scale ('scale-83.0322', dict(width=1000, height=500), [ - ('resize', ((1000 * 0.830322, 500 * 0.830322), ), {}), + ('resize', ((int(1000 * 0.830322), int(500 * 0.830322)), ), {}), ]), ]