wagtail / Willow

A wrapper that combines the functionality of multiple Python image libraries into one API
https://willow.wagtail.org/
BSD 3-Clause "New" or "Revised" License
273 stars 53 forks source link

Dynamic image preview fails when WILLOW_OPTIMIZERS is set #147

Closed tomkins closed 2 months ago

tomkins commented 3 months ago

Issue Summary

Currently when you've got an optimizer enabled in WILLOW_OPTIMIZERS, and use the Image URL Generator, it'll come up with a 500:

Internal Server Error: /admin/images/26/preview/original/
Traceback (most recent call last):
  ...
  File "/Users/tomkins/Python/wagtail/wagtail/images/views/images.py", line 295, in preview
    image = Filter(spec=filter_spec).run(image, response)
            ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/Users/tomkins/Python/wagtail/wagtail/images/models.py", line 1031, in run
    return willow.save_as_png(output, optimize=True)
           ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/Users/tomkins/Python/willow/willow/plugins/pillow.py", line 313, in save_as_png
    self.optimize(f, "png")
  File "/Users/tomkins/Python/willow/willow/image.py", line 178, in optimize
    optimizer.process(file_path)
                      ^^^^^^^^^
UnboundLocalError: cannot access local variable 'file_path' where it is not associated with a value

Slightly obscure (not sure how many people actually the combination of Willow optimizers and the dynamic image serve view!).

Steps to Reproduce

Technical details

Working on this

Pull request coming shortly!

RealOrangeOne commented 3 months ago

Transferred this issue from Wagtail, as whilst we can avoid the issue in Wagtail, there's still a bug in Willow to fix.

The root cause is in this block: https://github.com/wagtail/Willow/blob/7e49ca06dc5211a3e85bfc89314ba8ae3914e854/willow/image.py#L150-L173

The if doesn't have an else case, and so if an unexpected type is passed, file_path never gets defined.

The solution will either be to attempt to read whatever object we get into a SpooledTemporaryFile, or explicitly raise a type error.