From c3ef5172c35a57be29b4bad97f097fe37dbd2c10 Mon Sep 17 00:00:00 2001 From: Matthew Tretter Date: Sat, 11 Feb 2012 13:06:48 -0500 Subject: [PATCH] Rename ImageSpec to ImageSpecField The ImageSpec class remains for now, but using it throws deprecation warnings. --- README.rst | 12 ++++----- imagekit/admin.py | 2 +- imagekit/models.py | 47 ++++++++++++++++++++------------- imagekit/processors/__init__.py | 2 +- tests/core/tests.py | 12 ++++----- 5 files changed, 42 insertions(+), 33 deletions(-) diff --git a/README.rst b/README.rst index 3dc86cc..5ca153f 100644 --- a/README.rst +++ b/README.rst @@ -29,11 +29,11 @@ Much like ``django.db.models.ImageField``, Specs are defined as properties of a model class:: from django.db import models - from imagekit.models import ImageSpec + from imagekit.models import ImageSpecField class Photo(models.Model): original_image = models.ImageField(upload_to='photos') - formatted_image = ImageSpec(image_field='original_image', format='JPEG', + formatted_image = ImageSpecField(image_field='original_image', format='JPEG', options={'quality': 90}) Accessing the spec through a model instance will create the image and return @@ -44,7 +44,7 @@ an ImageFile-like object (just like with a normal photo.original_image.url # > '/media/photos/birthday.tiff' photo.formatted_image.url # > '/media/cache/photos/birthday_formatted_image.jpeg' -Check out ``imagekit.models.ImageSpec`` for more information. +Check out ``imagekit.models.ImageSpecField`` for more information. Processors @@ -55,12 +55,12 @@ something to it, and return the result. By providing a list of processors to your spec, you can expose different versions of the original image:: from django.db import models - from imagekit.models import ImageSpec + from imagekit.models import ImageSpecField from imagekit.processors import resize, Adjust class Photo(models.Model): original_image = models.ImageField(upload_to='photos') - thumbnail = ImageSpec([Adjust(contrast=1.2, sharpness=1.1), + thumbnail = ImageSpecField([Adjust(contrast=1.2, sharpness=1.1), resize.Crop(50, 50)], image_field='original_image', format='JPEG', options={'quality': 90}) @@ -87,7 +87,7 @@ implement a ``process()`` method:: class Photo(models.Model): original_image = models.ImageField(upload_to='photos') - watermarked_image = ImageSpec([Watermark()], image_field='original_image', + watermarked_image = ImageSpecField([Watermark()], image_field='original_image', format='JPEG', options={'quality': 90}) diff --git a/imagekit/admin.py b/imagekit/admin.py index ebab76c..f764d3e 100644 --- a/imagekit/admin.py +++ b/imagekit/admin.py @@ -12,7 +12,7 @@ class AdminThumbnail(object): def __init__(self, image_field, template=None): """ - :param image_field: The name of the ImageField or ImageSpec on the + :param image_field: The name of the ImageField or ImageSpecField on the model to use for the thumbnail. :param template: The template with which to render the thumbnail diff --git a/imagekit/models.py b/imagekit/models.py index 01569fc..a170216 100755 --- a/imagekit/models.py +++ b/imagekit/models.py @@ -12,9 +12,10 @@ from imagekit.utils import img_to_fobj, get_spec_files, open_image, \ format_to_extension, extension_to_format, UnknownFormatError, \ UnknownExtensionError from imagekit.processors import ProcessorPipeline, AutoConvert +import warnings -class _ImageSpecMixin(object): +class _ImageSpecFieldMixin(object): def __init__(self, processors=None, format=None, options={}, autoconvert=True): self.processors = processors @@ -30,9 +31,9 @@ class _ImageSpecMixin(object): return processors.process(image.copy()) -class ImageSpec(_ImageSpecMixin): +class ImageSpecField(_ImageSpecFieldMixin): """ - The heart and soul of the ImageKit library, ImageSpec allows you to add + The heart and soul of the ImageKit library, ImageSpecField allows you to add variants of uploaded images to your models. """ @@ -44,7 +45,7 @@ class ImageSpec(_ImageSpecMixin): """ :param processors: A list of processors to run on the original image. :param format: The format of the output file. If not provided, - ImageSpec will try to guess the appropriate format based on the + ImageSpecField will try to guess the appropriate format based on the extension of the filename and the format of the input image. :param options: A dictionary that will be passed to PIL's ``Image.save()`` method as keyword arguments. Valid options vary @@ -77,7 +78,7 @@ class ImageSpec(_ImageSpecMixin): """ - _ImageSpecMixin.__init__(self, processors, format=format, + _ImageSpecFieldMixin.__init__(self, processors, format=format, options=options, autoconvert=autoconvert) self.image_field = image_field self.pre_cache = pre_cache @@ -85,7 +86,7 @@ class ImageSpec(_ImageSpecMixin): self.cache_to = cache_to def contribute_to_class(self, cls, name): - setattr(cls, name, _ImageSpecDescriptor(self, name)) + setattr(cls, name, _ImageSpecFieldDescriptor(self, name)) try: ik = getattr(cls, '_ik') except AttributeError: @@ -101,6 +102,13 @@ class ImageSpec(_ImageSpecMixin): dispatch_uid='%s.delete' % uid) +class ImageSpec(ImageSpecField): + def __init__(self, *args, **kwargs): + warnings.warn('ImageSpec has been renamed to ImageSpecField. Please' + ' use that instead.', DeprecationWarning) + super(ImageSpec, self).__init__(*args, **kwargs) + + def _get_suggested_extension(name, format): original_extension = os.path.splitext(name)[1] try: @@ -124,7 +132,7 @@ def _get_suggested_extension(name, format): return extension -class _ImageSpecFileMixin(object): +class _ImageSpecFieldFileMixin(object): def _process_content(self, filename, content): img = open_image(content) original_format = img.format @@ -156,7 +164,7 @@ class _ImageSpecFileMixin(object): return img, content -class ImageSpecFile(_ImageSpecFileMixin, ImageFieldFile): +class ImageSpecFieldFile(_ImageSpecFieldFileMixin, ImageFieldFile): def __init__(self, instance, field, attname): ImageFieldFile.__init__(self, instance, field, None) self.attname = attname @@ -173,12 +181,12 @@ class ImageSpecFile(_ImageSpecFileMixin, ImageFieldFile): isinstance(f, models.ImageField)] if len(image_fields) == 0: raise Exception('%s does not define any ImageFields, so your' \ - ' %s ImageSpec has no image to act on.' % \ + ' %s ImageSpecField has no image to act on.' % \ (self.instance.__class__.__name__, self.attname)) elif len(image_fields) > 1: raise Exception('%s defines multiple ImageFields, but you' \ ' have not specified an image_field for your %s' \ - ' ImageSpec.' % (self.instance.__class__.__name__, + ' ImageSpecField.' % (self.instance.__class__.__name__, self.attname)) else: field_file = image_fields[0] @@ -275,7 +283,7 @@ class ImageSpecFile(_ImageSpecFileMixin, ImageFieldFile): def name(self): """ Specifies the filename that the cached image will use. The user can - control this by providing a `cache_to` method to the ImageSpec. + control this by providing a `cache_to` method to the ImageSpecField. """ name = getattr(self, '_name', None) @@ -303,12 +311,12 @@ class ImageSpecFile(_ImageSpecFileMixin, ImageFieldFile): def name(self, value): # TODO: Figure out a better way to handle this. We really don't want # to allow anybody to set the name, but ``File.__init__`` (which is - # called by ``ImageSpecFile.__init__``) does, so we have to allow it - # at least that one time. + # called by ``ImageSpecFieldFile.__init__``) does, so we have to allow + # it at least that one time. pass -class _ImageSpecDescriptor(object): +class _ImageSpecFieldDescriptor(object): def __init__(self, field, attname): self.attname = attname self.field = field @@ -317,7 +325,8 @@ class _ImageSpecDescriptor(object): if instance is None: return self.field else: - img_spec_file = ImageSpecFile(instance, self.field, self.attname) + img_spec_file = ImageSpecFieldFile(instance, self.field, + self.attname) setattr(instance, self.attname, img_spec_file) return img_spec_file @@ -340,14 +349,14 @@ def _post_delete_handler(sender, instance=None, **kwargs): spec_file.delete(save=False) -class ProcessedImageFieldFile(ImageFieldFile, _ImageSpecFileMixin): +class ProcessedImageFieldFile(ImageFieldFile, _ImageSpecFieldFileMixin): def save(self, name, content, save=True): new_filename = self.field.generate_filename(self.instance, name) img, content = self._process_content(new_filename, content) return super(ProcessedImageFieldFile, self).save(name, content, save) -class ProcessedImageField(models.ImageField, _ImageSpecMixin): +class ProcessedImageField(models.ImageField, _ImageSpecFieldMixin): """ ProcessedImageField is an ImageField that runs processors on the uploaded image *before* saving it to storage. This is in contrast to specs, which @@ -365,14 +374,14 @@ class ProcessedImageField(models.ImageField, _ImageSpecMixin): The ProcessedImageField constructor accepts all of the arguments that the :class:`django.db.models.ImageField` constructor accepts, as well as the ``processors``, ``format``, and ``options`` arguments of - :class:`imagekit.models.ImageSpec`. + :class:`imagekit.models.ImageSpecField`. """ if 'quality' in kwargs: raise Exception('The "quality" keyword argument has been' """ deprecated. Use `options={'quality': %s}` instead.""" \ % kwargs['quality']) - _ImageSpecMixin.__init__(self, processors, format=format, + _ImageSpecFieldMixin.__init__(self, processors, format=format, options=options, autoconvert=autoconvert) models.ImageField.__init__(self, verbose_name, name, width_field, height_field, **kwargs) diff --git a/imagekit/processors/__init__.py b/imagekit/processors/__init__.py index 87d753c..c3be66c 100644 --- a/imagekit/processors/__init__.py +++ b/imagekit/processors/__init__.py @@ -186,7 +186,7 @@ class Transpose(object): class AutoConvert(object): """A processor that does some common-sense conversions based on the target format. This includes things like preserving transparency and quantizing. - This processors is used automatically by ``ImageSpec`` and + This processors is used automatically by ``ImageSpecField`` and ``ProcessedImageField`` immediately before saving the image unless you specify ``autoconvert=False``. diff --git a/tests/core/tests.py b/tests/core/tests.py index 91ca847..6443f02 100644 --- a/tests/core/tests.py +++ b/tests/core/tests.py @@ -9,7 +9,7 @@ from django.test import TestCase from imagekit import utils from imagekit.lib import Image -from imagekit.models import ImageSpec +from imagekit.models import ImageSpecField from imagekit.processors import Adjust from imagekit.processors.resize import Crop from imagekit.processors.crop import SmartCrop @@ -18,13 +18,13 @@ from imagekit.processors.crop import SmartCrop class Photo(models.Model): original_image = models.ImageField(upload_to='photos') - thumbnail = ImageSpec([Adjust(contrast=1.2, sharpness=1.1), Crop(50, 50)], - image_field='original_image', format='JPEG', + thumbnail = ImageSpecField([Adjust(contrast=1.2, sharpness=1.1), + Crop(50, 50)], image_field='original_image', format='JPEG', options={'quality': 90}) - smartcropped_thumbnail = ImageSpec([Adjust(contrast=1.2, sharpness=1.1), SmartCrop(50, 50)], - image_field='original_image', format='JPEG', - options={'quality': 90}) + smartcropped_thumbnail = ImageSpecField([Adjust(contrast=1.2, + sharpness=1.1), SmartCrop(50, 50)], image_field='original_image', + format='JPEG', options={'quality': 90}) class IKTest(TestCase):