Skip to content

Commit

Permalink
Rename ImageSpec to ImageSpecField
Browse files Browse the repository at this point in the history
The ImageSpec class remains for now, but using it throws
deprecation warnings.
  • Loading branch information
matthewwithanm committed Feb 11, 2012
1 parent c2a4d01 commit c3ef517
Show file tree
Hide file tree
Showing 5 changed files with 42 additions and 33 deletions.
12 changes: 6 additions & 6 deletions README.rst
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand All @@ -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
Expand All @@ -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})

Expand All @@ -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})


Expand Down
2 changes: 1 addition & 1 deletion imagekit/admin.py
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down
47 changes: 28 additions & 19 deletions imagekit/models.py
Original file line number Diff line number Diff line change
Expand Up @@ -12,9 +12,10 @@
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
Expand All @@ -30,9 +31,9 @@ def process(self, image, file, instance):
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.
"""
Expand All @@ -44,7 +45,7 @@ def __init__(self, processors=None, format=None, options={},
"""
: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
Expand Down Expand Up @@ -77,15 +78,15 @@ def __init__(self, processors=None, format=None, options={},
"""

_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
self.storage = storage
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:
Expand All @@ -101,6 +102,13 @@ def contribute_to_class(self, cls, name):
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:
Expand All @@ -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
Expand Down Expand Up @@ -156,7 +164,7 @@ def _process_content(self, filename, content):
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
Expand All @@ -173,12 +181,12 @@ def source_file(self):
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]
Expand Down Expand Up @@ -275,7 +283,7 @@ def _default_cache_to(self, instance, path, specname, extension):
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)
Expand Down Expand Up @@ -303,12 +311,12 @@ def name(self):
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
Expand All @@ -317,7 +325,8 @@ def __get__(self, instance, owner):
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

Expand All @@ -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
Expand All @@ -365,14 +374,14 @@ def __init__(self, processors=None, format=None, options={},
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)
Expand Down
2 changes: 1 addition & 1 deletion imagekit/processors/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -186,7 +186,7 @@ def process(self, img):
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``.
Expand Down
12 changes: 6 additions & 6 deletions tests/core/tests.py
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@

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
Expand All @@ -18,13 +18,13 @@
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):
Expand Down

0 comments on commit c3ef517

Please sign in to comment.