Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
11 changes: 4 additions & 7 deletions .travis.yml
Original file line number Diff line number Diff line change
@@ -1,32 +1,29 @@
language: python
sudo: false
python:
- "2.6"
- "2.7"
- "3.2"
- "3.3"
- "3.4"
- "pypy"
- "pypy3"
env:
- DJANGO="<1.6,>=1.5"
- DJANGO="<1.7,>=1.6"
- DJANGO="<1.8,>=1.7"
- DJANGO="<1.9,>=1.8"

matrix:
allow_failures:
- env: DJANGO="<1.6,>=1.5"
- env: DJANGO="<1.7,>=1.6"
- python: "2.6"
- python: "3.2"
install:
- pip install --upgrade pip
- pip install -U pip
- pip install .
- pip install Django$DJANGO
- pip install pytest pytest-pep8 pytest-flakes
- pip install -U pytest pytest-pep8 pytest-flakes pytest-isort pep257
- pip install coveralls
script:
coverage run --source=stdimage runtests.py
- coverage run --source=stdimage runtests.py
- pep257 stdimage
after_success:
coveralls
1 change: 0 additions & 1 deletion README.rst
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,6 @@ Django Field that implement the following features:

* Django-Storages compatible (S3)
* Python 2, 3 and PyPy support
* Django 1.5 and later support
* Resize images to different sizes
* Access thumbnails on model level, no template tags required
* Preserves original image
Expand Down
2 changes: 1 addition & 1 deletion pytest.ini
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
[pytest]
norecursedirs=venv
DJANGO_SETTINGS_MODULE=tests.settings
addopts = --tb=short --pep8 --flakes -rxs
addopts = --tb=short --pep8 --isort --flakes -rxs
pep8ignore=
setup.py ALL
runtests.py ALL
Expand Down
6 changes: 6 additions & 0 deletions setup.cfg
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
[pep257]
verbose = true
explain = true
source = true
count = true
ignore = D100,D101,D102,D103
3 changes: 1 addition & 2 deletions stdimage/management/commands/rendervariations.py
Original file line number Diff line number Diff line change
Expand Up @@ -76,14 +76,13 @@ def init_progressbar(count):


def finish_progressbar():
global BAR
BAR.finish()


def render_field_variations(kwargs):
try:
global BAR
render_variations(**kwargs)
global BAR
BAR += 1
except:
raise Exception("".join(traceback.format_exception(*sys.exc_info())))
54 changes: 28 additions & 26 deletions stdimage/models.py
Original file line number Diff line number Diff line change
Expand Up @@ -18,20 +18,17 @@


class StdImageFileDescriptor(ImageFileDescriptor):
"""
The variation property of the field should be accessible in instance cases

"""
"""The variation property of the field is accessible in instance cases."""

def __set__(self, instance, value):
super(StdImageFileDescriptor, self).__set__(instance, value)
self.field.set_variations(instance)


class StdImageFieldFile(ImageFieldFile):
"""
Like ImageFieldFile but handles variations.
"""

"""Like ImageFieldFile but handles variations."""

def save(self, name, content, save=True):
super(StdImageFieldFile, self).save(name, content, save)
Expand All @@ -57,18 +54,14 @@ def is_smaller(img, variation):
or img.size[1] > variation['height']

def render_variations(self, replace=False):
"""
Renders all image variations and saves them to the storage
"""
for key, variation in self.field.variations.items():
"""Render all image variations and saves them to the storage."""
for _, variation in self.field.variations.items():
self.render_variation(self.name, variation, replace, self.storage)

