From 4b611228337e66fbd3b999c7d7dc3d4644b7fff2 Mon Sep 17 00:00:00 2001 From: Johannes Hoppe Date: Thu, 3 Dec 2015 19:47:51 +0100 Subject: [PATCH] Upgrade ci and package for django 1.9 --- .pre-commit-config.yaml | 6 ++-- .travis.yml | 11 ++---- README.rst | 1 - setup.py | 29 +++------------ .../management/commands/rendervariations.py | 36 ++++++------------- stdimage/models.py | 9 ++--- stdimage/utils.py | 4 +-- tests/test_models.py | 23 ++++++++---- 8 files changed, 46 insertions(+), 73 deletions(-) diff --git a/.pre-commit-config.yaml b/.pre-commit-config.yaml index 05a5879..36af530 100644 --- a/.pre-commit-config.yaml +++ b/.pre-commit-config.yaml @@ -1,5 +1,5 @@ - repo: git@github.com:pre-commit/pre-commit-hooks - sha: 29bf11d13689a0a9a895c41eb3591c7e942d377d + sha: e306ff3b7d0d9a6fc7d128ef9ca2e0b6e6e76e8f hooks: - id: trailing-whitespace - id: end-of-file-fixer @@ -13,13 +13,13 @@ args: - requirements-dev.txt - repo: git://github.com/FalconSocial/pre-commit-mirrors-pep257 - sha: 67c970e89857fdcebcd59ace94950a3331985a3b + sha: ebb1b1bb080b0c960bcf37cf81d09185cec4fc6d hooks: - id: pep257 args: - --explain - --ignore=D100,D101,D102,D103,D104,D105,D203 - repo: git://github.com/FalconSocial/pre-commit-python-sorter - sha: 934072fb29303aaa64bead610be042049e9db488 + sha: ec01d99f48a0dabb2ebbb2675139e2cc0fe2aa93 hooks: - id: python-import-sorter diff --git a/.travis.yml b/.travis.yml index 71fef7b..85c7ba8 100644 --- a/.travis.yml +++ b/.travis.yml @@ -1,23 +1,18 @@ language: python sudo: false -cache: - - pip +cache: pip python: - "2.7" - - "3.3" - "3.4" - "3.5" - - "pypy" - - "pypy3" env: matrix: - - DJANGO="Django<1.8,>=1.7" - DJANGO="Django<1.9,>=1.8" + - DJANGO="Django<1.10,>=1.9" - DJANGO="-e git+https://github.com/django/django.git@master#egg=Django" matrix: fast_finish: true allow_failures: - - python: "3.5" - env: DJANGO="-e git+https://github.com/django/django.git@master#egg=Django" install: - pip install --upgrade pip @@ -28,6 +23,6 @@ script: - isort --check-only --recursive --diff . - flake8 --jobs=2 . - pep257 --verbose --explain --source --count stdimage - - coverage run --source=stdimage runtests.py + - coverage run --source=stdimage -m 'pytest' after_success: - coveralls diff --git a/README.rst b/README.rst index f40909b..1849efc 100644 --- a/README.rst +++ b/README.rst @@ -29,7 +29,6 @@ Django Standarized Image Field Django Field that implement the following features: * Django-Storages compatible (S3) -* Python 2, 3 and PyPy support * Resize images to different sizes * Access thumbnails on model level, no template tags required * Preserves original image diff --git a/setup.py b/setup.py index 3765c05..0d89b65 100755 --- a/setup.py +++ b/setup.py @@ -1,24 +1,6 @@ #!/usr/bin/env python # -*- coding: utf-8 -*- -from setuptools import Command, find_packages, setup - - -class PyTest(Command): - user_options = [] - - def initialize_options(self): - pass - - def finalize_options(self): - pass - - def run(self): - import sys - import subprocess - - errno = subprocess.call([sys.executable, 'runtests.py']) - raise SystemExit(errno) - +from setuptools import find_packages, setup setup( name='django-stdimage', @@ -39,13 +21,13 @@ def run(self): 'Programming Language :: Python', 'Topic :: Software Development', 'Programming Language :: Python :: 2', - 'Programming Language :: Python :: 2.6', 'Programming Language :: Python :: 2.7', 'Programming Language :: Python :: 3', - 'Programming Language :: Python :: 3.2', - 'Programming Language :: Python :: 3.3', 'Programming Language :: Python :: 3.4', - 'Programming Language :: Python :: Implementation :: PyPy', + 'Programming Language :: Python :: 3.5', + 'Framework :: Django', + 'Framework :: Django :: 1.8', + 'Framework :: Django :: 1.9', ], packages=find_packages(exclude=[ "*.tests", "*.tests.*", "tests.*", "tests", ".egg-info" @@ -55,5 +37,4 @@ def run(self): 'pillow>=2.5', 'progressbar2>=3.0.0', ], - cmdclass={'test': PyTest}, ) diff --git a/stdimage/management/commands/rendervariations.py b/stdimage/management/commands/rendervariations.py index e82e199..e1c4eb0 100644 --- a/stdimage/management/commands/rendervariations.py +++ b/stdimage/management/commands/rendervariations.py @@ -7,15 +7,19 @@ from multiprocessing import Pool, cpu_count import progressbar +from django.apps import apps +from django.core.files.storage import get_storage_class from django.core.management import BaseCommand -from django.db.models import get_model from stdimage.utils import render_variations -is_pypy = '__pypy__' in sys.builtin_module_names BAR = None +def class_to_path(cls): + return '.'.join((cls.__module__, cls.__class__.__name__)) + + class MemoryUsageWidget(progressbar.widgets.WidgetBase): def __call__(self, progress, data): return 'RAM: {0:10.1f} MB'.format( @@ -38,7 +42,7 @@ def handle(self, *args, **options): replace = options.get('replace') for route in args: app_label, model_name, field_name = route.rsplit('.') - model_class = get_model(app_label, model_name) + model_class = apps.get_model(app_label, model_name) field = model_class._meta.get_field(field_name) queryset = model_class._default_manager \ @@ -47,13 +51,10 @@ def handle(self, *args, **options): images = queryset.values_list(field_name, flat=True).iterator() count = queryset.count() - if is_pypy: # pypy doesn't handle multiprocessing to well - self.render_linear(field, images, count, replace) - else: - self.render_in_parallel(field, images, count, replace) + self.render(field, images, count, replace) @staticmethod - def render_in_parallel(field, images, count, replace): + def render(field, images, count, replace): pool = Pool( initializer=init_progressbar, initargs=[count] @@ -63,7 +64,7 @@ def render_in_parallel(field, images, count, replace): file_name=file_name, variations=field.variations, replace=replace, - storage=field.storage + storage=class_to_path(field.storage), ) for file_name in images ] @@ -72,22 +73,6 @@ def render_in_parallel(field, images, count, replace): pool.close() pool.join() - @staticmethod - def render_linear(field, images, count, replace): - init_progressbar(count) - args_list = [ - dict( - file_name=file_name, - variations=field.variations, - replace=replace, - storage=field.storage - ) - for file_name in images - ] - for args in args_list: - render_variations(**args) - finish_progressbar() - def init_progressbar(count): global BAR @@ -107,6 +92,7 @@ def finish_progressbar(): def render_field_variations(kwargs): try: + kwargs['storage'] = get_storage_class(kwargs['storage'])() render_variations(**kwargs) global BAR BAR += 1 diff --git a/stdimage/models.py b/stdimage/models.py index a72af9f..515a8b5 100644 --- a/stdimage/models.py +++ b/stdimage/models.py @@ -6,10 +6,11 @@ from io import BytesIO from django.core.files.base import ContentFile -from django.core.files.storage import DefaultStorage +from django.core.files.storage import default_storage from django.db.models import signals -from django.db.models.fields.files import (ImageField, ImageFieldFile, - ImageFileDescriptor) +from django.db.models.fields.files import ( + ImageField, ImageFieldFile, ImageFileDescriptor +) from PIL import Image, ImageOps from .validators import MinSizeValidator @@ -58,7 +59,7 @@ def render_variations(self, replace=False): @classmethod def render_variation(cls, file_name, variation, replace=False, - storage=DefaultStorage()): + storage=default_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): diff --git a/stdimage/utils.py b/stdimage/utils.py index d00e99b..9e60d58 100644 --- a/stdimage/utils.py +++ b/stdimage/utils.py @@ -4,7 +4,7 @@ import os import uuid -from django.core.files.storage import DefaultStorage +from django.core.files.storage import default_storage from django.utils.text import slugify from .models import StdImageField, StdImageFieldFile @@ -89,7 +89,7 @@ def pre_save_delete_callback(sender, instance, **kwargs): def render_variations(file_name, variations, replace=False, - storage=DefaultStorage()): + storage=default_storage): """Render all variations for a given field.""" for key, variation in variations.items(): StdImageFieldFile.render_variation( diff --git a/tests/test_models.py b/tests/test_models.py index 1481831..79f8ce3 100644 --- a/tests/test_models.py +++ b/tests/test_models.py @@ -13,6 +13,7 @@ class UUID4Monkey(object): uuid.__dict__['uuid4'] = lambda: UUID4Monkey() +import django # NoQA from django.conf import settings # NoQA from django.core.files import File # NoQA from django.test import TestCase # NoQA @@ -174,9 +175,14 @@ def test_pre_save_delete_callback_clear(self): AdminDeleteModel.objects.create( image=self.fixtures['100.gif'] ) - self.client.post('/admin/tests/admindeletemodel/1/', { - 'image-clear': 'checked', - }) + if django.VERSION >= (1, 9): + self.client.post('/admin/tests/admindeletemodel/1/change/', { + 'image-clear': 'checked', + }) + else: + self.client.post('/admin/tests/admindeletemodel/1/', { + 'image-clear': 'checked', + }) self.assertFalse( os.path.exists(os.path.join(IMG_DIR, 'image.gif')) ) @@ -185,9 +191,14 @@ def test_pre_save_delete_callback_new(self): AdminDeleteModel.objects.create( image=self.fixtures['100.gif'] ) - self.client.post('/admin/tests/admindeletemodel/1/', { - 'image': self.fixtures['600x400.jpg'], - }) + if django.VERSION >= (1, 9): + self.client.post('/admin/tests/admindeletemodel/1/change/', { + 'image': self.fixtures['600x400.jpg'], + }) + else: + self.client.post('/admin/tests/admindeletemodel/1/', { + 'image': self.fixtures['600x400.jpg'], + }) self.assertFalse( os.path.exists(os.path.join(IMG_DIR, 'image.gif')) )