django-versatileimagefield
django-versatileimagefield copied to clipboard
Stdout call creates blank error in log
Just spent an hour or so tracing down a blank wsgi:error line that kept appearing in my live server logs. It was caused by the VersatileImageFieldWarmer.warm() method which is writing a new line character to stdout. I have a post_save receiver setup that automatically warms images when the model is saved, per docs on Auto-creating sets of images on post_save.
Towards the bottom VersatileImageFieldWarmer.warm() does this:
if a * b == total:
stdout.write('\n')
So for now I monkey patched my version with:
def patched_warm_method(self):
"""
NOTE - this is a MONKEY PATCH to fix the VersatileImageFieldWarmer.warm() method from using
stdout specifically where it does stdout.write('\n')
This keeps blank error lines out of the log, which are confusing!
Returns a 2-tuple:
[0]: Number of images successfully pre-warmed
[1]: A list of paths on the storage class associated with the
VersatileImageField field being processed by `self` of
files that could not be successfully seeded.
"""
num_images_pre_warmed = 0
failed_to_create_image_path_list = []
total = self.queryset.count() * len(self.size_key_list)
for a, instance in enumerate(self.queryset, start=1):
for b, size_key in enumerate(self.size_key_list, start=1):
success, url_or_filepath = self._prewarm_versatileimagefield(
size_key,
reduce(getattr, self.image_attr.split("."), instance)
)
if success is True:
num_images_pre_warmed += 1
else:
failed_to_create_image_path_list.append(url_or_filepath)
return (num_images_pre_warmed, failed_to_create_image_path_list)
And then you can use the patched version like so:
# MONKEY PATCH the warm method (see notes on patched_warm_method)
VersatileImageFieldWarmer.warm = patched_warm_method
img_warmer = VersatileImageFieldWarmer(
instance_or_queryset=instance,
rendition_key_set='image_field',
image_attr='image_field',
)
num_created, failed_to_create = img_warmer.warm()
As alternative you may use patch context manager from unittest to change stdout to devnull:
with open(os.devnull, "w") as f:
with patch("versatileimagefield.image_warmer.stdout", f):
Warmer(...).warm()
But it would be nice to pass some optional argument to warm, so as not to output anything to stdout