@classmethod
def render_variation(cls, file_name, variation, replace=False,
storage=DefaultStorage()):
"""
Renders an image variation and saves it to the storage
"""
"""Render an image variation and saves it to the storage."""
variation_name = cls.get_variation_name(file_name, variation['name'])
if storage.exists(variation_name):
if replace:
Expand Down Expand Up @@ -118,10 +111,7 @@ def render_variation(cls, file_name, variation, replace=False,

@classmethod
def get_variation_name(cls, file_name, variation_name):
"""
Returns the variation file name based on the model
it's field and it's variation.
"""
"""Return the variation file name based on the variation."""
ext = cls.get_file_extension(file_name)
path = file_name.rsplit('/', 1)[0]
file_name = file_name.rsplit('/', 1)[-1].rsplit('.', 1)[0]
Expand All @@ -134,9 +124,7 @@ def get_variation_name(cls, file_name, variation_name):

@staticmethod
def get_file_extension(filename):
"""
Returns the file extension.
"""
"""Return the file extension."""
return os.path.splitext(filename)[1].lower()

def delete(self, save=True):
Expand All @@ -150,13 +138,25 @@ def delete_variations(self):


class StdImageField(ImageField):

"""
Django field that behaves as ImageField, with some extra features like:
- Auto resizing
- Allow image deletion
Django ImageField that is able to create different size variations.

Extra features are:
- Django-Storages compatible (S3)
- Python 2, 3 and PyPy support
- Django 1.5 and later support
- Resize images to different sizes
- Access thumbnails on model level, no template tags required
- Preserves original image
- Asynchronous rendering (Celery & Co)
- Multi threading and processing for optimum performance
- Restrict accepted image dimensions
- Rename files to a standardized name (using a callable upload_to)

:param variations: size variations of the image
"""

descriptor_class = StdImageFileDescriptor
attr_class = StdImageFieldFile
def_variation = {
Expand All @@ -170,7 +170,8 @@ def __init__(self, verbose_name=None, name=None, variations=None,
render_variations=True, force_min_size=False,
*args, **kwargs):
"""
Standardized ImageField for Django
Standardized ImageField for Django.

Usage: StdImageField(upload_to='PATH',
variations={'thumbnail': {"width", "height", "crop", "resample"}})
:param variations: size variations of the image
Expand Down Expand Up @@ -222,7 +223,8 @@ def add_variation(self, name, params):

def set_variations(self, instance=None, **kwargs):
"""
Creates a "variation" object as attribute of the ImageField instance.
Create a "variation" object as attribute of the ImageField instance.

Variation attribute will be of the same class as the original image, so
"path", "url"... properties can be used

Expand All @@ -242,7 +244,7 @@ def set_variations(self, instance=None, **kwargs):
setattr(field, name, variation_field)

def contribute_to_class(self, cls, name):
"""Call methods for generating all operations on specified signals"""
"""Generating all operations on specified signals."""
super(StdImageField, self).contribute_to_class(cls, name)
signals.post_init.connect(self.set_variations, sender=cls)

Expand Down
4 changes: 1 addition & 3 deletions stdimage/utils.py
Original file line number Diff line number Diff line change
Expand Up @@ -88,9 +88,7 @@ def pre_save_delete_callback(sender, instance, **kwargs):

def render_variations(file_name, variations, replace=False,
storage=DefaultStorage()):
"""
Renders all variations for a given field.
"""
"""Render all variations for a given field."""
for key, variation in variations.items():
StdImageFieldFile.render_variation(
file_name, variation, replace, storage
Expand Down
10 changes: 7 additions & 3 deletions stdimage/validators.py
Original file line number Diff line number Diff line change
Expand Up @@ -10,9 +10,9 @@


class BaseSizeValidator(BaseValidator):
"""
Base validator that validates the size of an image.
"""

"""Base validator that validates the size of an image."""

compare = lambda self, x: True

def __init__(self, width, height):
Expand All @@ -36,11 +36,13 @@ def clean(value):


class MaxSizeValidator(BaseSizeValidator):

"""
ImageField validator to validate the max with and height of an image.

You may use float("inf") as an infinite boundary.
"""

compare = lambda self, img_size, max_size:\
img_size[0] > max_size[0] or img_size[1] > max_size[1]
message = _('The image you uploaded is too large.'
Expand All @@ -50,11 +52,13 @@ class MaxSizeValidator(BaseSizeValidator):


class MinSizeValidator(BaseSizeValidator):

"""
ImageField validator to validate the min with and height of an image.

You may use float("inf") as an infinite boundary.
"""

compare = lambda self, img_size, min_size:\
img_size[0] < min_size[0] or img_size[1] < min_size[1]
message = _('The image you uploaded is too small.'
Expand Down