From 18cba0964a852555fd8749d487d258e6e20f6759 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Thu, 4 Mar 2021 17:44:14 +0000 Subject: [PATCH 01/98] Update actions/checkout requirement to v2.3.4 Updates the requirements on [actions/checkout](https://github.com/actions/checkout) to permit the latest version. - [Release notes](https://github.com/actions/checkout/releases) - [Changelog](https://github.com/actions/checkout/blob/main/CHANGELOG.md) - [Commits](https://github.com/actions/checkout/commits/5a4ac9002d0be2fb38bd78e4b4dbde5606d7042f) Signed-off-by: dependabot[bot] --- .github/workflows/release.yml | 2 +- .github/workflows/tests.yml | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml index 02fcd4c..ca6481e 100644 --- a/.github/workflows/release.yml +++ b/.github/workflows/release.yml @@ -7,7 +7,7 @@ jobs: runs-on: ubuntu-latest steps: - - uses: actions/checkout@v1 + - uses: actions/checkout@v2.3.4 - name: Set up Python ${{ matrix.python-version }} uses: actions/setup-python@v1 with: diff --git a/.github/workflows/tests.yml b/.github/workflows/tests.yml index 026496f..1941385 100644 --- a/.github/workflows/tests.yml +++ b/.github/workflows/tests.yml @@ -15,7 +15,7 @@ jobs: run: sudo apt-get install gettext -y - uses: actions/setup-python@v2 - run: python -m pip install --upgrade pip setuptools wheel twine readme-renderer - - uses: actions/checkout@v2 + - uses: actions/checkout@v2.3.4 - run: python setup.py sdist bdist_wheel - run: python -m twine check dist/* @@ -35,7 +35,7 @@ jobs: uses: actions/setup-python@v1 with: python-version: ${{ matrix.python-version }} - - uses: actions/checkout@v1 + - uses: actions/checkout@v2.3.4 - name: Install dependencies run: | python -m pip install --upgrade pip setuptools codecov From a99cb529c01000b12682043509a9bb49645be60e Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Thu, 4 Mar 2021 17:44:14 +0000 Subject: [PATCH 02/98] Update actions/setup-python requirement to v2.2.1 Updates the requirements on [actions/setup-python](https://github.com/actions/setup-python) to permit the latest version. - [Release notes](https://github.com/actions/setup-python/releases) - [Commits](https://github.com/actions/setup-python/commits/3105fb18c05ddd93efea5f9e0bef7a03a6e9e7df) Signed-off-by: dependabot[bot] --- .github/workflows/release.yml | 2 +- .github/workflows/tests.yml | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml index ca6481e..01f8ace 100644 --- a/.github/workflows/release.yml +++ b/.github/workflows/release.yml @@ -9,7 +9,7 @@ jobs: steps: - uses: actions/checkout@v2.3.4 - name: Set up Python ${{ matrix.python-version }} - uses: actions/setup-python@v1 + uses: actions/setup-python@v2.2.1 with: python-version: ${{ matrix.python-version }} - name: Install gettext diff --git a/.github/workflows/tests.yml b/.github/workflows/tests.yml index 1941385..865794d 100644 --- a/.github/workflows/tests.yml +++ b/.github/workflows/tests.yml @@ -13,7 +13,7 @@ jobs: steps: - name: Install gettext run: sudo apt-get install gettext -y - - uses: actions/setup-python@v2 + - uses: actions/setup-python@v2.2.1 - run: python -m pip install --upgrade pip setuptools wheel twine readme-renderer - uses: actions/checkout@v2.3.4 - run: python setup.py sdist bdist_wheel @@ -32,7 +32,7 @@ jobs: - "3.1" steps: - name: Set up Python ${{ matrix.python-version }} - uses: actions/setup-python@v1 + uses: actions/setup-python@v2.2.1 with: python-version: ${{ matrix.python-version }} - uses: actions/checkout@v2.3.4 From e981a6d67c4e6477d04adb7ab02d422269256cf8 Mon Sep 17 00:00:00 2001 From: Christopher Banck Date: Fri, 26 Mar 2021 09:17:13 +0100 Subject: [PATCH 03/98] Fix #224 -- delete_orphans independent from blank (#225) --- stdimage/models.py | 2 +- tests/admin.py | 1 + tests/models.py | 12 ++++++++++++ tests/test_models.py | 23 +++++++++++++++++++---- 4 files changed, 33 insertions(+), 5 deletions(-) diff --git a/stdimage/models.py b/stdimage/models.py index e1528b6..d479f5f 100644 --- a/stdimage/models.py +++ b/stdimage/models.py @@ -284,7 +284,7 @@ def validate(self, value, model_instance): MinSizeValidator(self.min_size[0], self.min_size[1])(value) def save_form_data(self, instance, data): - if self.delete_orphans and self.blank and (data is False or data is not None): + if self.delete_orphans and (data is False or data is not None): file = getattr(instance, self.name) if file and file._committed and file != data: file.delete(save=False) diff --git a/tests/admin.py b/tests/admin.py index 0abab8b..da8f70a 100644 --- a/tests/admin.py +++ b/tests/admin.py @@ -3,6 +3,7 @@ from . import models admin.site.register(models.AdminDeleteModel) +admin.site.register(models.AdminUpdateModel) admin.site.register(models.ResizeCropModel) admin.site.register(models.ResizeModel) admin.site.register(models.SimpleModel) diff --git a/tests/models.py b/tests/models.py index 34a4255..4b294f7 100644 --- a/tests/models.py +++ b/tests/models.py @@ -30,6 +30,18 @@ class AdminDeleteModel(models.Model): ) +class AdminUpdateModel(models.Model): + """can be updated through admin, image not optional""" + image = StdImageField( + upload_to=upload_to, + variations={ + 'thumbnail': (100, 75), + }, + blank=False, + delete_orphans=True, + ) + + class ResizeModel(models.Model): """resizes image to maximum size to fit a 640x480 area""" image = StdImageField( diff --git a/tests/test_models.py b/tests/test_models.py index f681e7a..ed1b2d0 100644 --- a/tests/test_models.py +++ b/tests/test_models.py @@ -9,8 +9,8 @@ from PIL import Image from . import models -from .models import (AdminDeleteModel, CustomRenderVariationsModel, ResizeCropModel, - ResizeModel, SimpleModel, ThumbnailModel, +from .models import (AdminDeleteModel, AdminUpdateModel, CustomRenderVariationsModel, + ResizeCropModel, ResizeModel, SimpleModel, ThumbnailModel, ThumbnailWithoutDirectoryModel, UtilVariationsModel,) IMG_DIR = os.path.join(settings.MEDIA_ROOT, 'img') @@ -198,13 +198,28 @@ def test_pre_save_delete_callback_clear(self, admin_client): assert not os.path.exists(path) def test_pre_save_delete_callback_new(self, admin_client): - AdminDeleteModel.objects.create( + obj = AdminDeleteModel.objects.create( image=self.fixtures['100.gif'] ) + path = obj.image.path + assert os.path.exists(path) admin_client.post('/admin/tests/admindeletemodel/1/change/', { 'image': self.fixtures['600x400.jpg'], }) - assert not os.path.exists(os.path.join(IMG_DIR, 'image.gif')) + assert not os.path.exists(path) + assert os.path.exists(os.path.join(IMG_DIR, '600x400.jpg')) + + def test_pre_save_delete_callback_update(self, admin_client): + obj = AdminUpdateModel.objects.create( + image=self.fixtures['100.gif'] + ) + path = obj.image.path + assert os.path.exists(path) + admin_client.post('/admin/tests/adminupdatemodel/1/change/', { + 'image': self.fixtures['600x400.jpg'], + }) + assert not os.path.exists(path) + assert os.path.exists(os.path.join(IMG_DIR, '600x400.jpg')) def test_render_variations_callback(self, db): obj = UtilVariationsModel.objects.create(image=self.fixtures['100.gif']) From 2606fd22fbcd6145bd686d22b5ee973749c9668c Mon Sep 17 00:00:00 2001 From: Johannes Maron Date: Fri, 26 Mar 2021 09:29:09 +0100 Subject: [PATCH 04/98] Update package and CI setup --- .fussyfox.yml | 4 -- .github/dependabot.yml | 4 ++ .github/workflows/ci.yml | 103 ++++++++++++++++++++++++++++++++++++ .github/workflows/tests.yml | 45 ---------------- MANIFEST.in | 1 + lint-requirements.txt | 6 +++ setup.cfg | 19 +++---- setup.py | 39 +++++++------- 8 files changed, 142 insertions(+), 79 deletions(-) delete mode 100644 .fussyfox.yml create mode 100644 .github/workflows/ci.yml delete mode 100644 .github/workflows/tests.yml create mode 100644 lint-requirements.txt diff --git a/.fussyfox.yml b/.fussyfox.yml deleted file mode 100644 index 600df19..0000000 --- a/.fussyfox.yml +++ /dev/null @@ -1,4 +0,0 @@ -- bandit -- flake8 -- isort -- pydocstyle diff --git a/.github/dependabot.yml b/.github/dependabot.yml index 71607d0..d232a23 100644 --- a/.github/dependabot.yml +++ b/.github/dependabot.yml @@ -1,5 +1,9 @@ version: 2 updates: +- package-ecosystem: pip + directory: "/" + schedule: + interval: daily - package-ecosystem: github-actions directory: "/" schedule: diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml new file mode 100644 index 0000000..ad1748b --- /dev/null +++ b/.github/workflows/ci.yml @@ -0,0 +1,103 @@ +name: CI + +on: + push: + branches: + - master + pull_request: + +jobs: + + analyze: + name: CodeQL + runs-on: ubuntu-latest + steps: + - name: Checkout repository + uses: actions/checkout@v2 + - name: Initialize CodeQL + uses: github/codeql-action/init@v1 + with: + languages: python + - name: Perform CodeQL Analysis + uses: github/codeql-action/analyze@v1 + + msgcheck: + runs-on: ubuntu-latest + steps: + - uses: actions/setup-python@v2 + - uses: actions/checkout@v2 + - run: sudo apt install -y gettext aspell libenchant-dev + - uses: actions/cache@v2.1.4 + with: + path: ~/.cache/pip + key: ${{ runner.os }}-pip-${{ hashFiles('lint-requirements.txt') }} + restore-keys: | + ${{ runner.os }}-pip- + - run: python -m pip install -r lint-requirements.txt + - run: msgcheck -n stdimage/locale/*/LC_MESSAGES/*.po + + lint: + strategy: + fail-fast: false + matrix: + lint-command: + - "bandit -r . -x ./tests" + - "black --check --diff ." + - "flake8 ." + - "isort --check-only --diff ." + - "pydocstyle ." + runs-on: ubuntu-latest + steps: + - uses: actions/setup-python@v2 + - uses: actions/checkout@v2 + - uses: actions/cache@v2.1.4 + with: + path: ~/.cache/pip + key: ${{ runner.os }}-pip-${{ hashFiles('lint-requirements.txt') }} + restore-keys: | + ${{ runner.os }}-pip- + - run: python -m pip install -r lint-requirements.txt + - run: ${{ matrix.lint-command }} + + + dist: + runs-on: ubuntu-latest + steps: + - name: Install gettext + run: sudo apt-get install gettext -y + - uses: actions/setup-python@v2.2.1 + - run: python -m pip install --upgrade pip setuptools wheel twine readme-renderer + - uses: actions/checkout@v2.3.4 + - run: python setup.py sdist bdist_wheel + - run: python -m twine check dist/* + - uses: actions/upload-artifact@v2 + with: + path: dist/* + + pytest: + runs-on: ubuntu-latest + needs: + - lint + - msgcheck + strategy: + matrix: + python-version: + - "3.7" + - "3.8" + - "3.9" + django-version: + - "2.2" + - "3.1" + steps: + - name: Set up Python ${{ matrix.python-version }} + uses: actions/setup-python@v2.2.1 + with: + python-version: ${{ matrix.python-version }} + - uses: actions/checkout@v2.3.4 + - name: Install dependencies + run: | + python -m pip install --upgrade pip setuptools codecov + pip install django~=${{ matrix.django-version }} + - name: Test with pytest + run: python setup.py test + - run: codecov diff --git a/.github/workflows/tests.yml b/.github/workflows/tests.yml deleted file mode 100644 index 865794d..0000000 --- a/.github/workflows/tests.yml +++ /dev/null @@ -1,45 +0,0 @@ -name: CI - -on: - push: - branches: - - master - pull_request: - -jobs: - - dist: - runs-on: ubuntu-latest - steps: - - name: Install gettext - run: sudo apt-get install gettext -y - - uses: actions/setup-python@v2.2.1 - - run: python -m pip install --upgrade pip setuptools wheel twine readme-renderer - - uses: actions/checkout@v2.3.4 - - run: python setup.py sdist bdist_wheel - - run: python -m twine check dist/* - - pytest: - runs-on: ubuntu-latest - strategy: - matrix: - python-version: - - "3.7" - - "3.8" - - "3.9" - django-version: - - "2.2" - - "3.1" - steps: - - name: Set up Python ${{ matrix.python-version }} - uses: actions/setup-python@v2.2.1 - with: - python-version: ${{ matrix.python-version }} - - uses: actions/checkout@v2.3.4 - - name: Install dependencies - run: | - python -m pip install --upgrade pip setuptools codecov - pip install django~=${{ matrix.django-version }} - - name: Test with pytest - run: python setup.py test - - run: codecov diff --git a/MANIFEST.in b/MANIFEST.in index 6f39718..8fb7fc9 100644 --- a/MANIFEST.in +++ b/MANIFEST.in @@ -3,3 +3,4 @@ include stdimage/locale/*/LC_MESSAGES/django.mo prune tests prune .github exclude .* +exclude lint-requirements.txt diff --git a/lint-requirements.txt b/lint-requirements.txt new file mode 100644 index 0000000..296bfa6 --- /dev/null +++ b/lint-requirements.txt @@ -0,0 +1,6 @@ +bandit==1.7.0 +black==20.8b1 +flake8==3.9.0 +isort==5.7.0 +msgcheck==3.1 +pydocstyle==6.0.0 diff --git a/setup.cfg b/setup.cfg index 4255691..b968058 100644 --- a/setup.cfg +++ b/setup.cfg @@ -20,7 +20,14 @@ classifier = Topic :: Software Development Programming Language :: Python :: 3 Programming Language :: Python :: 3 :: Only + Programming Language :: Python :: 3.7 + Programming Language :: Python :: 3.8 + Programming Language :: Python :: 3.9 Framework :: Django + Framework :: Django :: 2.2 + Framework :: Django :: 3.1 + +python_requires = >=3.7 [options] include_package_data = True @@ -53,17 +60,7 @@ test = pytest [tool:pytest] norecursedirs=venv env .eggs DJANGO_SETTINGS_MODULE=tests.settings -addopts = --cov=stdimage --cov-report xml --tb=short -rxs --nomigrations - -[tox:tox] -envlist = py{36,37}-dj{111,22,master} - -[testenv] -deps = - dj111: https://github.com/django/django/archive/stable/1.11.x.tar.gz#egg=django - dj22: https://github.com/django/django/archive/stable/2.2.x.tar.gz#egg=django - djmaster: https://github.com/django/django/archive/master.tar.gz#egg=django -commands = python setup.py test +addopts = --cov=stdimage --nomigrations [flake8] max-line-length = 88 diff --git a/setup.py b/setup.py index abf1228..a4d818b 100755 --- a/setup.py +++ b/setup.py @@ -5,53 +5,54 @@ import subprocess # nosec from distutils.cmd import Command from distutils.command.build import build as _build +from distutils.command.install import install as _install from setuptools import setup -from setuptools.command.install_lib import install_lib as _install_lib BASE_DIR = os.path.dirname((os.path.abspath(__file__))) class compile_translations(Command): - description = 'Compile i18n translations using gettext.' + description = "Compile i18n translations using gettext." user_options = [] def initialize_options(self): - pass + self.build_lib = None def finalize_options(self): - pass + self.set_undefined_options("build", ("build_lib", "build_lib")) def run(self): - pattern = 'stdimage/locale/*/LC_MESSAGES/django.po' + pattern = "stdimage/locale/*/LC_MESSAGES/django.po" for file in glob.glob(pattern): - cmd = ['msgfmt', '-c'] name, ext = os.path.splitext(file) - - cmd += ['-o', '%s.mo' % name] - cmd += ['%s.po' % name] + cmd = ["msgfmt", "-c", "-o", f"{self.build_lib}/{name}.mo", file] self.announce( - 'running command: %s' % ' '.join(cmd), - level=distutils.log.INFO) + "running command: %s" % " ".join(cmd), level=distutils.log.INFO + ) subprocess.check_call(cmd, cwd=BASE_DIR) # nosec class build(_build): - sub_commands = [('compile_translations', None)] + _build.sub_commands + sub_commands = [ + *_build.sub_commands, + ("compile_translations", None), + ] -class install_lib(_install_lib): - def run(self): - self.run_command('compile_translations') - _install_lib.run(self) +class install(_install): + sub_commands = [ + *_install.sub_commands, + ("compile_translations", None), + ] setup( name='django-stdimage', use_scm_version=True, cmdclass={ - 'build': build, - 'install_lib': install_lib, - 'compile_translations': compile_translations, + "build": build, + "install": install, + "compile_translations": compile_translations, }, ) From bcd912252b63daa507f910c5a2d6ba1d74a25ed3 Mon Sep 17 00:00:00 2001 From: Johannes Maron Date: Fri, 26 Mar 2021 09:31:51 +0100 Subject: [PATCH 05/98] Add black code format --- setup.cfg | 22 ++- setup.py | 2 +- .../management/commands/rendervariations.py | 92 +++++---- stdimage/models.py | 183 ++++++++--------- stdimage/utils.py | 13 +- stdimage/validators.py | 26 ++- tests/conftest.py | 9 +- tests/forms.py | 3 +- tests/models.py | 71 +++---- tests/settings.py | 36 ++-- tests/test_commands.py | 85 +++----- tests/test_forms.py | 15 +- tests/test_models.py | 186 +++++++++--------- tests/test_utils.py | 16 +- tests/test_validators.py | 3 +- tests/urls.py | 2 +- 16 files changed, 376 insertions(+), 388 deletions(-) diff --git a/setup.cfg b/setup.cfg index b968058..cb1ab4e 100644 --- a/setup.cfg +++ b/setup.cfg @@ -62,16 +62,6 @@ norecursedirs=venv env .eggs DJANGO_SETTINGS_MODULE=tests.settings addopts = --cov=stdimage --nomigrations -[flake8] -max-line-length = 88 -statistics = true -show-source = true -exclude = */migrations/*,docs/*,env/*,venv/*,.tox/*,.eggs - -[pydocstyle] -add-ignore = D1 -match-dir = (?!tests|env|docs|\.).* - [coverage:run] source = . omit = @@ -84,10 +74,22 @@ omit = ignore_errors = True show_missing = True +[flake8] +max_line_length=88 +select = C,E,F,W,B,B950 +ignore = E203, E501, W503 + +[pydocstyle] +add-ignore = D1 +match-dir = (?!tests|env|docs|\.).* + [isort] atomic = true line_length = 88 known_first_party = stdimage, tests include_trailing_comma = True +multi_line_output = 3 +force_grid_wrap = 0 +use_parentheses = True default_section=THIRDPARTY combine_as_imports = true diff --git a/setup.py b/setup.py index a4d818b..e19500b 100755 --- a/setup.py +++ b/setup.py @@ -48,7 +48,7 @@ class install(_install): setup( - name='django-stdimage', + name="django-stdimage", use_scm_version=True, cmdclass={ "build": build, diff --git a/stdimage/management/commands/rendervariations.py b/stdimage/management/commands/rendervariations.py index 2ba3df3..07e5efb 100644 --- a/stdimage/management/commands/rendervariations.py +++ b/stdimage/management/commands/rendervariations.py @@ -7,44 +7,48 @@ class Command(BaseCommand): - help = 'Renders all variations of a StdImageField.' - args = '' + help = "Renders all variations of a StdImageField." + args = "" def add_arguments(self, parser): - parser.add_argument('field_path', - nargs='+', - type=str, - help='') - parser.add_argument('--replace', - action='store_true', - dest='replace', - default=False, - help='Replace existing files.') + parser.add_argument( + "field_path", nargs="+", type=str, help="" + ) + parser.add_argument( + "--replace", + action="store_true", + dest="replace", + default=False, + help="Replace existing files.", + ) - parser.add_argument('-i', '--ignore-missing', - action='store_true', - dest='ignore_missing', - default=False, - help='Ignore missing source file error and ' - 'skip render for that file') + parser.add_argument( + "-i", + "--ignore-missing", + action="store_true", + dest="ignore_missing", + default=False, + help="Ignore missing source file error and " "skip render for that file", + ) def handle(self, *args, **options): - replace = options.get('replace', False) - ignore_missing = options.get('ignore_missing', False) - routes = options.get('field_path', []) + replace = options.get("replace", False) + ignore_missing = options.get("ignore_missing", False) + routes = options.get("field_path", []) for route in routes: try: - app_label, model_name, field_name = route.rsplit('.') + app_label, model_name, field_name = route.rsplit(".") except ValueError: - raise CommandError("Error parsing field_path '{}'. Use format " - "." - .format(route)) + raise CommandError( + "Error parsing field_path '{}'. Use format " + ".".format(route) + ) model_class = apps.get_model(app_label, model_name) field = model_class._meta.get_field(field_name) - queryset = model_class._default_manager \ - .exclude(**{'%s__isnull' % field_name: True}) \ - .exclude(**{field_name: ''}) + queryset = model_class._default_manager.exclude( + **{"%s__isnull" % field_name: True} + ).exclude(**{field_name: ""}) obj = queryset.first() do_render = True if obj: @@ -53,8 +57,7 @@ def handle(self, *args, **options): images = queryset.values_list(field_name, flat=True).iterator() count = queryset.count() - self.render(field, images, count, replace, ignore_missing, - do_render) + self.render(field, images, count, replace, ignore_missing, do_render) @staticmethod def render(field, images, count, replace, ignore_missing, do_render): @@ -70,28 +73,35 @@ def render(field, images, count, replace, ignore_missing, do_render): ) for file_name in images ) - with progressbar.ProgressBar(max_value=count, widgets=( - progressbar.RotatingMarker(), - ' | ', progressbar.AdaptiveETA(), - ' | ', progressbar.Percentage(), - ' ', progressbar.Bar(), - )) as bar: + with progressbar.ProgressBar( + max_value=count, + widgets=( + progressbar.RotatingMarker(), + " | ", + progressbar.AdaptiveETA(), + " | ", + progressbar.Percentage(), + " ", + progressbar.Bar(), + ), + ) as bar: for _ in map(render_field_variations, kwargs_list): bar += 1 def render_field_variations(kwargs): - kwargs['storage'] = get_storage_class(kwargs['storage'])() - ignore_missing = kwargs.pop('ignore_missing') - do_render = kwargs.pop('do_render') + kwargs["storage"] = get_storage_class(kwargs["storage"])() + ignore_missing = kwargs.pop("ignore_missing") + do_render = kwargs.pop("do_render") try: if callable(do_render): - kwargs.pop('field_class') + kwargs.pop("field_class") do_render = do_render(**kwargs) if do_render: render_variations(**kwargs) except FileNotFoundError as e: if not ignore_missing: raise CommandError( - 'Source file was not found, terminating. ' - 'Use -i/--ignore-missing to skip this error.') from e + "Source file was not found, terminating. " + "Use -i/--ignore-missing to skip this error." + ) from e diff --git a/stdimage/models.py b/stdimage/models.py index d479f5f..2722ee8 100644 --- a/stdimage/models.py +++ b/stdimage/models.py @@ -5,8 +5,11 @@ from django.core.files.base import ContentFile 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, ImageFile, ImageOps from .validators import MinSizeValidator @@ -37,16 +40,15 @@ def save(self, name, content, save=True): if not isinstance(render_variations, bool): msg = ( '"render_variations" callable expects a boolean return value,' - ' but got %s' - ) % type(render_variations) + " but got %s" + ) % type(render_variations) raise TypeError(msg) if render_variations: self.render_variations() @staticmethod def is_smaller(img, variation): - return img.size[0] > variation['width'] \ - or img.size[1] > variation['height'] + return img.size[0] > variation["width"] or img.size[1] > variation["height"] def render_variations(self, replace=True): """Render all image variations and saves them to the storage.""" @@ -54,11 +56,12 @@ def render_variations(self, replace=True): self.render_variation(self.name, variation, replace, self.storage) @classmethod - def render_variation(cls, file_name, variation, replace=True, - storage=default_storage): + def render_variation( + cls, file_name, variation, replace=True, storage=default_storage + ): """Render an image variation and saves it to the storage.""" - variation_name = cls.get_variation_name(file_name, variation['name']) - file_overwrite = getattr(storage, 'file_overwrite', False) + variation_name = cls.get_variation_name(file_name, variation["name"]) + file_overwrite = getattr(storage, "file_overwrite", False) if not replace and storage.exists(variation_name): logger.info('File "%s" already exists.', variation_name) return variation_name @@ -83,47 +86,38 @@ def process_variation(cls, variation, image): """Process variation before actual saving.""" save_kargs = {} file_format = image.format - save_kargs['format'] = file_format + save_kargs["format"] = file_format - resample = variation['resample'] + resample = variation["resample"] if cls.is_smaller(image, variation): factor = 1 - while image.size[0] / factor \ - > 2 * variation['width'] \ - and image.size[1] * 2 / factor \ - > 2 * variation['height']: + while ( + image.size[0] / factor > 2 * variation["width"] + and image.size[1] * 2 / factor > 2 * variation["height"] + ): factor *= 2 if factor > 1: image.thumbnail( - (int(image.size[0] / factor), - int(image.size[1] / factor)), - resample=resample + (int(image.size[0] / factor), int(image.size[1] / factor)), + resample=resample, ) - size = variation['width'], variation['height'] - size = tuple(int(i) if i is not None else i - for i in size) + size = variation["width"], variation["height"] + size = tuple(int(i) if i is not None else i for i in size) - if file_format == 'JPEG': + if file_format == "JPEG": # http://stackoverflow.com/a/21669827 - image = image.convert('RGB') - save_kargs['optimize'] = True - save_kargs['quality'] = 'web_high' + image = image.convert("RGB") + save_kargs["optimize"] = True + save_kargs["quality"] = "web_high" if size[0] * size[1] > 10000: # roughly <10kb - save_kargs['progressive'] = True + save_kargs["progressive"] = True - if variation['crop']: - image = ImageOps.fit( - image, - size, - method=resample - ) + if variation["crop"]: + image = ImageOps.fit(image, size, method=resample) else: - image.thumbnail( - size, - resample=resample - ) + image.thumbnail(size, resample=resample) return image, save_kargs @@ -132,11 +126,13 @@ def get_variation_name(cls, file_name, variation_name): """Return the variation file name based on the variation.""" path, ext = os.path.splitext(file_name) path, file_name = os.path.split(path) - file_name = '{file_name}.{variation_name}{extension}'.format(**{ - 'file_name': file_name, - 'variation_name': variation_name, - 'extension': ext, - }) + file_name = "{file_name}.{variation_name}{extension}".format( + **{ + "file_name": file_name, + "variation_name": variation_name, + "extension": ext, + } + ) return os.path.join(path, file_name) def delete(self, save=True): @@ -168,15 +164,22 @@ class StdImageField(ImageField): descriptor_class = StdImageFileDescriptor attr_class = StdImageFieldFile def_variation = { - 'width': None, - 'height': None, - 'crop': False, - 'resample': Image.ANTIALIAS, + "width": None, + "height": None, + "crop": False, + "resample": Image.ANTIALIAS, } - def __init__(self, verbose_name=None, name=None, variations=None, - render_variations=True, force_min_size=False, delete_orphans=False, - **kwargs): + def __init__( + self, + verbose_name=None, + name=None, + variations=None, + render_variations=True, + force_min_size=False, + delete_orphans=False, + **kwargs + ): """ Standardized ImageField for Django. @@ -207,13 +210,12 @@ def __init__(self, verbose_name=None, name=None, variations=None, if not variations: variations = {} if not isinstance(variations, dict): - msg = ('"variations" expects a dict,' - ' but got %s') % type(variations) + msg = ('"variations" expects a dict,' " but got %s") % type(variations) raise TypeError(msg) - if not (isinstance(render_variations, bool) or - callable(render_variations)): - msg = ('"render_variations" excepts a boolean or callable,' - ' but got %s') % type(render_variations) + if not (isinstance(render_variations, bool) or callable(render_variations)): + msg = ( + '"render_variations" excepts a boolean or callable,' " but got %s" + ) % type(render_variations) raise TypeError(msg) self._variations = variations @@ -227,10 +229,8 @@ def __init__(self, verbose_name=None, name=None, variations=None, if self.variations and self.force_min_size: self.min_size = ( - max(self.variations.values(), - key=lambda x: x["width"])["width"], - max(self.variations.values(), - key=lambda x: x["height"])["height"] + max(self.variations.values(), key=lambda x: x["width"])["width"], + max(self.variations.values(), key=lambda x: x["height"])["height"], ) super().__init__(verbose_name=verbose_name, name=name, **kwargs) @@ -260,12 +260,9 @@ def set_variations(self, instance=None, **kwargs): if field._committed: for name, variation in list(self.variations.items()): variation_name = self.attr_class.get_variation_name( - field.name, - variation['name'] + field.name, variation["name"] ) - variation_field = ImageFieldFile(instance, - self, - variation_name) + variation_field = ImageFieldFile(instance, self, variation_name) setattr(field, name, variation_field) def post_delete_callback(self, sender, instance, **kwargs): @@ -292,65 +289,55 @@ def save_form_data(self, instance, data): class JPEGFieldFile(StdImageFieldFile): - @classmethod def get_variation_name(cls, file_name, variation_name): path = super().get_variation_name(file_name, variation_name) path, ext = os.path.splitext(path) - return '%s.jpeg' % path + return "%s.jpeg" % path @classmethod def process_variation(cls, variation, image): """Process variation before actual saving.""" save_kargs = {} - file_format = 'JPEG' - save_kargs['format'] = file_format + file_format = "JPEG" + save_kargs["format"] = file_format - resample = variation['resample'] + resample = variation["resample"] - if variation['width'] is None: - variation['width'] = image.size[0] + if variation["width"] is None: + variation["width"] = image.size[0] - if variation['height'] is None: - variation['height'] = image.size[1] + if variation["height"] is None: + variation["height"] = image.size[1] factor = 1 - while image.size[0] / factor \ - > 2 * variation['width'] \ - and image.size[1] * 2 / factor \ - > 2 * variation['height']: + while ( + image.size[0] / factor > 2 * variation["width"] + and image.size[1] * 2 / factor > 2 * variation["height"] + ): factor *= 2 if factor > 1: image.thumbnail( - (int(image.size[0] / factor), - int(image.size[1] / factor)), - resample=resample + (int(image.size[0] / factor), int(image.size[1] / factor)), + resample=resample, ) - size = variation['width'], variation['height'] - size = tuple(int(i) if i is not None else i - for i in size) + size = variation["width"], variation["height"] + size = tuple(int(i) if i is not None else i for i in size) # http://stackoverflow.com/a/21669827 - image = image.convert('RGB') - save_kargs['optimize'] = True - save_kargs['quality'] = 'web_high' + image = image.convert("RGB") + save_kargs["optimize"] = True + save_kargs["quality"] = "web_high" if size[0] * size[1] > 10000: # roughly <10kb - save_kargs['progressive'] = True + save_kargs["progressive"] = True - if variation['crop']: - image = ImageOps.fit( - image, - size, - method=resample - ) + if variation["crop"]: + image = ImageOps.fit(image, size, method=resample) else: - image.thumbnail( - size, - resample=resample - ) + image.thumbnail(size, resample=resample) - save_kargs.update(variation['kwargs']) + save_kargs.update(variation["kwargs"]) return image, save_kargs diff --git a/stdimage/utils.py b/stdimage/utils.py index 667ab74..183289a 100644 --- a/stdimage/utils.py +++ b/stdimage/utils.py @@ -3,10 +3,13 @@ from .models import StdImageFieldFile -def render_variations(file_name, variations, replace=False, - storage=default_storage, field_class=StdImageFieldFile): +def render_variations( + file_name, + variations, + replace=False, + storage=default_storage, + field_class=StdImageFieldFile, +): """Render all variations for a given field.""" for key, variation in variations.items(): - field_class.render_variation( - file_name, variation, replace, storage - ) + field_class.render_variation(file_name, variation, replace, storage) diff --git a/stdimage/validators.py b/stdimage/validators.py index b609c55..257374a 100644 --- a/stdimage/validators.py +++ b/stdimage/validators.py @@ -13,14 +13,14 @@ def compare(self, x): return True def __init__(self, width, height): - self.limit_value = width or float('inf'), height or float('inf') + self.limit_value = width or float("inf"), height or float("inf") def __call__(self, value): cleaned = self.clean(value) if self.compare(cleaned, self.limit_value): params = { - 'width': self.limit_value[0], - 'height': self.limit_value[1], + "width": self.limit_value[0], + "height": self.limit_value[1], } raise ValidationError(self.message, code=self.code, params=params) @@ -42,10 +42,13 @@ class MaxSizeValidator(BaseSizeValidator): def compare(self, img_size, max_size): return img_size[0] > max_size[0] or img_size[1] > max_size[1] - message = _('The image you uploaded is too large.' - ' The required maximum resolution is:' - ' %(width)sx%(height)s px.') - code = 'max_resolution' + + message = _( + "The image you uploaded is too large." + " The required maximum resolution is:" + " %(width)sx%(height)s px." + ) + code = "max_resolution" class MinSizeValidator(BaseSizeValidator): @@ -57,6 +60,9 @@ class MinSizeValidator(BaseSizeValidator): def compare(self, img_size, min_size): return img_size[0] < min_size[0] or img_size[1] < min_size[1] - message = _('The image you uploaded is too small.' - ' The required minimum resolution is:' - ' %(width)sx%(height)s px.') + + message = _( + "The image you uploaded is too small." + " The required minimum resolution is:" + " %(width)sx%(height)s px." + ) diff --git a/tests/conftest.py b/tests/conftest.py index 33ebae0..bcce969 100644 --- a/tests/conftest.py +++ b/tests/conftest.py @@ -7,17 +7,14 @@ @pytest.fixture def imagedata(): - img = Image.new('RGB', (250, 250), (255, 55, 255)) + img = Image.new("RGB", (250, 250), (255, 55, 255)) output = io.BytesIO() - img.save(output, format='JPEG') + img.save(output, format="JPEG") return output @pytest.fixture def image_upload_file(imagedata): - return SimpleUploadedFile( - 'image.jpg', - imagedata.getvalue() - ) + return SimpleUploadedFile("image.jpg", imagedata.getvalue()) diff --git a/tests/forms.py b/tests/forms.py index 0e660fd..c70347d 100644 --- a/tests/forms.py +++ b/tests/forms.py @@ -4,7 +4,6 @@ class ThumbnailModelForm(forms.ModelForm): - class Meta: model = models.ThumbnailModel - fields = '__all__' + fields = "__all__" diff --git a/tests/models.py b/tests/models.py index 4b294f7..68a702f 100644 --- a/tests/models.py +++ b/tests/models.py @@ -10,20 +10,22 @@ from stdimage.utils import render_variations from stdimage.validators import MaxSizeValidator, MinSizeValidator -upload_to = 'img/' +upload_to = "img/" class SimpleModel(models.Model): """works as ImageField""" + image = StdImageField(upload_to=upload_to) class AdminDeleteModel(models.Model): """can be deleted through admin""" + image = StdImageField( upload_to=upload_to, variations={ - 'thumbnail': (100, 75), + "thumbnail": (100, 75), }, blank=True, delete_orphans=True, @@ -32,10 +34,11 @@ class AdminDeleteModel(models.Model): class AdminUpdateModel(models.Model): """can be updated through admin, image not optional""" + image = StdImageField( upload_to=upload_to, variations={ - 'thumbnail': (100, 75), + "thumbnail": (100, 75), }, blank=False, delete_orphans=True, @@ -44,71 +47,68 @@ class AdminUpdateModel(models.Model): class ResizeModel(models.Model): """resizes image to maximum size to fit a 640x480 area""" + image = StdImageField( upload_to=upload_to, variations={ - 'medium': {'width': 400, 'height': 400}, - 'thumbnail': (100, 75), - } + "medium": {"width": 400, "height": 400}, + "thumbnail": (100, 75), + }, ) class ResizeCropModel(models.Model): """resizes image to 640x480 cropping if necessary""" + image = StdImageField( - upload_to=upload_to, - variations={'thumbnail': (150, 150, True)} + upload_to=upload_to, variations={"thumbnail": (150, 150, True)} ) class ThumbnailModel(models.Model): """creates a thumbnail resized to maximum size to fit a 100x75 area""" + image = StdImageField( upload_to=upload_to, blank=True, - variations={'thumbnail': (100, 75)}, + variations={"thumbnail": (100, 75)}, delete_orphans=True, ) class JPEGModel(models.Model): """creates a thumbnail resized to maximum size to fit a 100x75 area""" + image = JPEGField( upload_to=upload_to, blank=True, variations={ - 'full': (None, None), - 'thumbnail': (100, 75, True), - }, + "full": (None, None), + "thumbnail": (100, 75, True), + }, delete_orphans=True, ) class MaxSizeModel(models.Model): - image = StdImageField( - upload_to=upload_to, - validators=[MaxSizeValidator(16, 16)] - ) + image = StdImageField(upload_to=upload_to, validators=[MaxSizeValidator(16, 16)]) class MinSizeModel(models.Model): - image = StdImageField( - upload_to=upload_to, - validators=[MinSizeValidator(200, 200)] - ) + image = StdImageField(upload_to=upload_to, validators=[MinSizeValidator(200, 200)]) class ForceMinSizeModel(models.Model): """creates a thumbnail resized to maximum size to fit a 100x75 area""" + image = StdImageField( - upload_to=upload_to, - force_min_size=True, - variations={'thumbnail': (600, 600)} + upload_to=upload_to, force_min_size=True, variations={"thumbnail": (600, 600)} ) class CustomManager(models.Manager): """Just like Django's default, but a different class.""" + pass @@ -121,18 +121,20 @@ class Meta: class ManualVariationsModel(CustomManagerModel): """delays creation of 150x150 thumbnails until it is called manually""" + image = StdImageField( upload_to=upload_to, - variations={'thumbnail': (150, 150, True)}, - render_variations=False + variations={"thumbnail": (150, 150, True)}, + render_variations=False, ) class MyStorageModel(CustomManagerModel): """delays creation of 150x150 thumbnails until it is called manually""" + image = StdImageField( upload_to=upload_to, - variations={'thumbnail': (150, 150, True)}, + variations={"thumbnail": (150, 150, True)}, storage=FileSystemStorage(), ) @@ -144,18 +146,20 @@ def render_job(**kwargs): class UtilVariationsModel(models.Model): """delays creation of 150x150 thumbnails until it is called manually""" + image = StdImageField( upload_to=upload_to, - variations={'thumbnail': (150, 150, True)}, - render_variations=render_job + variations={"thumbnail": (150, 150, True)}, + render_variations=render_job, ) class ThumbnailWithoutDirectoryModel(models.Model): """Save into a generated filename that does not contain any '/' char""" + image = StdImageField( - upload_to=lambda instance, filename: 'custom.gif', - variations={'thumbnail': {'width': 150, 'height': 150}}, + upload_to=lambda instance, filename: "custom.gif", + variations={"thumbnail": {"width": 150, "height": 150}}, ) @@ -163,8 +167,7 @@ def custom_render_variations(file_name, variations, storage, replace=False): """Resize image to 100x100.""" for _, variation in variations.items(): variation_name = StdImageFieldFile.get_variation_name( - file_name, - variation['name'] + file_name, variation["name"] ) if storage.exists(variation_name): storage.delete(variation_name) @@ -175,7 +178,7 @@ def custom_render_variations(file_name, variations, storage, replace=False): img = img.resize(size) with BytesIO() as file_buffer: - img.save(file_buffer, 'JPEG') + img.save(file_buffer, "JPEG") f = ContentFile(file_buffer.getvalue()) storage.save(variation_name, f) @@ -187,6 +190,6 @@ class CustomRenderVariationsModel(models.Model): image = StdImageField( upload_to=upload_to, - variations={'thumbnail': (150, 150)}, + variations={"thumbnail": (150, 150)}, render_variations=custom_render_variations, ) diff --git a/tests/settings.py b/tests/settings.py index 81d782a..03ebbd9 100644 --- a/tests/settings.py +++ b/tests/settings.py @@ -7,42 +7,42 @@ BASE_DIR = os.path.dirname(os.path.abspath(__file__)) DATABASES = { - 'default': { - 'ENGINE': 'django.db.backends.sqlite3', - 'NAME': ':memory:', + "default": { + "ENGINE": "django.db.backends.sqlite3", + "NAME": ":memory:", } } INSTALLED_APPS = ( - 'django.contrib.admin', - 'django.contrib.auth', - 'django.contrib.contenttypes', - 'django.contrib.sessions', - 'django.contrib.sites', - 'stdimage', - 'tests' + "django.contrib.admin", + "django.contrib.auth", + "django.contrib.contenttypes", + "django.contrib.sessions", + "django.contrib.sites", + "stdimage", + "tests", ) -DEFAULT_FILE_STORAGE = 'tests.storage.MyFileSystemStorage' +DEFAULT_FILE_STORAGE = "tests.storage.MyFileSystemStorage" TEMPLATES = [ { - 'BACKEND': 'django.template.backends.django.DjangoTemplates', - 'APP_DIRS': True, + "BACKEND": "django.template.backends.django.DjangoTemplates", + "APP_DIRS": True, } ] MIDDLEWARE = MIDDLEWARE_CLASSES = ( - 'django.contrib.sessions.middleware.SessionMiddleware', - 'django.contrib.auth.middleware.AuthenticationMiddleware', - 'django.contrib.messages.middleware.MessageMiddleware', + "django.contrib.sessions.middleware.SessionMiddleware", + "django.contrib.auth.middleware.AuthenticationMiddleware", + "django.contrib.messages.middleware.MessageMiddleware", ) MEDIA_ROOT = tempfile.mkdtemp() SITE_ID = 1 -ROOT_URLCONF = 'tests.urls' +ROOT_URLCONF = "tests.urls" -SECRET_KEY = 'foobar' +SECRET_KEY = "foobar" USE_L10N = True diff --git a/tests/test_commands.py b/tests/test_commands.py index 1e0b8b0..0ef69b1 100644 --- a/tests/test_commands.py +++ b/tests/test_commands.py @@ -11,45 +11,30 @@ @pytest.mark.django_db class TestRenderVariations: - @pytest.fixture(autouse=True) def _swap_concurrent_executor(self, monkeypatch): """Use ThreadPoolExecutor for coverage reports.""" monkeypatch.setattr( - 'concurrent.futures.ProcessPoolExecutor', + "concurrent.futures.ProcessPoolExecutor", ThreadPoolExecutor, ) def test_no_options(self, image_upload_file): - obj = ThumbnailModel.objects.create( - image=image_upload_file - ) + obj = ThumbnailModel.objects.create(image=image_upload_file) file_path = obj.image.thumbnail.path obj.image.delete_variations() - call_command( - 'rendervariations', - 'tests.ThumbnailModel.image' - ) + call_command("rendervariations", "tests.ThumbnailModel.image") assert os.path.exists(file_path) def test_multiprocessing(self, image_upload_file): objs = [ - ThumbnailModel.objects.create( - image=image_upload_file - ) - for _ in range(100) + ThumbnailModel.objects.create(image=image_upload_file) for _ in range(100) ] - file_names = [ - obj.image.thumbnail.path - for obj in objs - ] + file_names = [obj.image.thumbnail.path for obj in objs] for obj in objs: obj.image.delete_variations() assert not any([os.path.exists(f) for f in file_names]) - call_command( - 'rendervariations', - 'tests.ThumbnailModel.image' - ) + call_command("rendervariations", "tests.ThumbnailModel.image") assert any([os.path.exists(f) for f in file_names]) def test_no_replace(self, image_upload_file): @@ -59,8 +44,8 @@ def test_no_replace(self, image_upload_file): before = os.path.getmtime(file_path) time.sleep(0.1) call_command( - 'rendervariations', - 'tests.ThumbnailModel.image', + "rendervariations", + "tests.ThumbnailModel.image", ) assert os.path.exists(file_path) after = os.path.getmtime(file_path) @@ -72,11 +57,7 @@ def test_replace(self, image_upload_file): assert os.path.exists(file_path) before = os.path.getmtime(file_path) time.sleep(0.1) - call_command( - 'rendervariations', - 'tests.ThumbnailModel.image', - replace=True - ) + call_command("rendervariations", "tests.ThumbnailModel.image", replace=True) assert os.path.exists(file_path) after = os.path.getmtime(file_path) assert before != after @@ -89,9 +70,9 @@ def test_ignore_missing(self, image_upload_file): assert not os.path.exists(file_path) time.sleep(0.1) call_command( - 'rendervariations', - 'tests.ThumbnailModel.image', - '--ignore-missing', + "rendervariations", + "tests.ThumbnailModel.image", + "--ignore-missing", replace=True, ) @@ -103,9 +84,9 @@ def test_short_ignore_missing(self, image_upload_file): assert not os.path.exists(file_path) time.sleep(0.1) call_command( - 'rendervariations', - 'tests.ThumbnailModel.image', - '-i', + "rendervariations", + "tests.ThumbnailModel.image", + "-i", replace=True, ) @@ -118,48 +99,40 @@ def test_no_ignore_missing(self, image_upload_file): time.sleep(0.1) with pytest.raises(CommandError): call_command( - 'rendervariations', - 'tests.ThumbnailModel.image', + "rendervariations", + "tests.ThumbnailModel.image", replace=True, ) def test_none_default_storage(self, image_upload_file): - obj = MyStorageModel.customer_manager.create( - image=image_upload_file - ) + obj = MyStorageModel.customer_manager.create(image=image_upload_file) file_path = obj.image.thumbnail.path obj.image.delete_variations() - call_command( - 'rendervariations', - 'tests.MyStorageModel.image' - ) + call_command("rendervariations", "tests.MyStorageModel.image") assert os.path.exists(file_path) def test_invalid_field_path(self): with pytest.raises(CommandError) as exc_info: - call_command( - 'rendervariations', - 'MyStorageModel.image' - ) + call_command("rendervariations", "MyStorageModel.image") - error_message = "Error parsing field_path 'MyStorageModel.image'. "\ - "Use format ." + error_message = ( + "Error parsing field_path 'MyStorageModel.image'. " + "Use format ." + ) assert str(exc_info.value) == error_message def test_custom_render_variations(self, image_upload_file): - obj = CustomRenderVariationsModel.objects.create( - image=image_upload_file - ) + obj = CustomRenderVariationsModel.objects.create(image=image_upload_file) file_path = obj.image.thumbnail.path assert os.path.exists(file_path) - with open(file_path, 'rb') as f: + with open(file_path, "rb") as f: before = hashlib.md5(f.read()).hexdigest() call_command( - 'rendervariations', - 'tests.CustomRenderVariationsModel.image', + "rendervariations", + "tests.CustomRenderVariationsModel.image", replace=True, ) assert os.path.exists(file_path) - with open(file_path, 'rb') as f: + with open(file_path, "rb") as f: after = hashlib.md5(f.read()).hexdigest() assert before == after diff --git a/tests/test_forms.py b/tests/test_forms.py index 1420d2c..81b3360 100644 --- a/tests/test_forms.py +++ b/tests/test_forms.py @@ -6,27 +6,26 @@ class TestStdImageField(TestStdImage): - def test_save_form_data__new(self, db): - instance = models.ThumbnailModel.objects.create(image=self.fixtures['100.gif']) + instance = models.ThumbnailModel.objects.create(image=self.fixtures["100.gif"]) org_path = instance.image.path assert os.path.exists(org_path) form = forms.ThumbnailModelForm( - files=dict(image=self.fixtures['600x400.jpg']), + files=dict(image=self.fixtures["600x400.jpg"]), instance=instance, ) assert form.is_valid() obj = form.save() - assert obj.image.name == 'img/600x400.jpg' + assert obj.image.name == "img/600x400.jpg" assert os.path.exists(instance.image.path) assert not os.path.exists(org_path) def test_save_form_data__false(self, db): - instance = models.ThumbnailModel.objects.create(image=self.fixtures['100.gif']) + instance = models.ThumbnailModel.objects.create(image=self.fixtures["100.gif"]) org_path = instance.image.path assert os.path.exists(org_path) form = forms.ThumbnailModelForm( - data={'image-clear': '1'}, + data={"image-clear": "1"}, instance=instance, ) assert form.is_valid() @@ -35,11 +34,11 @@ def test_save_form_data__false(self, db): assert not os.path.exists(org_path) def test_save_form_data__none(self, db): - instance = models.ThumbnailModel.objects.create(image=self.fixtures['100.gif']) + instance = models.ThumbnailModel.objects.create(image=self.fixtures["100.gif"]) org_path = instance.image.path assert os.path.exists(org_path) form = forms.ThumbnailModelForm( - data={'image': None}, + data={"image": None}, instance=instance, ) assert form.is_valid() diff --git a/tests/test_models.py b/tests/test_models.py index ed1b2d0..516f6a3 100644 --- a/tests/test_models.py +++ b/tests/test_models.py @@ -9,17 +9,25 @@ from PIL import Image from . import models -from .models import (AdminDeleteModel, AdminUpdateModel, CustomRenderVariationsModel, - ResizeCropModel, ResizeModel, SimpleModel, ThumbnailModel, - ThumbnailWithoutDirectoryModel, UtilVariationsModel,) - -IMG_DIR = os.path.join(settings.MEDIA_ROOT, 'img') +from .models import ( + AdminDeleteModel, + AdminUpdateModel, + CustomRenderVariationsModel, + ResizeCropModel, + ResizeModel, + SimpleModel, + ThumbnailModel, + ThumbnailWithoutDirectoryModel, + UtilVariationsModel, +) + +IMG_DIR = os.path.join(settings.MEDIA_ROOT, "img") FIXTURES = [ - ('100.gif', 'GIF', 100, 100), - ('600x400.gif', 'GIF', 600, 400), - ('600x400.jpg', 'JPEG', 600, 400), - ('600x400.jpg', 'PNG', 600, 400), + ("100.gif", "GIF", 100, 100), + ("600x400.gif", "GIF", 600, 400), + ("600x400.jpg", "JPEG", 600, 400), + ("600x400.jpg", "PNG", 600, 400), ] @@ -30,7 +38,7 @@ class TestStdImage: def setup(self): for fixture_filename, img_format, width, height in FIXTURES: with io.BytesIO() as f: - img = Image.new('RGB', (width, height), (255, 55, 255)) + img = Image.new("RGB", (width, height), (255, 55, 255)) img.save(f, format=img_format) suf = SimpleUploadedFile(fixture_filename, f.getvalue()) self.fixtures[fixture_filename] = suf @@ -49,105 +57,100 @@ class TestModel(TestStdImage): def test_simple(self, db): """Tests if Field behaves just like Django's ImageField.""" - instance = SimpleModel.objects.create(image=self.fixtures['100.gif']) - target_file = os.path.join(IMG_DIR, '100.gif') - source_file = self.fixtures['100.gif'] + instance = SimpleModel.objects.create(image=self.fixtures["100.gif"]) + target_file = os.path.join(IMG_DIR, "100.gif") + source_file = self.fixtures["100.gif"] assert SimpleModel.objects.count() == 1 assert SimpleModel.objects.get(pk=1) == instance assert os.path.exists(target_file) - with open(target_file, 'rb') as f: + with open(target_file, "rb") as f: source_file.seek(0) assert source_file.read() == f.read() def test_variations(self, db): """Adds image and checks filesystem as well as width and height.""" - instance = ResizeModel.objects.create( - image=self.fixtures['600x400.jpg'] - ) + instance = ResizeModel.objects.create(image=self.fixtures["600x400.jpg"]) - source_file = self.fixtures['600x400.jpg'] + source_file = self.fixtures["600x400.jpg"] - assert os.path.exists(os.path.join(IMG_DIR, '600x400.jpg')) + assert os.path.exists(os.path.join(IMG_DIR, "600x400.jpg")) assert instance.image.width == 600 assert instance.image.height == 400 - path = os.path.join(IMG_DIR, '600x400.jpg') + path = os.path.join(IMG_DIR, "600x400.jpg") - with open(path, 'rb') as f: + with open(path, "rb") as f: source_file.seek(0) assert source_file.read() == f.read() - path = os.path.join(IMG_DIR, '600x400.medium.jpg') + path = os.path.join(IMG_DIR, "600x400.medium.jpg") assert os.path.exists(path) assert instance.image.medium.width == 400 assert instance.image.medium.height <= 400 - with open(os.path.join(IMG_DIR, '600x400.medium.jpg'), 'rb') as f: + with open(os.path.join(IMG_DIR, "600x400.medium.jpg"), "rb") as f: source_file.seek(0) assert source_file.read() != f.read() - assert os.path.exists(os.path.join(IMG_DIR, '600x400.thumbnail.jpg')) + assert os.path.exists(os.path.join(IMG_DIR, "600x400.thumbnail.jpg")) assert instance.image.thumbnail.width == 100 assert instance.image.thumbnail.height <= 75 - with open(os.path.join(IMG_DIR, '600x400.thumbnail.jpg'), 'rb') as f: + with open(os.path.join(IMG_DIR, "600x400.thumbnail.jpg"), "rb") as f: source_file.seek(0) assert source_file.read() != f.read() def test_cropping(self, db): - instance = ResizeCropModel.objects.create( - image=self.fixtures['600x400.jpg'] - ) + instance = ResizeCropModel.objects.create(image=self.fixtures["600x400.jpg"]) assert instance.image.thumbnail.width == 150 assert instance.image.thumbnail.height == 150 def test_variations_override(self, db): - source_file = self.fixtures['600x400.jpg'] - target_file = os.path.join(IMG_DIR, 'image.thumbnail.jpg') + source_file = self.fixtures["600x400.jpg"] + target_file = os.path.join(IMG_DIR, "image.thumbnail.jpg") os.mkdir(IMG_DIR) default_storage.save(target_file, source_file) - ResizeModel.objects.create( - image=self.fixtures['600x400.jpg'] - ) - thumbnail_path = os.path.join(IMG_DIR, 'image.thumbnail.jpg') + ResizeModel.objects.create(image=self.fixtures["600x400.jpg"]) + thumbnail_path = os.path.join(IMG_DIR, "image.thumbnail.jpg") assert os.path.exists(thumbnail_path) - thumbnail_path = os.path.join(IMG_DIR, 'image.thumbnail_1.jpg') + thumbnail_path = os.path.join(IMG_DIR, "image.thumbnail_1.jpg") assert not os.path.exists(thumbnail_path) def test_delete_thumbnail(self, db): """Delete an image with thumbnail""" - obj = ThumbnailModel.objects.create( - image=self.fixtures['100.gif'] - ) + obj = ThumbnailModel.objects.create(image=self.fixtures["100.gif"]) obj.image.delete() - path = os.path.join(IMG_DIR, 'image.gif') + path = os.path.join(IMG_DIR, "image.gif") assert not os.path.exists(path) - path = os.path.join(IMG_DIR, 'image.thumbnail.gif') + path = os.path.join(IMG_DIR, "image.thumbnail.gif") assert not os.path.exists(path) def test_fore_min_size(self, admin_client): - admin_client.post('/admin/tests/forceminsizemodel/add/', { - 'image': self.fixtures['100.gif'], - }) - path = os.path.join(IMG_DIR, 'image.gif') + admin_client.post( + "/admin/tests/forceminsizemodel/add/", + { + "image": self.fixtures["100.gif"], + }, + ) + path = os.path.join(IMG_DIR, "image.gif") assert not os.path.exists(path) def test_thumbnail_save_without_directory(self, db): obj = ThumbnailWithoutDirectoryModel.objects.create( - image=self.fixtures['100.gif'] + image=self.fixtures["100.gif"] ) obj.save() # Our model saves the images directly into the MEDIA_ROOT directory # not IMG_DIR, under a custom name - original = os.path.join(settings.MEDIA_ROOT, 'custom.gif') - thumbnail = os.path.join(settings.MEDIA_ROOT, 'custom.thumbnail.gif') + original = os.path.join(settings.MEDIA_ROOT, "custom.gif") + thumbnail = os.path.join(settings.MEDIA_ROOT, "custom.thumbnail.gif") assert os.path.exists(original) assert os.path.exists(thumbnail) def test_custom_render_variations(self, db): instance = CustomRenderVariationsModel.objects.create( - image=self.fixtures['600x400.jpg'] + image=self.fixtures["600x400.jpg"] ) # Image size must be 100x100 despite variations settings assert instance.image.thumbnail.width == 100 @@ -160,9 +163,9 @@ def test_defer(self, db, django_assert_num_queries): Accessing a deferred field would cause Django to do a second implicit database query. """ - instance = ResizeModel.objects.create(image=self.fixtures['100.gif']) + instance = ResizeModel.objects.create(image=self.fixtures["100.gif"]) with django_assert_num_queries(1): - deferred = ResizeModel.objects.only('pk').get(pk=instance.pk) + deferred = ResizeModel.objects.only("pk").get(pk=instance.pk) with django_assert_num_queries(1): deferred.image assert instance.image.thumbnail == deferred.image.thumbnail @@ -172,57 +175,56 @@ class TestUtils(TestStdImage): """Tests Utils""" def test_deletion_singnal_receiver(self, db): - obj = AdminDeleteModel.objects.create( - image=self.fixtures['100.gif'] - ) + obj = AdminDeleteModel.objects.create(image=self.fixtures["100.gif"]) path = obj.image.path obj.delete() assert not os.path.exists(path) def test_deletion_singnal_receiver_many(self, db): - obj = AdminDeleteModel.objects.create( - image=self.fixtures['100.gif'] - ) + obj = AdminDeleteModel.objects.create(image=self.fixtures["100.gif"]) path = obj.image.path AdminDeleteModel.objects.all().delete() assert not os.path.exists(path) def test_pre_save_delete_callback_clear(self, admin_client): - obj = AdminDeleteModel.objects.create( - image=self.fixtures['100.gif'] - ) + obj = AdminDeleteModel.objects.create(image=self.fixtures["100.gif"]) path = obj.image.path - admin_client.post('/admin/tests/admindeletemodel/1/change/', { - 'image-clear': 'checked', - }) + admin_client.post( + "/admin/tests/admindeletemodel/1/change/", + { + "image-clear": "checked", + }, + ) assert not os.path.exists(path) def test_pre_save_delete_callback_new(self, admin_client): - obj = AdminDeleteModel.objects.create( - image=self.fixtures['100.gif'] - ) + obj = AdminDeleteModel.objects.create(image=self.fixtures["100.gif"]) path = obj.image.path assert os.path.exists(path) - admin_client.post('/admin/tests/admindeletemodel/1/change/', { - 'image': self.fixtures['600x400.jpg'], - }) + admin_client.post( + "/admin/tests/admindeletemodel/1/change/", + { + "image": self.fixtures["600x400.jpg"], + }, + ) assert not os.path.exists(path) - assert os.path.exists(os.path.join(IMG_DIR, '600x400.jpg')) + assert os.path.exists(os.path.join(IMG_DIR, "600x400.jpg")) def test_pre_save_delete_callback_update(self, admin_client): - obj = AdminUpdateModel.objects.create( - image=self.fixtures['100.gif'] - ) + obj = AdminUpdateModel.objects.create(image=self.fixtures["100.gif"]) path = obj.image.path assert os.path.exists(path) - admin_client.post('/admin/tests/adminupdatemodel/1/change/', { - 'image': self.fixtures['600x400.jpg'], - }) + admin_client.post( + "/admin/tests/adminupdatemodel/1/change/", + { + "image": self.fixtures["600x400.jpg"], + }, + ) assert not os.path.exists(path) - assert os.path.exists(os.path.join(IMG_DIR, '600x400.jpg')) + assert os.path.exists(os.path.join(IMG_DIR, "600x400.jpg")) def test_render_variations_callback(self, db): - obj = UtilVariationsModel.objects.create(image=self.fixtures['100.gif']) + obj = UtilVariationsModel.objects.create(image=self.fixtures["100.gif"]) file_path = obj.image.thumbnail.path assert os.path.exists(file_path) @@ -242,23 +244,29 @@ def test_render_variations_overwrite(self, db, image_upload_file): class TestValidators(TestStdImage): def test_max_size_validator(self, admin_client): - response = admin_client.post('/admin/tests/maxsizemodel/add/', { - 'image': self.fixtures['600x400.jpg'], - }) - assert 'too large' in response.context['adminform'].form.errors['image'][0] - assert not os.path.exists(os.path.join(IMG_DIR, '800x600.jpg')) + response = admin_client.post( + "/admin/tests/maxsizemodel/add/", + { + "image": self.fixtures["600x400.jpg"], + }, + ) + assert "too large" in response.context["adminform"].form.errors["image"][0] + assert not os.path.exists(os.path.join(IMG_DIR, "800x600.jpg")) def test_min_size_validator(self, admin_client): - response = admin_client.post('/admin/tests/minsizemodel/add/', { - 'image': self.fixtures['100.gif'], - }) - assert 'too small' in response.context['adminform'].form.errors['image'][0] - assert not os.path.exists(os.path.join(IMG_DIR, '100.gif')) + response = admin_client.post( + "/admin/tests/minsizemodel/add/", + { + "image": self.fixtures["100.gif"], + }, + ) + assert "too small" in response.context["adminform"].form.errors["image"][0] + assert not os.path.exists(os.path.join(IMG_DIR, "100.gif")) class TestJPEGField(TestStdImage): def test_convert(self, db): - obj = models.JPEGModel.objects.create(image=self.fixtures['100.gif']) - assert obj.image.thumbnail.path.endswith('img/100.thumbnail.jpeg') + obj = models.JPEGModel.objects.create(image=self.fixtures["100.gif"]) + assert obj.image.thumbnail.path.endswith("img/100.thumbnail.jpeg") assert obj.image.full.width == 100 assert obj.image.full.height == 100 diff --git a/tests/test_utils.py b/tests/test_utils.py index 047a651..2ab2c68 100644 --- a/tests/test_utils.py +++ b/tests/test_utils.py @@ -14,18 +14,18 @@ def test_render_variations(self, image_upload_file): instance = ManualVariationsModel.customer_manager.create( image=image_upload_file ) - path = os.path.join(IMG_DIR, 'image.thumbnail.jpg') + path = os.path.join(IMG_DIR, "image.thumbnail.jpg") assert not os.path.exists(path) render_variations( file_name=instance.image.name, variations={ - 'thumbnail': { - 'name': 'thumbnail', - 'width': 150, - 'height': 150, - 'crop': True, - 'resample': Image.ANTIALIAS + "thumbnail": { + "name": "thumbnail", + "width": 150, + "height": 150, + "crop": True, + "resample": Image.ANTIALIAS, } - } + }, ) assert os.path.exists(path) diff --git a/tests/test_validators.py b/tests/test_validators.py index 4a3b4ac..5ccdd93 100644 --- a/tests/test_validators.py +++ b/tests/test_validators.py @@ -4,7 +4,8 @@ class TestBaseSizeValidator: def test_init__none(self): assert validators.MinSizeValidator(None, None).limit_value == ( - float('inf'), float('inf') + float("inf"), + float("inf"), ) diff --git a/tests/urls.py b/tests/urls.py index d69c573..483e1a1 100644 --- a/tests/urls.py +++ b/tests/urls.py @@ -4,5 +4,5 @@ admin.autodiscover() urlpatterns = [ - url(r'^admin/', admin.site.urls), + url(r"^admin/", admin.site.urls), ] From 8826c7b5fe2294ff7b406dd6a3be995aa55f4310 Mon Sep 17 00:00:00 2001 From: Johannes Maron Date: Fri, 26 Mar 2021 09:45:59 +0100 Subject: [PATCH 06/98] Resolve deprecation errors and add Django 3.2 ci suite --- .github/workflows/ci.yml | 1 + setup.cfg | 5 ++++- tests/urls.py | 4 ++-- 3 files changed, 7 insertions(+), 3 deletions(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index ad1748b..062fdb7 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -88,6 +88,7 @@ jobs: django-version: - "2.2" - "3.1" + - "3.2rc1" steps: - name: Set up Python ${{ matrix.python-version }} uses: actions/setup-python@v2.2.1 diff --git a/setup.cfg b/setup.cfg index cb1ab4e..373bf87 100644 --- a/setup.cfg +++ b/setup.cfg @@ -26,6 +26,7 @@ classifier = Framework :: Django Framework :: Django :: 2.2 Framework :: Django :: 3.1 + Framework :: Django :: 3.2 python_requires = >=3.7 @@ -60,7 +61,9 @@ test = pytest [tool:pytest] norecursedirs=venv env .eggs DJANGO_SETTINGS_MODULE=tests.settings -addopts = --cov=stdimage --nomigrations +addopts = --cov=stdimage --nomigrations --tb=short +filterwarnings = + error [coverage:run] source = . diff --git a/tests/urls.py b/tests/urls.py index 483e1a1..f8aa21b 100644 --- a/tests/urls.py +++ b/tests/urls.py @@ -1,8 +1,8 @@ -from django.conf.urls import url from django.contrib import admin +from django.urls import path admin.autodiscover() urlpatterns = [ - url(r"^admin/", admin.site.urls), + path("admin/", admin.site.urls), ] From 8e3ee5b36932be230fc3bcd87e390dfd027cbaae Mon Sep 17 00:00:00 2001 From: Johannes Maron Date: Fri, 26 Mar 2021 09:48:37 +0100 Subject: [PATCH 07/98] Remove fussyfox --- .checks.yml | 3 --- 1 file changed, 3 deletions(-) delete mode 100644 .checks.yml diff --git a/.checks.yml b/.checks.yml deleted file mode 100644 index 288e631..0000000 --- a/.checks.yml +++ /dev/null @@ -1,3 +0,0 @@ -- bandit -- flake8 -- pydocstyle From a2867a97ece1874a60319d60e889afb683897ab0 Mon Sep 17 00:00:00 2001 From: Johannes Maron Date: Fri, 26 Mar 2021 10:14:58 +0100 Subject: [PATCH 08/98] Remove progressbar dependency --- .github/workflows/ci.yml | 14 ++++--- setup.cfg | 5 ++- .../management/commands/rendervariations.py | 40 +++++++++++-------- 3 files changed, 36 insertions(+), 23 deletions(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 062fdb7..808aa2d 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -64,7 +64,7 @@ jobs: runs-on: ubuntu-latest steps: - name: Install gettext - run: sudo apt-get install gettext -y + run: sudo apt install gettext -y - uses: actions/setup-python@v2.2.1 - run: python -m pip install --upgrade pip setuptools wheel twine readme-renderer - uses: actions/checkout@v2.3.4 @@ -89,16 +89,20 @@ jobs: - "2.2" - "3.1" - "3.2rc1" + extra: + - "" + - "progressbar" steps: - name: Set up Python ${{ matrix.python-version }} uses: actions/setup-python@v2.2.1 with: python-version: ${{ matrix.python-version }} + - run: sudo apt install gettext -y - uses: actions/checkout@v2.3.4 - - name: Install dependencies - run: | - python -m pip install --upgrade pip setuptools codecov - pip install django~=${{ matrix.django-version }} + - run: python -m pip install --upgrade pip setuptools codecov wheel + - run: python -m pip install .[${{ matrix.extra }}] + if: ${{ matrix.extra }} + - run: python -m pip install django~=${{ matrix.django-version }} - name: Test with pytest run: python setup.py test - run: codecov diff --git a/setup.cfg b/setup.cfg index 373bf87..696d7c0 100644 --- a/setup.cfg +++ b/setup.cfg @@ -36,7 +36,7 @@ packages = stdimage install_requires = Django>=2.2 pillow>=2.5 - progressbar2>=3.0.0 + setup_requires = setuptools_scm pytest-runner @@ -52,6 +52,9 @@ tests_require = exclude = tests +[options.extras_require] +progressbar = progressbar2>=3.0.0 + [bdist_wheel] universal = 1 diff --git a/stdimage/management/commands/rendervariations.py b/stdimage/management/commands/rendervariations.py index 07e5efb..bcc852e 100644 --- a/stdimage/management/commands/rendervariations.py +++ b/stdimage/management/commands/rendervariations.py @@ -1,4 +1,3 @@ -import progressbar from django.apps import apps from django.core.files.storage import get_storage_class from django.core.management import BaseCommand, CommandError @@ -59,8 +58,7 @@ def handle(self, *args, **options): self.render(field, images, count, replace, ignore_missing, do_render) - @staticmethod - def render(field, images, count, replace, ignore_missing, do_render): + def render(self, field, images, count, replace, ignore_missing, do_render): kwargs_list = ( dict( file_name=file_name, @@ -73,20 +71,26 @@ def render(field, images, count, replace, ignore_missing, do_render): ) for file_name in images ) - with progressbar.ProgressBar( - max_value=count, - widgets=( - progressbar.RotatingMarker(), - " | ", - progressbar.AdaptiveETA(), - " | ", - progressbar.Percentage(), - " ", - progressbar.Bar(), - ), - ) as bar: - for _ in map(render_field_variations, kwargs_list): - bar += 1 + try: + import progressbar + except ImportError: + for file_name in map(render_field_variations, kwargs_list): + self.stdout.write(f"Processing: {file_name}", self.style.NOTICE) + else: + with progressbar.ProgressBar( + max_value=count, + widgets=( + progressbar.RotatingMarker(), + " | ", + progressbar.AdaptiveETA(), + " | ", + progressbar.Percentage(), + " ", + progressbar.Bar(), + ), + ) as bar: + for _ in map(render_field_variations, kwargs_list): + bar += 1 def render_field_variations(kwargs): @@ -101,7 +105,9 @@ def render_field_variations(kwargs): render_variations(**kwargs) except FileNotFoundError as e: if not ignore_missing: + print(ignore_missing) raise CommandError( "Source file was not found, terminating. " "Use -i/--ignore-missing to skip this error." ) from e + return kwargs["file_name"] From e23e12d8f763fa08e85ac6687c4eaf42dce5e78f Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Fri, 26 Mar 2021 09:46:17 +0000 Subject: [PATCH 09/98] Bump isort from 5.7.0 to 5.8.0 Bumps [isort](https://github.com/pycqa/isort) from 5.7.0 to 5.8.0. - [Release notes](https://github.com/pycqa/isort/releases) - [Changelog](https://github.com/PyCQA/isort/blob/main/CHANGELOG.md) - [Commits](https://github.com/pycqa/isort/compare/5.7.0...5.8.0) Signed-off-by: dependabot[bot] --- lint-requirements.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lint-requirements.txt b/lint-requirements.txt index 296bfa6..7306238 100644 --- a/lint-requirements.txt +++ b/lint-requirements.txt @@ -1,6 +1,6 @@ bandit==1.7.0 black==20.8b1 flake8==3.9.0 -isort==5.7.0 +isort==5.8.0 msgcheck==3.1 pydocstyle==6.0.0 From 0e30efa8581fd424c0ddced580864fe666a6a0a0 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Tue, 13 Apr 2021 07:37:45 +0000 Subject: [PATCH 10/98] Bump actions/cache from v2.1.4 to v2.1.5 Bumps [actions/cache](https://github.com/actions/cache) from v2.1.4 to v2.1.5. - [Release notes](https://github.com/actions/cache/releases) - [Commits](https://github.com/actions/cache/compare/v2.1.4...1a9e2138d905efd099035b49d8b7a3888c653ca8) Signed-off-by: dependabot[bot] --- .github/workflows/ci.yml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 808aa2d..742baa4 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -27,7 +27,7 @@ jobs: - uses: actions/setup-python@v2 - uses: actions/checkout@v2 - run: sudo apt install -y gettext aspell libenchant-dev - - uses: actions/cache@v2.1.4 + - uses: actions/cache@v2.1.5 with: path: ~/.cache/pip key: ${{ runner.os }}-pip-${{ hashFiles('lint-requirements.txt') }} @@ -50,7 +50,7 @@ jobs: steps: - uses: actions/setup-python@v2 - uses: actions/checkout@v2 - - uses: actions/cache@v2.1.4 + - uses: actions/cache@v2.1.5 with: path: ~/.cache/pip key: ${{ runner.os }}-pip-${{ hashFiles('lint-requirements.txt') }} From 4c6f4269dc569533243194d4b795266977a194cf Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Fri, 16 Apr 2021 07:50:21 +0000 Subject: [PATCH 11/98] Bump flake8 from 3.9.0 to 3.9.1 Bumps [flake8](https://gitlab.com/pycqa/flake8) from 3.9.0 to 3.9.1. - [Release notes](https://gitlab.com/pycqa/flake8/tags) - [Commits](https://gitlab.com/pycqa/flake8/compare/3.9.0...3.9.1) Signed-off-by: dependabot[bot] --- lint-requirements.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lint-requirements.txt b/lint-requirements.txt index 7306238..b053706 100644 --- a/lint-requirements.txt +++ b/lint-requirements.txt @@ -1,6 +1,6 @@ bandit==1.7.0 black==20.8b1 -flake8==3.9.0 +flake8==3.9.1 isort==5.8.0 msgcheck==3.1 pydocstyle==6.0.0 From f4a4333bd6d387a1fdd8460c23c5b1d039e2d43d Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 26 Apr 2021 09:36:36 +0000 Subject: [PATCH 12/98] Bump black from 20.8b1 to 21.4b0 Bumps [black](https://github.com/psf/black) from 20.8b1 to 21.4b0. - [Release notes](https://github.com/psf/black/releases) - [Changelog](https://github.com/psf/black/blob/master/CHANGES.md) - [Commits](https://github.com/psf/black/commits) Signed-off-by: dependabot[bot] --- lint-requirements.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lint-requirements.txt b/lint-requirements.txt index b053706..12626fc 100644 --- a/lint-requirements.txt +++ b/lint-requirements.txt @@ -1,5 +1,5 @@ bandit==1.7.0 -black==20.8b1 +black==21.4b0 flake8==3.9.1 isort==5.8.0 msgcheck==3.1 From 668f239a2c1f1cd12e651e956ddecc1e50c53bc4 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Wed, 28 Apr 2021 07:56:17 +0000 Subject: [PATCH 13/98] Bump black from 21.4b0 to 21.4b1 Bumps [black](https://github.com/psf/black) from 21.4b0 to 21.4b1. - [Release notes](https://github.com/psf/black/releases) - [Changelog](https://github.com/psf/black/blob/master/CHANGES.md) - [Commits](https://github.com/psf/black/commits) Signed-off-by: dependabot[bot] --- lint-requirements.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lint-requirements.txt b/lint-requirements.txt index 12626fc..d3fb144 100644 --- a/lint-requirements.txt +++ b/lint-requirements.txt @@ -1,5 +1,5 @@ bandit==1.7.0 -black==21.4b0 +black==21.4b1 flake8==3.9.1 isort==5.8.0 msgcheck==3.1 From ae0f53e4beef41da455564cf98b1659ef112aeae Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Thu, 29 Apr 2021 07:50:18 +0000 Subject: [PATCH 14/98] Bump black from 21.4b1 to 21.4b2 Bumps [black](https://github.com/psf/black) from 21.4b1 to 21.4b2. - [Release notes](https://github.com/psf/black/releases) - [Changelog](https://github.com/psf/black/blob/master/CHANGES.md) - [Commits](https://github.com/psf/black/commits) Signed-off-by: dependabot[bot] --- lint-requirements.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lint-requirements.txt b/lint-requirements.txt index d3fb144..9c3b8d2 100644 --- a/lint-requirements.txt +++ b/lint-requirements.txt @@ -1,5 +1,5 @@ bandit==1.7.0 -black==21.4b1 +black==21.4b2 flake8==3.9.1 isort==5.8.0 msgcheck==3.1 From ce060e55f9dd6751c309f84e9330a5dac49c55dc Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Wed, 5 May 2021 07:45:34 +0000 Subject: [PATCH 15/98] Bump black from 21.4b2 to 21.5b0 Bumps [black](https://github.com/psf/black) from 21.4b2 to 21.5b0. - [Release notes](https://github.com/psf/black/releases) - [Changelog](https://github.com/psf/black/blob/master/CHANGES.md) - [Commits](https://github.com/psf/black/commits) Signed-off-by: dependabot[bot] --- lint-requirements.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lint-requirements.txt b/lint-requirements.txt index 9c3b8d2..09362b2 100644 --- a/lint-requirements.txt +++ b/lint-requirements.txt @@ -1,5 +1,5 @@ bandit==1.7.0 -black==21.4b2 +black==21.5b0 flake8==3.9.1 isort==5.8.0 msgcheck==3.1 From 3e59f2f61321aa5c83cc784bffb0d24215ea27ba Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 10 May 2021 09:52:02 +0000 Subject: [PATCH 16/98] Bump flake8 from 3.9.1 to 3.9.2 Bumps [flake8](https://gitlab.com/pycqa/flake8) from 3.9.1 to 3.9.2. - [Release notes](https://gitlab.com/pycqa/flake8/tags) - [Commits](https://gitlab.com/pycqa/flake8/compare/3.9.1...3.9.2) Signed-off-by: dependabot[bot] --- lint-requirements.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lint-requirements.txt b/lint-requirements.txt index 09362b2..0a62a14 100644 --- a/lint-requirements.txt +++ b/lint-requirements.txt @@ -1,6 +1,6 @@ bandit==1.7.0 black==21.5b0 -flake8==3.9.1 +flake8==3.9.2 isort==5.8.0 msgcheck==3.1 pydocstyle==6.0.0 From 6a4db8d62e26ce085abf63dc47c45eaaa8e7ea1f Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Tue, 11 May 2021 06:12:00 +0000 Subject: [PATCH 17/98] Bump black from 21.5b0 to 21.5b1 Bumps [black](https://github.com/psf/black) from 21.5b0 to 21.5b1. - [Release notes](https://github.com/psf/black/releases) - [Changelog](https://github.com/psf/black/blob/main/CHANGES.md) - [Commits](https://github.com/psf/black/commits) Signed-off-by: dependabot[bot] --- lint-requirements.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lint-requirements.txt b/lint-requirements.txt index 0a62a14..cd15ba1 100644 --- a/lint-requirements.txt +++ b/lint-requirements.txt @@ -1,5 +1,5 @@ bandit==1.7.0 -black==21.5b0 +black==21.5b1 flake8==3.9.2 isort==5.8.0 msgcheck==3.1 From 99880d6b55cd4680b29396b6f7f12f9f37f88c67 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Wed, 12 May 2021 06:02:57 +0000 Subject: [PATCH 18/98] Bump actions/checkout from 2 to 2.3.4 Bumps [actions/checkout](https://github.com/actions/checkout) from 2 to 2.3.4. - [Release notes](https://github.com/actions/checkout/releases) - [Changelog](https://github.com/actions/checkout/blob/main/CHANGELOG.md) - [Commits](https://github.com/actions/checkout/compare/v2...v2.3.4) Signed-off-by: dependabot[bot] --- .github/workflows/ci.yml | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 742baa4..b72632e 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -13,7 +13,7 @@ jobs: runs-on: ubuntu-latest steps: - name: Checkout repository - uses: actions/checkout@v2 + uses: actions/checkout@v2.3.4 - name: Initialize CodeQL uses: github/codeql-action/init@v1 with: @@ -25,7 +25,7 @@ jobs: runs-on: ubuntu-latest steps: - uses: actions/setup-python@v2 - - uses: actions/checkout@v2 + - uses: actions/checkout@v2.3.4 - run: sudo apt install -y gettext aspell libenchant-dev - uses: actions/cache@v2.1.5 with: @@ -49,7 +49,7 @@ jobs: runs-on: ubuntu-latest steps: - uses: actions/setup-python@v2 - - uses: actions/checkout@v2 + - uses: actions/checkout@v2.3.4 - uses: actions/cache@v2.1.5 with: path: ~/.cache/pip From 4598f27b4462424f09c71da3c0e6e30adab9b1ce Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Wed, 12 May 2021 07:42:48 +0000 Subject: [PATCH 19/98] Bump actions/setup-python from 2 to 2.2.2 Bumps [actions/setup-python](https://github.com/actions/setup-python) from 2 to 2.2.2. - [Release notes](https://github.com/actions/setup-python/releases) - [Commits](https://github.com/actions/setup-python/compare/v2...v2.2.2) Signed-off-by: dependabot[bot] --- .github/workflows/ci.yml | 8 ++++---- .github/workflows/release.yml | 2 +- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index b72632e..cf0e933 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -24,7 +24,7 @@ jobs: msgcheck: runs-on: ubuntu-latest steps: - - uses: actions/setup-python@v2 + - uses: actions/setup-python@v2.2.2 - uses: actions/checkout@v2.3.4 - run: sudo apt install -y gettext aspell libenchant-dev - uses: actions/cache@v2.1.5 @@ -48,7 +48,7 @@ jobs: - "pydocstyle ." runs-on: ubuntu-latest steps: - - uses: actions/setup-python@v2 + - uses: actions/setup-python@v2.2.2 - uses: actions/checkout@v2.3.4 - uses: actions/cache@v2.1.5 with: @@ -65,7 +65,7 @@ jobs: steps: - name: Install gettext run: sudo apt install gettext -y - - uses: actions/setup-python@v2.2.1 + - uses: actions/setup-python@v2.2.2 - run: python -m pip install --upgrade pip setuptools wheel twine readme-renderer - uses: actions/checkout@v2.3.4 - run: python setup.py sdist bdist_wheel @@ -94,7 +94,7 @@ jobs: - "progressbar" steps: - name: Set up Python ${{ matrix.python-version }} - uses: actions/setup-python@v2.2.1 + uses: actions/setup-python@v2.2.2 with: python-version: ${{ matrix.python-version }} - run: sudo apt install gettext -y diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml index 01f8ace..30eb296 100644 --- a/.github/workflows/release.yml +++ b/.github/workflows/release.yml @@ -9,7 +9,7 @@ jobs: steps: - uses: actions/checkout@v2.3.4 - name: Set up Python ${{ matrix.python-version }} - uses: actions/setup-python@v2.2.1 + uses: actions/setup-python@v2.2.2 with: python-version: ${{ matrix.python-version }} - name: Install gettext From a6975eb966a6ff4907ee02017b3551f3f1e9e8b8 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Tue, 18 May 2021 06:35:24 +0000 Subject: [PATCH 20/98] Bump pydocstyle from 6.0.0 to 6.1.1 Bumps [pydocstyle](https://github.com/PyCQA/pydocstyle) from 6.0.0 to 6.1.1. - [Release notes](https://github.com/PyCQA/pydocstyle/releases) - [Changelog](https://github.com/PyCQA/pydocstyle/blob/master/docs/release_notes.rst) - [Commits](https://github.com/PyCQA/pydocstyle/compare/6.0.0...6.1.1) Signed-off-by: dependabot[bot] --- lint-requirements.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lint-requirements.txt b/lint-requirements.txt index cd15ba1..a8978cc 100644 --- a/lint-requirements.txt +++ b/lint-requirements.txt @@ -3,4 +3,4 @@ black==21.5b1 flake8==3.9.2 isort==5.8.0 msgcheck==3.1 -pydocstyle==6.0.0 +pydocstyle==6.1.1 From eeaa9a7e5534df48f6e43d68d73d5561e286389a Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Fri, 28 May 2021 06:11:08 +0000 Subject: [PATCH 21/98] Bump actions/cache from 2.1.5 to 2.1.6 Bumps [actions/cache](https://github.com/actions/cache) from 2.1.5 to 2.1.6. - [Release notes](https://github.com/actions/cache/releases) - [Commits](https://github.com/actions/cache/compare/v2.1.5...v2.1.6) Signed-off-by: dependabot[bot] --- .github/workflows/ci.yml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index cf0e933..07799f2 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -27,7 +27,7 @@ jobs: - uses: actions/setup-python@v2.2.2 - uses: actions/checkout@v2.3.4 - run: sudo apt install -y gettext aspell libenchant-dev - - uses: actions/cache@v2.1.5 + - uses: actions/cache@v2.1.6 with: path: ~/.cache/pip key: ${{ runner.os }}-pip-${{ hashFiles('lint-requirements.txt') }} @@ -50,7 +50,7 @@ jobs: steps: - uses: actions/setup-python@v2.2.2 - uses: actions/checkout@v2.3.4 - - uses: actions/cache@v2.1.5 + - uses: actions/cache@v2.1.6 with: path: ~/.cache/pip key: ${{ runner.os }}-pip-${{ hashFiles('lint-requirements.txt') }} From 3a91926e189adf68fa095e04c00ef6caa80a22a8 Mon Sep 17 00:00:00 2001 From: James Meakin <12661555+jmsmkn@users.noreply.github.com> Date: Thu, 13 May 2021 10:48:38 +0200 Subject: [PATCH 22/98] Add failing test for multiple jpeg conversion --- tests/test_models.py | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/tests/test_models.py b/tests/test_models.py index 516f6a3..772737d 100644 --- a/tests/test_models.py +++ b/tests/test_models.py @@ -270,3 +270,13 @@ def test_convert(self, db): assert obj.image.thumbnail.path.endswith("img/100.thumbnail.jpeg") assert obj.image.full.width == 100 assert obj.image.full.height == 100 + + def test_convert_multiple(self, db): + large = models.JPEGModel.objects.create(image=self.fixtures["600x400.gif"]) + small = models.JPEGModel.objects.create(image=self.fixtures["100.gif"]) + + assert large.image.field._variations["full"] == (None, None) + assert small.image.field._variations["full"] == (None, None) + + assert large.image.full.width == 600 + assert small.image.full.width == 100 From 5c72f048b462c11df13a05a8199ed30ca3780529 Mon Sep 17 00:00:00 2001 From: James Meakin <12661555+jmsmkn@users.noreply.github.com> Date: Thu, 13 May 2021 10:49:35 +0200 Subject: [PATCH 23/98] Fix multiple jpeg file conversion --- stdimage/models.py | 13 +++++-------- 1 file changed, 5 insertions(+), 8 deletions(-) diff --git a/stdimage/models.py b/stdimage/models.py index 2722ee8..0eb6943 100644 --- a/stdimage/models.py +++ b/stdimage/models.py @@ -304,16 +304,13 @@ def process_variation(cls, variation, image): resample = variation["resample"] - if variation["width"] is None: - variation["width"] = image.size[0] - - if variation["height"] is None: - variation["height"] = image.size[1] + width = image.size[0] if variation["width"] is None else variation["width"] + height = image.size[1] if variation["height"] is None else variation["height"] factor = 1 while ( - image.size[0] / factor > 2 * variation["width"] - and image.size[1] * 2 / factor > 2 * variation["height"] + image.size[0] / factor > 2 * width + and image.size[1] * 2 / factor > 2 * height ): factor *= 2 if factor > 1: @@ -322,7 +319,7 @@ def process_variation(cls, variation, image): resample=resample, ) - size = variation["width"], variation["height"] + size = width, height size = tuple(int(i) if i is not None else i for i in size) # http://stackoverflow.com/a/21669827 From 0b0cc033cbbdb4befe97087360030a063e4f718f Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Tue, 1 Jun 2021 06:48:54 +0000 Subject: [PATCH 24/98] Bump black from 21.5b1 to 21.5b2 Bumps [black](https://github.com/psf/black) from 21.5b1 to 21.5b2. - [Release notes](https://github.com/psf/black/releases) - [Changelog](https://github.com/psf/black/blob/main/CHANGES.md) - [Commits](https://github.com/psf/black/commits) Signed-off-by: dependabot[bot] --- lint-requirements.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lint-requirements.txt b/lint-requirements.txt index a8978cc..55c00aa 100644 --- a/lint-requirements.txt +++ b/lint-requirements.txt @@ -1,5 +1,5 @@ bandit==1.7.0 -black==21.5b1 +black==21.5b2 flake8==3.9.2 isort==5.8.0 msgcheck==3.1 From 6213f8b5140a002f2a84055b8f62925972187818 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Fri, 11 Jun 2021 06:04:39 +0000 Subject: [PATCH 25/98] Bump black from 21.5b2 to 21.6b0 Bumps [black](https://github.com/psf/black) from 21.5b2 to 21.6b0. - [Release notes](https://github.com/psf/black/releases) - [Changelog](https://github.com/psf/black/blob/main/CHANGES.md) - [Commits](https://github.com/psf/black/commits) --- updated-dependencies: - dependency-name: black dependency-type: direct:production ... Signed-off-by: dependabot[bot] --- lint-requirements.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lint-requirements.txt b/lint-requirements.txt index 55c00aa..d34f646 100644 --- a/lint-requirements.txt +++ b/lint-requirements.txt @@ -1,5 +1,5 @@ bandit==1.7.0 -black==21.5b2 +black==21.6b0 flake8==3.9.2 isort==5.8.0 msgcheck==3.1 From f9ebead951c408e82343cfda2b742d2bc0381b96 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 21 Jun 2021 21:09:44 +0000 Subject: [PATCH 26/98] Bump isort from 5.8.0 to 5.9.1 Bumps [isort](https://github.com/pycqa/isort) from 5.8.0 to 5.9.1. - [Release notes](https://github.com/pycqa/isort/releases) - [Changelog](https://github.com/PyCQA/isort/blob/main/CHANGELOG.md) - [Commits](https://github.com/pycqa/isort/compare/5.8.0...5.9.1) --- updated-dependencies: - dependency-name: isort dependency-type: direct:production update-type: version-update:semver-minor ... Signed-off-by: dependabot[bot] --- lint-requirements.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lint-requirements.txt b/lint-requirements.txt index d34f646..537ded7 100644 --- a/lint-requirements.txt +++ b/lint-requirements.txt @@ -1,6 +1,6 @@ bandit==1.7.0 black==21.6b0 flake8==3.9.2 -isort==5.8.0 +isort==5.9.1 msgcheck==3.1 pydocstyle==6.1.1 From 70171369cf48e56a803c376ad4a703e7e51fa81d Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Thu, 8 Jul 2021 21:09:13 +0000 Subject: [PATCH 27/98] Bump isort from 5.9.1 to 5.9.2 Bumps [isort](https://github.com/pycqa/isort) from 5.9.1 to 5.9.2. - [Release notes](https://github.com/pycqa/isort/releases) - [Changelog](https://github.com/PyCQA/isort/blob/main/CHANGELOG.md) - [Commits](https://github.com/pycqa/isort/compare/5.9.1...5.9.2) --- updated-dependencies: - dependency-name: isort dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] --- lint-requirements.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lint-requirements.txt b/lint-requirements.txt index 537ded7..d78b0e2 100644 --- a/lint-requirements.txt +++ b/lint-requirements.txt @@ -1,6 +1,6 @@ bandit==1.7.0 black==21.6b0 flake8==3.9.2 -isort==5.9.1 +isort==5.9.2 msgcheck==3.1 pydocstyle==6.1.1 From ede1f92f142acbfbb81c5056e0a84a37f34ce4c8 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Fri, 16 Jul 2021 21:10:55 +0000 Subject: [PATCH 28/98] Bump black from 21.6b0 to 21.7b0 Bumps [black](https://github.com/psf/black) from 21.6b0 to 21.7b0. - [Release notes](https://github.com/psf/black/releases) - [Changelog](https://github.com/psf/black/blob/main/CHANGES.md) - [Commits](https://github.com/psf/black/commits) --- updated-dependencies: - dependency-name: black dependency-type: direct:production ... Signed-off-by: dependabot[bot] --- lint-requirements.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lint-requirements.txt b/lint-requirements.txt index d78b0e2..8f5e664 100644 --- a/lint-requirements.txt +++ b/lint-requirements.txt @@ -1,5 +1,5 @@ bandit==1.7.0 -black==21.6b0 +black==21.7b0 flake8==3.9.2 isort==5.9.2 msgcheck==3.1 From c8df00c8239e7de5689e9f6235a597bf00afa125 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Thu, 29 Jul 2021 21:07:21 +0000 Subject: [PATCH 29/98] Bump isort from 5.9.2 to 5.9.3 Bumps [isort](https://github.com/pycqa/isort) from 5.9.2 to 5.9.3. - [Release notes](https://github.com/pycqa/isort/releases) - [Changelog](https://github.com/PyCQA/isort/blob/main/CHANGELOG.md) - [Commits](https://github.com/pycqa/isort/compare/5.9.2...5.9.3) --- updated-dependencies: - dependency-name: isort dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] --- lint-requirements.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lint-requirements.txt b/lint-requirements.txt index 8f5e664..2fa4d03 100644 --- a/lint-requirements.txt +++ b/lint-requirements.txt @@ -1,6 +1,6 @@ bandit==1.7.0 black==21.7b0 flake8==3.9.2 -isort==5.9.2 +isort==5.9.3 msgcheck==3.1 pydocstyle==6.1.1 From 06ffda7c5ad29a0ebcdb76498f6d02b716337e16 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 30 Aug 2021 21:08:35 +0000 Subject: [PATCH 30/98] Bump black from 21.7b0 to 21.8b0 Bumps [black](https://github.com/psf/black) from 21.7b0 to 21.8b0. - [Release notes](https://github.com/psf/black/releases) - [Changelog](https://github.com/psf/black/blob/main/CHANGES.md) - [Commits](https://github.com/psf/black/commits) --- updated-dependencies: - dependency-name: black dependency-type: direct:production ... Signed-off-by: dependabot[bot] --- lint-requirements.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lint-requirements.txt b/lint-requirements.txt index 2fa4d03..765ef00 100644 --- a/lint-requirements.txt +++ b/lint-requirements.txt @@ -1,5 +1,5 @@ bandit==1.7.0 -black==21.7b0 +black==21.8b0 flake8==3.9.2 isort==5.9.3 msgcheck==3.1 From 6c043a08a892b75202b96a73615588d8e16aa9e1 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Tue, 14 Sep 2021 21:09:43 +0000 Subject: [PATCH 31/98] Bump black from 21.8b0 to 21.9b0 Bumps [black](https://github.com/psf/black) from 21.8b0 to 21.9b0. - [Release notes](https://github.com/psf/black/releases) - [Changelog](https://github.com/psf/black/blob/main/CHANGES.md) - [Commits](https://github.com/psf/black/commits) --- updated-dependencies: - dependency-name: black dependency-type: direct:production ... Signed-off-by: dependabot[bot] --- lint-requirements.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lint-requirements.txt b/lint-requirements.txt index 765ef00..3f771e6 100644 --- a/lint-requirements.txt +++ b/lint-requirements.txt @@ -1,5 +1,5 @@ bandit==1.7.0 -black==21.8b0 +black==21.9b0 flake8==3.9.2 isort==5.9.3 msgcheck==3.1 From ef9a2eb4843f0de41117a5eec9ba04962181d23d Mon Sep 17 00:00:00 2001 From: Johannes Maron Date: Sun, 19 Sep 2021 12:16:48 +0200 Subject: [PATCH 32/98] Use correct Django version in CI suite The PEP440 syntax with a tilde ~ increments the last bit of the version identifier. This cased all tests to run agains the latest v2 or v3 release instead of the correct subversion and their latest security releases. Close #257 --- .github/workflows/ci.yml | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 07799f2..3ec3fd0 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -86,9 +86,9 @@ jobs: - "3.8" - "3.9" django-version: - - "2.2" - - "3.1" - - "3.2rc1" + - "2.2.*" + - "3.1.*" + - "3.2.*" extra: - "" - "progressbar" @@ -102,7 +102,7 @@ jobs: - run: python -m pip install --upgrade pip setuptools codecov wheel - run: python -m pip install .[${{ matrix.extra }}] if: ${{ matrix.extra }} - - run: python -m pip install django~=${{ matrix.django-version }} + - run: python -m pip install django==${{ matrix.django-version }} - name: Test with pytest run: python setup.py test - run: codecov From 7988d9db647be9ea9c03cf0c55c95cadf4b60d84 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 11 Oct 2021 21:08:37 +0000 Subject: [PATCH 33/98] Bump flake8 from 3.9.2 to 4.0.1 Bumps [flake8](https://github.com/pycqa/flake8) from 3.9.2 to 4.0.1. - [Release notes](https://github.com/pycqa/flake8/releases) - [Commits](https://github.com/pycqa/flake8/compare/3.9.2...4.0.1) --- updated-dependencies: - dependency-name: flake8 dependency-type: direct:production update-type: version-update:semver-major ... Signed-off-by: dependabot[bot] --- lint-requirements.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lint-requirements.txt b/lint-requirements.txt index 3f771e6..a9e0eb1 100644 --- a/lint-requirements.txt +++ b/lint-requirements.txt @@ -1,6 +1,6 @@ bandit==1.7.0 black==21.9b0 -flake8==3.9.2 +flake8==4.0.1 isort==5.9.3 msgcheck==3.1 pydocstyle==6.1.1 From 252de6d332782bb5bd32d7668f9e5d8588582352 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Fri, 15 Oct 2021 21:08:13 +0000 Subject: [PATCH 34/98] Bump actions/checkout from 2.3.4 to 2.3.5 Bumps [actions/checkout](https://github.com/actions/checkout) from 2.3.4 to 2.3.5. - [Release notes](https://github.com/actions/checkout/releases) - [Changelog](https://github.com/actions/checkout/blob/main/CHANGELOG.md) - [Commits](https://github.com/actions/checkout/compare/v2.3.4...v2.3.5) --- updated-dependencies: - dependency-name: actions/checkout dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] --- .github/workflows/ci.yml | 10 +++++----- .github/workflows/release.yml | 2 +- 2 files changed, 6 insertions(+), 6 deletions(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 3ec3fd0..5c57457 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -13,7 +13,7 @@ jobs: runs-on: ubuntu-latest steps: - name: Checkout repository - uses: actions/checkout@v2.3.4 + uses: actions/checkout@v2.3.5 - name: Initialize CodeQL uses: github/codeql-action/init@v1 with: @@ -25,7 +25,7 @@ jobs: runs-on: ubuntu-latest steps: - uses: actions/setup-python@v2.2.2 - - uses: actions/checkout@v2.3.4 + - uses: actions/checkout@v2.3.5 - run: sudo apt install -y gettext aspell libenchant-dev - uses: actions/cache@v2.1.6 with: @@ -49,7 +49,7 @@ jobs: runs-on: ubuntu-latest steps: - uses: actions/setup-python@v2.2.2 - - uses: actions/checkout@v2.3.4 + - uses: actions/checkout@v2.3.5 - uses: actions/cache@v2.1.6 with: path: ~/.cache/pip @@ -67,7 +67,7 @@ jobs: run: sudo apt install gettext -y - uses: actions/setup-python@v2.2.2 - run: python -m pip install --upgrade pip setuptools wheel twine readme-renderer - - uses: actions/checkout@v2.3.4 + - uses: actions/checkout@v2.3.5 - run: python setup.py sdist bdist_wheel - run: python -m twine check dist/* - uses: actions/upload-artifact@v2 @@ -98,7 +98,7 @@ jobs: with: python-version: ${{ matrix.python-version }} - run: sudo apt install gettext -y - - uses: actions/checkout@v2.3.4 + - uses: actions/checkout@v2.3.5 - run: python -m pip install --upgrade pip setuptools codecov wheel - run: python -m pip install .[${{ matrix.extra }}] if: ${{ matrix.extra }} diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml index 30eb296..0be76e6 100644 --- a/.github/workflows/release.yml +++ b/.github/workflows/release.yml @@ -7,7 +7,7 @@ jobs: runs-on: ubuntu-latest steps: - - uses: actions/checkout@v2.3.4 + - uses: actions/checkout@v2.3.5 - name: Set up Python ${{ matrix.python-version }} uses: actions/setup-python@v2.2.2 with: From 79c462e352ef453bc424ec4f9dbf141e4fd1f3ed Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 1 Nov 2021 21:11:58 +0000 Subject: [PATCH 35/98] Bump black from 21.9b0 to 21.10b0 Bumps [black](https://github.com/psf/black) from 21.9b0 to 21.10b0. - [Release notes](https://github.com/psf/black/releases) - [Changelog](https://github.com/psf/black/blob/main/CHANGES.md) - [Commits](https://github.com/psf/black/commits) --- updated-dependencies: - dependency-name: black dependency-type: direct:production ... Signed-off-by: dependabot[bot] --- lint-requirements.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lint-requirements.txt b/lint-requirements.txt index a9e0eb1..3ef6243 100644 --- a/lint-requirements.txt +++ b/lint-requirements.txt @@ -1,5 +1,5 @@ bandit==1.7.0 -black==21.9b0 +black==21.10b0 flake8==4.0.1 isort==5.9.3 msgcheck==3.1 From ae1194a0982b7256b23c8ac1c9f83ebd1d989d4f Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Tue, 2 Nov 2021 21:09:53 +0000 Subject: [PATCH 36/98] Bump actions/checkout from 2.3.5 to 2.4.0 Bumps [actions/checkout](https://github.com/actions/checkout) from 2.3.5 to 2.4.0. - [Release notes](https://github.com/actions/checkout/releases) - [Changelog](https://github.com/actions/checkout/blob/main/CHANGELOG.md) - [Commits](https://github.com/actions/checkout/compare/v2.3.5...v2.4.0) --- updated-dependencies: - dependency-name: actions/checkout dependency-type: direct:production update-type: version-update:semver-minor ... Signed-off-by: dependabot[bot] --- .github/workflows/ci.yml | 10 +++++----- .github/workflows/release.yml | 2 +- 2 files changed, 6 insertions(+), 6 deletions(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 5c57457..6031a4a 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -13,7 +13,7 @@ jobs: runs-on: ubuntu-latest steps: - name: Checkout repository - uses: actions/checkout@v2.3.5 + uses: actions/checkout@v2.4.0 - name: Initialize CodeQL uses: github/codeql-action/init@v1 with: @@ -25,7 +25,7 @@ jobs: runs-on: ubuntu-latest steps: - uses: actions/setup-python@v2.2.2 - - uses: actions/checkout@v2.3.5 + - uses: actions/checkout@v2.4.0 - run: sudo apt install -y gettext aspell libenchant-dev - uses: actions/cache@v2.1.6 with: @@ -49,7 +49,7 @@ jobs: runs-on: ubuntu-latest steps: - uses: actions/setup-python@v2.2.2 - - uses: actions/checkout@v2.3.5 + - uses: actions/checkout@v2.4.0 - uses: actions/cache@v2.1.6 with: path: ~/.cache/pip @@ -67,7 +67,7 @@ jobs: run: sudo apt install gettext -y - uses: actions/setup-python@v2.2.2 - run: python -m pip install --upgrade pip setuptools wheel twine readme-renderer - - uses: actions/checkout@v2.3.5 + - uses: actions/checkout@v2.4.0 - run: python setup.py sdist bdist_wheel - run: python -m twine check dist/* - uses: actions/upload-artifact@v2 @@ -98,7 +98,7 @@ jobs: with: python-version: ${{ matrix.python-version }} - run: sudo apt install gettext -y - - uses: actions/checkout@v2.3.5 + - uses: actions/checkout@v2.4.0 - run: python -m pip install --upgrade pip setuptools codecov wheel - run: python -m pip install .[${{ matrix.extra }}] if: ${{ matrix.extra }} diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml index 0be76e6..e5b2d8a 100644 --- a/.github/workflows/release.yml +++ b/.github/workflows/release.yml @@ -7,7 +7,7 @@ jobs: runs-on: ubuntu-latest steps: - - uses: actions/checkout@v2.3.5 + - uses: actions/checkout@v2.4.0 - name: Set up Python ${{ matrix.python-version }} uses: actions/setup-python@v2.2.2 with: From aa3e2c8b90687c6d02043e98845dca9ae193258c Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Wed, 3 Nov 2021 21:10:44 +0000 Subject: [PATCH 37/98] Bump isort from 5.9.3 to 5.10.0 Bumps [isort](https://github.com/pycqa/isort) from 5.9.3 to 5.10.0. - [Release notes](https://github.com/pycqa/isort/releases) - [Changelog](https://github.com/PyCQA/isort/blob/main/CHANGELOG.md) - [Commits](https://github.com/pycqa/isort/compare/5.9.3...5.10.0) --- updated-dependencies: - dependency-name: isort dependency-type: direct:production update-type: version-update:semver-minor ... Signed-off-by: dependabot[bot] --- lint-requirements.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lint-requirements.txt b/lint-requirements.txt index 3ef6243..89827dc 100644 --- a/lint-requirements.txt +++ b/lint-requirements.txt @@ -1,6 +1,6 @@ bandit==1.7.0 black==21.10b0 flake8==4.0.1 -isort==5.9.3 +isort==5.10.0 msgcheck==3.1 pydocstyle==6.1.1 From 5f003b6d45149aaa845ea7650e7d29ff8fd3304b Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Tue, 9 Nov 2021 21:09:24 +0000 Subject: [PATCH 38/98] Bump isort from 5.10.0 to 5.10.1 Bumps [isort](https://github.com/pycqa/isort) from 5.10.0 to 5.10.1. - [Release notes](https://github.com/pycqa/isort/releases) - [Changelog](https://github.com/PyCQA/isort/blob/main/CHANGELOG.md) - [Commits](https://github.com/pycqa/isort/compare/5.10.0...5.10.1) --- updated-dependencies: - dependency-name: isort dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] --- lint-requirements.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lint-requirements.txt b/lint-requirements.txt index 89827dc..ac2dc85 100644 --- a/lint-requirements.txt +++ b/lint-requirements.txt @@ -1,6 +1,6 @@ bandit==1.7.0 black==21.10b0 flake8==4.0.1 -isort==5.10.0 +isort==5.10.1 msgcheck==3.1 pydocstyle==6.1.1 From 46843043e6a428b78433995b810ab49ab7e88157 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Fri, 12 Nov 2021 21:10:00 +0000 Subject: [PATCH 39/98] Bump bandit from 1.7.0 to 1.7.1 Bumps [bandit](https://github.com/PyCQA/bandit) from 1.7.0 to 1.7.1. - [Release notes](https://github.com/PyCQA/bandit/releases) - [Commits](https://github.com/PyCQA/bandit/compare/1.7.0...1.7.1) --- updated-dependencies: - dependency-name: bandit dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] --- lint-requirements.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lint-requirements.txt b/lint-requirements.txt index ac2dc85..9f34b44 100644 --- a/lint-requirements.txt +++ b/lint-requirements.txt @@ -1,4 +1,4 @@ -bandit==1.7.0 +bandit==1.7.1 black==21.10b0 flake8==4.0.1 isort==5.10.1 From 6471f750a2a45373bc85e3592841c4a584ec697a Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Wed, 17 Nov 2021 21:06:12 +0000 Subject: [PATCH 40/98] Bump actions/setup-python from 2.2.2 to 2.3.0 Bumps [actions/setup-python](https://github.com/actions/setup-python) from 2.2.2 to 2.3.0. - [Release notes](https://github.com/actions/setup-python/releases) - [Commits](https://github.com/actions/setup-python/compare/v2.2.2...v2.3.0) --- updated-dependencies: - dependency-name: actions/setup-python dependency-type: direct:production update-type: version-update:semver-minor ... Signed-off-by: dependabot[bot] --- .github/workflows/ci.yml | 8 ++++---- .github/workflows/release.yml | 2 +- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 6031a4a..f31567c 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -24,7 +24,7 @@ jobs: msgcheck: runs-on: ubuntu-latest steps: - - uses: actions/setup-python@v2.2.2 + - uses: actions/setup-python@v2.3.0 - uses: actions/checkout@v2.4.0 - run: sudo apt install -y gettext aspell libenchant-dev - uses: actions/cache@v2.1.6 @@ -48,7 +48,7 @@ jobs: - "pydocstyle ." runs-on: ubuntu-latest steps: - - uses: actions/setup-python@v2.2.2 + - uses: actions/setup-python@v2.3.0 - uses: actions/checkout@v2.4.0 - uses: actions/cache@v2.1.6 with: @@ -65,7 +65,7 @@ jobs: steps: - name: Install gettext run: sudo apt install gettext -y - - uses: actions/setup-python@v2.2.2 + - uses: actions/setup-python@v2.3.0 - run: python -m pip install --upgrade pip setuptools wheel twine readme-renderer - uses: actions/checkout@v2.4.0 - run: python setup.py sdist bdist_wheel @@ -94,7 +94,7 @@ jobs: - "progressbar" steps: - name: Set up Python ${{ matrix.python-version }} - uses: actions/setup-python@v2.2.2 + uses: actions/setup-python@v2.3.0 with: python-version: ${{ matrix.python-version }} - run: sudo apt install gettext -y diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml index e5b2d8a..aff83e7 100644 --- a/.github/workflows/release.yml +++ b/.github/workflows/release.yml @@ -9,7 +9,7 @@ jobs: steps: - uses: actions/checkout@v2.4.0 - name: Set up Python ${{ matrix.python-version }} - uses: actions/setup-python@v2.2.2 + uses: actions/setup-python@v2.3.0 with: python-version: ${{ matrix.python-version }} - name: Install gettext From 66d75c698982fc87c4bffc313ff5e8af27313696 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Thu, 18 Nov 2021 21:07:50 +0000 Subject: [PATCH 41/98] Bump black from 21.10b0 to 21.11b1 Bumps [black](https://github.com/psf/black) from 21.10b0 to 21.11b1. - [Release notes](https://github.com/psf/black/releases) - [Changelog](https://github.com/psf/black/blob/main/CHANGES.md) - [Commits](https://github.com/psf/black/commits) --- updated-dependencies: - dependency-name: black dependency-type: direct:production ... Signed-off-by: dependabot[bot] --- lint-requirements.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lint-requirements.txt b/lint-requirements.txt index 9f34b44..917b23b 100644 --- a/lint-requirements.txt +++ b/lint-requirements.txt @@ -1,5 +1,5 @@ bandit==1.7.1 -black==21.10b0 +black==21.11b1 flake8==4.0.1 isort==5.10.1 msgcheck==3.1 From 777f404fd6a04293160339da1c6e5371153531dd Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Tue, 23 Nov 2021 21:10:23 +0000 Subject: [PATCH 42/98] Bump actions/cache from 2.1.6 to 2.1.7 Bumps [actions/cache](https://github.com/actions/cache) from 2.1.6 to 2.1.7. - [Release notes](https://github.com/actions/cache/releases) - [Commits](https://github.com/actions/cache/compare/v2.1.6...v2.1.7) --- updated-dependencies: - dependency-name: actions/cache dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] --- .github/workflows/ci.yml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index f31567c..2cfcb60 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -27,7 +27,7 @@ jobs: - uses: actions/setup-python@v2.3.0 - uses: actions/checkout@v2.4.0 - run: sudo apt install -y gettext aspell libenchant-dev - - uses: actions/cache@v2.1.6 + - uses: actions/cache@v2.1.7 with: path: ~/.cache/pip key: ${{ runner.os }}-pip-${{ hashFiles('lint-requirements.txt') }} @@ -50,7 +50,7 @@ jobs: steps: - uses: actions/setup-python@v2.3.0 - uses: actions/checkout@v2.4.0 - - uses: actions/cache@v2.1.6 + - uses: actions/cache@v2.1.7 with: path: ~/.cache/pip key: ${{ runner.os }}-pip-${{ hashFiles('lint-requirements.txt') }} From 2171033f6883fad0dd61643b147767dddee8c48b Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 29 Nov 2021 21:12:32 +0000 Subject: [PATCH 43/98] Bump actions/setup-python from 2.3.0 to 2.3.1 Bumps [actions/setup-python](https://github.com/actions/setup-python) from 2.3.0 to 2.3.1. - [Release notes](https://github.com/actions/setup-python/releases) - [Commits](https://github.com/actions/setup-python/compare/v2.3.0...v2.3.1) --- updated-dependencies: - dependency-name: actions/setup-python dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] --- .github/workflows/ci.yml | 8 ++++---- .github/workflows/release.yml | 2 +- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 2cfcb60..3d354fb 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -24,7 +24,7 @@ jobs: msgcheck: runs-on: ubuntu-latest steps: - - uses: actions/setup-python@v2.3.0 + - uses: actions/setup-python@v2.3.1 - uses: actions/checkout@v2.4.0 - run: sudo apt install -y gettext aspell libenchant-dev - uses: actions/cache@v2.1.7 @@ -48,7 +48,7 @@ jobs: - "pydocstyle ." runs-on: ubuntu-latest steps: - - uses: actions/setup-python@v2.3.0 + - uses: actions/setup-python@v2.3.1 - uses: actions/checkout@v2.4.0 - uses: actions/cache@v2.1.7 with: @@ -65,7 +65,7 @@ jobs: steps: - name: Install gettext run: sudo apt install gettext -y - - uses: actions/setup-python@v2.3.0 + - uses: actions/setup-python@v2.3.1 - run: python -m pip install --upgrade pip setuptools wheel twine readme-renderer - uses: actions/checkout@v2.4.0 - run: python setup.py sdist bdist_wheel @@ -94,7 +94,7 @@ jobs: - "progressbar" steps: - name: Set up Python ${{ matrix.python-version }} - uses: actions/setup-python@v2.3.0 + uses: actions/setup-python@v2.3.1 with: python-version: ${{ matrix.python-version }} - run: sudo apt install gettext -y diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml index aff83e7..77e3f44 100644 --- a/.github/workflows/release.yml +++ b/.github/workflows/release.yml @@ -9,7 +9,7 @@ jobs: steps: - uses: actions/checkout@v2.4.0 - name: Set up Python ${{ matrix.python-version }} - uses: actions/setup-python@v2.3.0 + uses: actions/setup-python@v2.3.1 with: python-version: ${{ matrix.python-version }} - name: Install gettext From a1080640996b727fd9df8b94405c0df1a19b21c9 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 6 Dec 2021 21:10:55 +0000 Subject: [PATCH 44/98] Bump black from 21.11b1 to 21.12b0 Bumps [black](https://github.com/psf/black) from 21.11b1 to 21.12b0. - [Release notes](https://github.com/psf/black/releases) - [Changelog](https://github.com/psf/black/blob/main/CHANGES.md) - [Commits](https://github.com/psf/black/commits) --- updated-dependencies: - dependency-name: black dependency-type: direct:production ... Signed-off-by: dependabot[bot] --- lint-requirements.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lint-requirements.txt b/lint-requirements.txt index 917b23b..fc3ed5b 100644 --- a/lint-requirements.txt +++ b/lint-requirements.txt @@ -1,5 +1,5 @@ bandit==1.7.1 -black==21.11b1 +black==21.12b0 flake8==4.0.1 isort==5.10.1 msgcheck==3.1 From 07101ed8ffca598560db82af1a19370d9bb314bc Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 24 Jan 2022 21:10:59 +0000 Subject: [PATCH 45/98] Bump msgcheck from 3.1 to 4.0.0 Bumps [msgcheck](https://github.com/flashcode/msgcheck) from 3.1 to 4.0.0. - [Release notes](https://github.com/flashcode/msgcheck/releases) - [Changelog](https://github.com/flashcode/msgcheck/blob/master/ChangeLog.md) - [Commits](https://github.com/flashcode/msgcheck/compare/v3.1...v4.0.0) --- updated-dependencies: - dependency-name: msgcheck dependency-type: direct:production update-type: version-update:semver-major ... Signed-off-by: dependabot[bot] --- lint-requirements.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lint-requirements.txt b/lint-requirements.txt index fc3ed5b..4d5a068 100644 --- a/lint-requirements.txt +++ b/lint-requirements.txt @@ -2,5 +2,5 @@ bandit==1.7.1 black==21.12b0 flake8==4.0.1 isort==5.10.1 -msgcheck==3.1 +msgcheck==4.0.0 pydocstyle==6.1.1 From 5162d916b303e9b9417ec0311c88ca1e605d8e23 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Wed, 26 Jan 2022 21:10:33 +0000 Subject: [PATCH 46/98] Bump bandit from 1.7.1 to 1.7.2 Bumps [bandit](https://github.com/PyCQA/bandit) from 1.7.1 to 1.7.2. - [Release notes](https://github.com/PyCQA/bandit/releases) - [Commits](https://github.com/PyCQA/bandit/compare/1.7.1...1.7.2) --- updated-dependencies: - dependency-name: bandit dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] --- lint-requirements.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lint-requirements.txt b/lint-requirements.txt index 4d5a068..b445147 100644 --- a/lint-requirements.txt +++ b/lint-requirements.txt @@ -1,4 +1,4 @@ -bandit==1.7.1 +bandit==1.7.2 black==21.12b0 flake8==4.0.1 isort==5.10.1 From 4bf3bcdd147544e6fbb95a1a7da317c92aa20784 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 31 Jan 2022 21:08:59 +0000 Subject: [PATCH 47/98] Bump black from 21.12b0 to 22.1.0 Bumps [black](https://github.com/psf/black) from 21.12b0 to 22.1.0. - [Release notes](https://github.com/psf/black/releases) - [Changelog](https://github.com/psf/black/blob/main/CHANGES.md) - [Commits](https://github.com/psf/black/commits/22.1.0) --- updated-dependencies: - dependency-name: black dependency-type: direct:production ... Signed-off-by: dependabot[bot] --- lint-requirements.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lint-requirements.txt b/lint-requirements.txt index b445147..aab7a21 100644 --- a/lint-requirements.txt +++ b/lint-requirements.txt @@ -1,5 +1,5 @@ bandit==1.7.2 -black==21.12b0 +black==22.1.0 flake8==4.0.1 isort==5.10.1 msgcheck==4.0.0 From fbab25668bfb0ec079cf73e190d8f06ec87066fe Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Fri, 4 Feb 2022 21:08:13 +0000 Subject: [PATCH 48/98] Bump actions/setup-python from 2.3.1 to 2.3.2 Bumps [actions/setup-python](https://github.com/actions/setup-python) from 2.3.1 to 2.3.2. - [Release notes](https://github.com/actions/setup-python/releases) - [Commits](https://github.com/actions/setup-python/compare/v2.3.1...v2.3.2) --- updated-dependencies: - dependency-name: actions/setup-python dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] --- .github/workflows/ci.yml | 8 ++++---- .github/workflows/release.yml | 2 +- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 3d354fb..fb911e7 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -24,7 +24,7 @@ jobs: msgcheck: runs-on: ubuntu-latest steps: - - uses: actions/setup-python@v2.3.1 + - uses: actions/setup-python@v2.3.2 - uses: actions/checkout@v2.4.0 - run: sudo apt install -y gettext aspell libenchant-dev - uses: actions/cache@v2.1.7 @@ -48,7 +48,7 @@ jobs: - "pydocstyle ." runs-on: ubuntu-latest steps: - - uses: actions/setup-python@v2.3.1 + - uses: actions/setup-python@v2.3.2 - uses: actions/checkout@v2.4.0 - uses: actions/cache@v2.1.7 with: @@ -65,7 +65,7 @@ jobs: steps: - name: Install gettext run: sudo apt install gettext -y - - uses: actions/setup-python@v2.3.1 + - uses: actions/setup-python@v2.3.2 - run: python -m pip install --upgrade pip setuptools wheel twine readme-renderer - uses: actions/checkout@v2.4.0 - run: python setup.py sdist bdist_wheel @@ -94,7 +94,7 @@ jobs: - "progressbar" steps: - name: Set up Python ${{ matrix.python-version }} - uses: actions/setup-python@v2.3.1 + uses: actions/setup-python@v2.3.2 with: python-version: ${{ matrix.python-version }} - run: sudo apt install gettext -y diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml index 77e3f44..0f42f0e 100644 --- a/.github/workflows/release.yml +++ b/.github/workflows/release.yml @@ -9,7 +9,7 @@ jobs: steps: - uses: actions/checkout@v2.4.0 - name: Set up Python ${{ matrix.python-version }} - uses: actions/setup-python@v2.3.1 + uses: actions/setup-python@v2.3.2 with: python-version: ${{ matrix.python-version }} - name: Install gettext From 7185d45c62bd0130962cd706bac1a470ff921726 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 28 Feb 2022 21:08:14 +0000 Subject: [PATCH 49/98] Bump actions/setup-python from 2.3.2 to 3 Bumps [actions/setup-python](https://github.com/actions/setup-python) from 2.3.2 to 3. - [Release notes](https://github.com/actions/setup-python/releases) - [Commits](https://github.com/actions/setup-python/compare/v2.3.2...v3) --- updated-dependencies: - dependency-name: actions/setup-python dependency-type: direct:production update-type: version-update:semver-major ... Signed-off-by: dependabot[bot] --- .github/workflows/ci.yml | 8 ++++---- .github/workflows/release.yml | 2 +- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index fb911e7..8080858 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -24,7 +24,7 @@ jobs: msgcheck: runs-on: ubuntu-latest steps: - - uses: actions/setup-python@v2.3.2 + - uses: actions/setup-python@v3 - uses: actions/checkout@v2.4.0 - run: sudo apt install -y gettext aspell libenchant-dev - uses: actions/cache@v2.1.7 @@ -48,7 +48,7 @@ jobs: - "pydocstyle ." runs-on: ubuntu-latest steps: - - uses: actions/setup-python@v2.3.2 + - uses: actions/setup-python@v3 - uses: actions/checkout@v2.4.0 - uses: actions/cache@v2.1.7 with: @@ -65,7 +65,7 @@ jobs: steps: - name: Install gettext run: sudo apt install gettext -y - - uses: actions/setup-python@v2.3.2 + - uses: actions/setup-python@v3 - run: python -m pip install --upgrade pip setuptools wheel twine readme-renderer - uses: actions/checkout@v2.4.0 - run: python setup.py sdist bdist_wheel @@ -94,7 +94,7 @@ jobs: - "progressbar" steps: - name: Set up Python ${{ matrix.python-version }} - uses: actions/setup-python@v2.3.2 + uses: actions/setup-python@v3 with: python-version: ${{ matrix.python-version }} - run: sudo apt install gettext -y diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml index 0f42f0e..c9e6fc5 100644 --- a/.github/workflows/release.yml +++ b/.github/workflows/release.yml @@ -9,7 +9,7 @@ jobs: steps: - uses: actions/checkout@v2.4.0 - name: Set up Python ${{ matrix.python-version }} - uses: actions/setup-python@v2.3.2 + uses: actions/setup-python@v3 with: python-version: ${{ matrix.python-version }} - name: Install gettext From e28f0c9593ddf4a11e9f9df1166f4f6e64eb9bf6 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 28 Feb 2022 21:08:48 +0000 Subject: [PATCH 50/98] Bump bandit from 1.7.2 to 1.7.3 Bumps [bandit](https://github.com/PyCQA/bandit) from 1.7.2 to 1.7.3. - [Release notes](https://github.com/PyCQA/bandit/releases) - [Commits](https://github.com/PyCQA/bandit/compare/1.7.2...1.7.3) --- updated-dependencies: - dependency-name: bandit dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] --- lint-requirements.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lint-requirements.txt b/lint-requirements.txt index aab7a21..7bc2f07 100644 --- a/lint-requirements.txt +++ b/lint-requirements.txt @@ -1,4 +1,4 @@ -bandit==1.7.2 +bandit==1.7.3 black==22.1.0 flake8==4.0.1 isort==5.10.1 From 500e5d9ff55a30a18e1c6e7fea39b14008da67d2 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Fri, 4 Mar 2022 21:06:51 +0000 Subject: [PATCH 51/98] Bump bandit from 1.7.3 to 1.7.4 Bumps [bandit](https://github.com/PyCQA/bandit) from 1.7.3 to 1.7.4. - [Release notes](https://github.com/PyCQA/bandit/releases) - [Commits](https://github.com/PyCQA/bandit/compare/1.7.3...1.7.4) --- updated-dependencies: - dependency-name: bandit dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] --- lint-requirements.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lint-requirements.txt b/lint-requirements.txt index 7bc2f07..50ab327 100644 --- a/lint-requirements.txt +++ b/lint-requirements.txt @@ -1,4 +1,4 @@ -bandit==1.7.3 +bandit==1.7.4 black==22.1.0 flake8==4.0.1 isort==5.10.1 From 2d9c7dc1f4bc0b8fbf9d3d80e6dcb5d1a219118b Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Tue, 1 Mar 2022 21:11:11 +0000 Subject: [PATCH 52/98] Bump actions/checkout from 2.4.0 to 3 Bumps [actions/checkout](https://github.com/actions/checkout) from 2.4.0 to 3. - [Release notes](https://github.com/actions/checkout/releases) - [Changelog](https://github.com/actions/checkout/blob/main/CHANGELOG.md) - [Commits](https://github.com/actions/checkout/compare/v2.4.0...v3) --- updated-dependencies: - dependency-name: actions/checkout dependency-type: direct:production update-type: version-update:semver-major ... Signed-off-by: dependabot[bot] --- .github/workflows/ci.yml | 10 +++++----- .github/workflows/release.yml | 2 +- 2 files changed, 6 insertions(+), 6 deletions(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 8080858..9d0f56f 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -13,7 +13,7 @@ jobs: runs-on: ubuntu-latest steps: - name: Checkout repository - uses: actions/checkout@v2.4.0 + uses: actions/checkout@v3 - name: Initialize CodeQL uses: github/codeql-action/init@v1 with: @@ -25,7 +25,7 @@ jobs: runs-on: ubuntu-latest steps: - uses: actions/setup-python@v3 - - uses: actions/checkout@v2.4.0 + - uses: actions/checkout@v3 - run: sudo apt install -y gettext aspell libenchant-dev - uses: actions/cache@v2.1.7 with: @@ -49,7 +49,7 @@ jobs: runs-on: ubuntu-latest steps: - uses: actions/setup-python@v3 - - uses: actions/checkout@v2.4.0 + - uses: actions/checkout@v3 - uses: actions/cache@v2.1.7 with: path: ~/.cache/pip @@ -67,7 +67,7 @@ jobs: run: sudo apt install gettext -y - uses: actions/setup-python@v3 - run: python -m pip install --upgrade pip setuptools wheel twine readme-renderer - - uses: actions/checkout@v2.4.0 + - uses: actions/checkout@v3 - run: python setup.py sdist bdist_wheel - run: python -m twine check dist/* - uses: actions/upload-artifact@v2 @@ -98,7 +98,7 @@ jobs: with: python-version: ${{ matrix.python-version }} - run: sudo apt install gettext -y - - uses: actions/checkout@v2.4.0 + - uses: actions/checkout@v3 - run: python -m pip install --upgrade pip setuptools codecov wheel - run: python -m pip install .[${{ matrix.extra }}] if: ${{ matrix.extra }} diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml index c9e6fc5..bfa7850 100644 --- a/.github/workflows/release.yml +++ b/.github/workflows/release.yml @@ -7,7 +7,7 @@ jobs: runs-on: ubuntu-latest steps: - - uses: actions/checkout@v2.4.0 + - uses: actions/checkout@v3 - name: Set up Python ${{ matrix.python-version }} uses: actions/setup-python@v3 with: From 4848948680acc8dd301d91c923420d51fc362f55 Mon Sep 17 00:00:00 2001 From: Christopher Banck Date: Wed, 16 Mar 2022 08:55:34 +0100 Subject: [PATCH 53/98] test with django 4 and python 3.10 --- .github/workflows/ci.yml | 9 +++++++++ setup.cfg | 2 ++ tests/settings.py | 2 +- 3 files changed, 12 insertions(+), 1 deletion(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 9d0f56f..a54c68e 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -85,13 +85,22 @@ jobs: - "3.7" - "3.8" - "3.9" + - "3.10" django-version: - "2.2.*" - "3.1.*" - "3.2.*" + - "4.0.*" extra: - "" - "progressbar" + exclude: + - python-version: "3.7" + django-version: "4.0.*" + - python-version: "3.10" + django-version: "3.1.*" + - python-version: "3.10" + django-version: "2.2.*" steps: - name: Set up Python ${{ matrix.python-version }} uses: actions/setup-python@v3 diff --git a/setup.cfg b/setup.cfg index 696d7c0..3b0ff1f 100644 --- a/setup.cfg +++ b/setup.cfg @@ -23,10 +23,12 @@ classifier = Programming Language :: Python :: 3.7 Programming Language :: Python :: 3.8 Programming Language :: Python :: 3.9 + Programming Language :: Python :: 3.10 Framework :: Django Framework :: Django :: 2.2 Framework :: Django :: 3.1 Framework :: Django :: 3.2 + Framework :: Django :: 4.0 python_requires = >=3.7 diff --git a/tests/settings.py b/tests/settings.py index 03ebbd9..480a744 100644 --- a/tests/settings.py +++ b/tests/settings.py @@ -45,4 +45,4 @@ SECRET_KEY = "foobar" -USE_L10N = True +USE_TZ = True From 901dbeb9b3d9bb4698733cc5280c4d55627a09bb Mon Sep 17 00:00:00 2001 From: Johannes Maron Date: Sat, 19 Mar 2022 15:59:17 +0100 Subject: [PATCH 54/98] Drop Django and Python EOL versions --- .github/workflows/ci.yml | 18 ++++-------------- setup.cfg | 5 +---- 2 files changed, 5 insertions(+), 18 deletions(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index a54c68e..671a50c 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -82,25 +82,15 @@ jobs: strategy: matrix: python-version: - - "3.7" - "3.8" - "3.9" - - "3.10" + - "3.10" django-version: - - "2.2.*" - - "3.1.*" - - "3.2.*" - - "4.0.*" + - "3.2a" + - "4.0a" extra: - "" - "progressbar" - exclude: - - python-version: "3.7" - django-version: "4.0.*" - - python-version: "3.10" - django-version: "3.1.*" - - python-version: "3.10" - django-version: "2.2.*" steps: - name: Set up Python ${{ matrix.python-version }} uses: actions/setup-python@v3 @@ -111,7 +101,7 @@ jobs: - run: python -m pip install --upgrade pip setuptools codecov wheel - run: python -m pip install .[${{ matrix.extra }}] if: ${{ matrix.extra }} - - run: python -m pip install django==${{ matrix.django-version }} + - run: python -m pip install django~=${{ matrix.django-version }} - name: Test with pytest run: python setup.py test - run: codecov diff --git a/setup.cfg b/setup.cfg index 3b0ff1f..10e8e2b 100644 --- a/setup.cfg +++ b/setup.cfg @@ -20,17 +20,14 @@ classifier = Topic :: Software Development Programming Language :: Python :: 3 Programming Language :: Python :: 3 :: Only - Programming Language :: Python :: 3.7 Programming Language :: Python :: 3.8 Programming Language :: Python :: 3.9 Programming Language :: Python :: 3.10 Framework :: Django - Framework :: Django :: 2.2 - Framework :: Django :: 3.1 Framework :: Django :: 3.2 Framework :: Django :: 4.0 -python_requires = >=3.7 +python_requires = >=3.8 [options] include_package_data = True From 90cf8de7fc0e2f31f8034e7f53ababcb5795c31a Mon Sep 17 00:00:00 2001 From: Johannes Maron Date: Sat, 19 Mar 2022 15:59:38 +0100 Subject: [PATCH 55/98] Drop analyze CI build --- .github/workflows/ci.yml | 13 ------------- 1 file changed, 13 deletions(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 671a50c..22dbeec 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -8,19 +8,6 @@ on: jobs: - analyze: - name: CodeQL - runs-on: ubuntu-latest - steps: - - name: Checkout repository - uses: actions/checkout@v3 - - name: Initialize CodeQL - uses: github/codeql-action/init@v1 - with: - languages: python - - name: Perform CodeQL Analysis - uses: github/codeql-action/analyze@v1 - msgcheck: runs-on: ubuntu-latest steps: From 10de7724f913f711b620070976253a0807d753e8 Mon Sep 17 00:00:00 2001 From: vchrisb Date: Wed, 17 Nov 2021 14:45:51 +0100 Subject: [PATCH 56/98] Fix #246 -- Add support for deepcopy --- stdimage/models.py | 19 +++++++++++++++++++ tests/test_models.py | 45 ++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 64 insertions(+) diff --git a/stdimage/models.py b/stdimage/models.py index 0eb6943..97ff514 100644 --- a/stdimage/models.py +++ b/stdimage/models.py @@ -144,6 +144,25 @@ def delete_variations(self): variation_name = self.get_variation_name(self.name, variation) self.storage.delete(variation_name) + def __getstate__(self): + state = super().__getstate__() + state["variations"] = {} + for variation_name in self.field.variations: + variation = getattr(self, variation_name) + variation_state = variation.__getstate__() + state["variations"][variation_name] = variation_state + return state + + def __setstate__(self, state): + variations = state["variations"] + state.pop("variations") + super().__setstate__(state) + for key, value in variations.items(): + cls = ImageFieldFile + field = cls.__new__(cls) + setattr(self, key, field) + getattr(self, key).__setstate__(value) + class StdImageField(ImageField): """ diff --git a/tests/test_models.py b/tests/test_models.py index 772737d..e8d47f2 100644 --- a/tests/test_models.py +++ b/tests/test_models.py @@ -1,13 +1,17 @@ import io import os import time +from copy import deepcopy import pytest from django.conf import settings from django.core.files.storage import default_storage from django.core.files.uploadedfile import SimpleUploadedFile +from django.db.models.fields.files import ImageFieldFile from PIL import Image +from stdimage.models import StdImageFieldFile + from . import models from .models import ( AdminDeleteModel, @@ -170,6 +174,47 @@ def test_defer(self, db, django_assert_num_queries): deferred.image assert instance.image.thumbnail == deferred.image.thumbnail + @pytest.mark.django_db + def test_variations_deepcopy(self): + """Tests test_variations() with a deep copied object""" + instance_original = ResizeModel.objects.create( + image=self.fixtures["600x400.jpg"] + ) + instance = deepcopy(instance_original) + assert isinstance(instance.image, StdImageFieldFile) + + assert hasattr(instance.image, "thumbnail") + assert hasattr(instance.image, "medium") + + assert isinstance(instance.image.thumbnail, ImageFieldFile) + assert isinstance(instance.image.medium, ImageFieldFile) + + source_file = self.fixtures["600x400.jpg"] + + assert os.path.exists(os.path.join(IMG_DIR, "600x400.jpg")) + assert instance.image.width == 600 + assert instance.image.height == 400 + path = os.path.join(IMG_DIR, "600x400.jpg") + + with open(path, "rb") as f: + source_file.seek(0) + assert source_file.read() == f.read() + + path = os.path.join(IMG_DIR, "600x400.medium.jpg") + assert os.path.exists(path) + assert instance.image.medium.width == 400 + assert instance.image.medium.height <= 400 + with open(os.path.join(IMG_DIR, "600x400.medium.jpg"), "rb") as f: + source_file.seek(0) + assert source_file.read() != f.read() + + assert os.path.exists(os.path.join(IMG_DIR, "600x400.thumbnail.jpg")) + assert instance.image.thumbnail.width == 100 + assert instance.image.thumbnail.height <= 75 + with open(os.path.join(IMG_DIR, "600x400.thumbnail.jpg"), "rb") as f: + source_file.seek(0) + assert source_file.read() != f.read() + class TestUtils(TestStdImage): """Tests Utils""" From c18976117ac1ec7501fb62de3eeb3125c890e161 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 21 Mar 2022 21:11:30 +0000 Subject: [PATCH 57/98] Bump actions/cache from 2.1.7 to 3 Bumps [actions/cache](https://github.com/actions/cache) from 2.1.7 to 3. - [Release notes](https://github.com/actions/cache/releases) - [Commits](https://github.com/actions/cache/compare/v2.1.7...v3) --- updated-dependencies: - dependency-name: actions/cache dependency-type: direct:production update-type: version-update:semver-major ... Signed-off-by: dependabot[bot] --- .github/workflows/ci.yml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 22dbeec..c6569c7 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -14,7 +14,7 @@ jobs: - uses: actions/setup-python@v3 - uses: actions/checkout@v3 - run: sudo apt install -y gettext aspell libenchant-dev - - uses: actions/cache@v2.1.7 + - uses: actions/cache@v3 with: path: ~/.cache/pip key: ${{ runner.os }}-pip-${{ hashFiles('lint-requirements.txt') }} @@ -37,7 +37,7 @@ jobs: steps: - uses: actions/setup-python@v3 - uses: actions/checkout@v3 - - uses: actions/cache@v2.1.7 + - uses: actions/cache@v3 with: path: ~/.cache/pip key: ${{ runner.os }}-pip-${{ hashFiles('lint-requirements.txt') }} From c0e16459d795dffbbea05cb1ea9296b62509752e Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 28 Mar 2022 21:11:02 +0000 Subject: [PATCH 58/98] Bump black from 22.1.0 to 22.3.0 Bumps [black](https://github.com/psf/black) from 22.1.0 to 22.3.0. - [Release notes](https://github.com/psf/black/releases) - [Changelog](https://github.com/psf/black/blob/main/CHANGES.md) - [Commits](https://github.com/psf/black/compare/22.1.0...22.3.0) --- updated-dependencies: - dependency-name: black dependency-type: direct:production update-type: version-update:semver-minor ... Signed-off-by: dependabot[bot] --- lint-requirements.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lint-requirements.txt b/lint-requirements.txt index 50ab327..7aae3f5 100644 --- a/lint-requirements.txt +++ b/lint-requirements.txt @@ -1,5 +1,5 @@ bandit==1.7.4 -black==22.1.0 +black==22.3.0 flake8==4.0.1 isort==5.10.1 msgcheck==4.0.0 From c3d520dc2d5c4f6e48db2a626667291a578090b3 Mon Sep 17 00:00:00 2001 From: Johannes Maron Date: Mon, 4 Apr 2022 14:25:14 +0200 Subject: [PATCH 59/98] Update release action --- .github/workflows/release.yml | 17 +++++------------ 1 file changed, 5 insertions(+), 12 deletions(-) diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml index bfa7850..ff70343 100644 --- a/.github/workflows/release.yml +++ b/.github/workflows/release.yml @@ -8,18 +8,11 @@ jobs: runs-on: ubuntu-latest steps: - uses: actions/checkout@v3 - - name: Set up Python ${{ matrix.python-version }} - uses: actions/setup-python@v3 - with: - python-version: ${{ matrix.python-version }} - - name: Install gettext - run: sudo apt-get install gettext -y - - name: Install dependencies - run: python -m pip install --upgrade pip setuptools wheel twine - - name: Build dist packages - run: python setup.py sdist bdist_wheel - - name: Upload packages - run: python -m twine upload dist/* + - uses: actions/setup-python@v3 + - run: sudo apt-get install gettext -y + - run: python -m pip install --upgrade pip build wheel twine + - run: python -m build --sdist --wheel + - run: python -m twine upload dist/* env: TWINE_USERNAME: ${{ secrets.TWINE_USERNAME }} TWINE_PASSWORD: ${{ secrets.TWINE_PASSWORD }} From 6f636a9f0bae5cc377dcd8b0b58220500a2a19f2 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Fri, 8 Apr 2022 21:06:47 +0000 Subject: [PATCH 60/98] Bump actions/upload-artifact from 2 to 3 Bumps [actions/upload-artifact](https://github.com/actions/upload-artifact) from 2 to 3. - [Release notes](https://github.com/actions/upload-artifact/releases) - [Commits](https://github.com/actions/upload-artifact/compare/v2...v3) --- updated-dependencies: - dependency-name: actions/upload-artifact dependency-type: direct:production update-type: version-update:semver-major ... Signed-off-by: dependabot[bot] --- .github/workflows/ci.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index c6569c7..3cdbc39 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -57,7 +57,7 @@ jobs: - uses: actions/checkout@v3 - run: python setup.py sdist bdist_wheel - run: python -m twine check dist/* - - uses: actions/upload-artifact@v2 + - uses: actions/upload-artifact@v3 with: path: dist/* From c2aa355b7a0af30a0715062e12adb204a99119e1 Mon Sep 17 00:00:00 2001 From: J Harley <502818+julzhk@users.noreply.github.com> Date: Tue, 26 Apr 2022 15:51:21 -0300 Subject: [PATCH 61/98] minor type in readme Otherwise: spelling --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index cc70313..2144030 100644 --- a/README.md +++ b/README.md @@ -191,5 +191,5 @@ python manage.py rendervariations 'app_name.model_name.field_name' [--replace] [ ``` The `replace` option will replace all existing files. The `ignore-missing` option will suspend missing source file errors and keep -rendering variations for other files. Othervise command will stop on first +rendering variations for other files. Otherwise command will stop on first missing file. From 39e2306f29863ab6cb22cb264d606afc8127cc88 Mon Sep 17 00:00:00 2001 From: J Harley <502818+julzhk@users.noreply.github.com> Date: Wed, 27 Apr 2022 10:58:09 -0300 Subject: [PATCH 62/98] Update Readme.md More extensive edit for clarity and readability --- README.md | 86 ++++++++++++++++++++++++++++++++++++------------------- 1 file changed, 57 insertions(+), 29 deletions(-) diff --git a/README.md b/README.md index 2144030..b006efc 100644 --- a/README.md +++ b/README.md @@ -4,19 +4,29 @@ # Django Standardized Image Field -Django Field that implement the following features: +## Why would I want this? -* Django-Storages compatible (S3) -* Resize images to different sizes +This is a drop-in replacement for the [Django ImageField](https://docs.djangoproject.com/en/1.8/ref/models/fields/#django.db.models.ImageField) that provides a standardized way to handle image uploads. +It is designed to be as easy to use as possible, and to provide a consistent interface for all image fields. +It allows images to be presented in various size variants (eg:thumbnails, mid, and hi-res versions) +and it provides a way to handle images that are too large with validators. + + +## Features + +Django Standardized Image Field implements the following features: + +* [Django-Storages](https://django-storages.readthedocs.io/en/latest/) compatible (eg: S3, Azure, Google Cloud Storage, etc) +* Resizes images to different sizes * Access thumbnails on model level, no template tags required -* Preserves original image -* Asynchronous rendering (Celery & Co) -* Restrict accepted image dimensions -* Rename files to a standardized name (using a callable upload_to) +* Preserves original images +* Can be rendered asynchronously (ie as a [Celery job](https://realpython.com/asynchronous-tasks-with-django-and-celery/)) +* Restricts acceptable image dimensions +* Renames file to a standardized name format (using a callable `upload_to` function, see below) ## Installation -Simply install the latest stable package using the command +Simply install the latest stable package using the following command ```bash pip install django-stdimage @@ -28,11 +38,13 @@ and add `'stdimage'` to `INSTALLED_APP`s in your settings.py, that's it! ## Usage +Now it's instally you can use either: `StdImageField` or `JPEGField`. + `StdImageField` works just like Django's own [ImageField](https://docs.djangoproject.com/en/dev/ref/models/fields/#imagefield) -except that you can specify different sized variations. +except that you can specify different size variations. -The `JPEGField` works similar to the `StdImageField` but all size variations are +The `JPEGField` is the same as the `StdImageField` but all images are converted to JPEGs, no matter what type the original file is. ### Variations @@ -58,7 +70,7 @@ class MyModel(models.Model): # is the same as dictionary-style call image = StdImageField(upload_to='path/to/img', variations={'thumbnail': (100, 75)}) - # variations are converted to JPEGs + # JPEGField variations are converted to JPEGs. jpeg = JPEGField( upload_to='path/to/img', variations={'full': (None, None), 'thumbnail': (100, 75)}, @@ -77,7 +89,7 @@ class MyModel(models.Model): }, delete_orphans=True) ``` -For using generated variations in templates use `myimagefield.variation_name`. +To use these variations in templates use `myimagefield.variation_name`. Example: @@ -85,15 +97,32 @@ Example: ``` -### Utils +### Upload to function + +You can use a function for the `upload_to` argument. Using [Django Dynamic Filenames][dynamic_filenames].[dynamic_filenames]: https://github.com/codingjoe/django-dynamic-filenames -Since version 4 the custom `upload_to` utils have been dropped in favor of -[Django Dynamic Filenames][dynamic_filenames]. +This allows images to be given unique paths and filenames based on the model instance. -[dynamic_filenames]: https://github.com/codingjoe/django-dynamic-filenames +Example + +```python +from django.db import models +from stdimage import StdImageField +from dynamic_filenames import FilePattern + +upload_to_pattern = FilePattern( + filename_pattern='my_model/{app_label:.25}/{model_name:.30}/{uuid:base32}{ext}', +) + + +class MyModel(models.Model): + # works just like django's ImageField + image = StdImageField(upload_to=upload_to_pattern) +``` ### Validators -The `StdImageField` doesn't implement any size validation. Validation can be specified using the validator attribute +The `StdImageField` doesn't implement any size validation out-of-the-box. +However, Validation can be specified using the validator attribute and using a set of validators shipped with this package. Validators can be used for both Forms and Models. @@ -120,9 +149,9 @@ Django [dropped support](https://docs.djangoproject.com/en/dev/releases/1.3/#del for automated deletions in version 1.3. Since version 5, this package supports a `delete_orphans` argument. It will delete -orphaned files, should a file be delete or replaced via Django form or and object with -a `StdImageField` be deleted. It will not be deleted if the field value is changed or -reassigned programatically. In those rare cases, you will need to handle proper deletion +orphaned files, should a file be deleted or replaced via a Django form and the object with +the `StdImageField` be deleted. It will not delete files if the field value is changed or +reassigned programatically. In these rare cases, you will need to handle proper deletion yourself. ```python @@ -141,10 +170,10 @@ class MyModel(models.Model): ### Async image processing Tools like celery allow to execute time-consuming tasks outside of the request. If you don't want -to wait for your variations to be rendered in request, StdImage provides your the option to pass a -async keyword and a util. -Note that the callback is not transaction save, but the file will be there. -This example is based on celery. +to wait for your variations to be rendered in request, StdImage provides you the option to pass an +async keyword and a 'render_variations' function that triggers the async task. +Note that the callback is not transaction save, but the file variations will be present. +The example below is based on celery. `tasks.py`: ```python @@ -177,19 +206,18 @@ def image_processor(file_name, variations, storage): class AsyncImageModel(models.Model): image = StdImageField( # above task definition can only handle one model object per image filename - upload_to='path/to/file/', + upload_to='path/to/file/', # or use a function render_variations=image_processor # pass boolean or callable ) processed = models.BooleanField(default=False) # flag that could be used for view querysets ``` ### Re-rendering variations -You might want to add new variations to a field. That means you need to render new variations for missing fields. +You might have added or changed variations to an existing field. That means you will need to render new variations. This can be accomplished using a management command. ```bash python manage.py rendervariations 'app_name.model_name.field_name' [--replace] [-i/--ignore-missing] ``` The `replace` option will replace all existing files. -The `ignore-missing` option will suspend missing source file errors and keep -rendering variations for other files. Otherwise command will stop on first -missing file. +The `ignore-missing` option will suspend 'missing source file' errors and keep +rendering variations for other files. Otherwise, the command will stop on first missing file. From bec1c82fde5958eba0743c6733ade5fafaacb0bc Mon Sep 17 00:00:00 2001 From: J Harley <502818+julzhk@users.noreply.github.com> Date: Tue, 3 May 2022 09:08:34 -0300 Subject: [PATCH 63/98] Update README.md Co-authored-by: Johannes Maron --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index b006efc..e1d3f63 100644 --- a/README.md +++ b/README.md @@ -22,7 +22,7 @@ Django Standardized Image Field implements the following features: * Preserves original images * Can be rendered asynchronously (ie as a [Celery job](https://realpython.com/asynchronous-tasks-with-django-and-celery/)) * Restricts acceptable image dimensions -* Renames file to a standardized name format (using a callable `upload_to` function, see below) +* Renames a file to a standardized name format (using a callable `upload_to` function, see below) ## Installation From bed5fed42062d14a43c55c1335cbbf3d3f05ed49 Mon Sep 17 00:00:00 2001 From: J Harley <502818+julzhk@users.noreply.github.com> Date: Tue, 3 May 2022 09:08:48 -0300 Subject: [PATCH 64/98] Update README.md Co-authored-by: Johannes Maron --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index e1d3f63..cac50c5 100644 --- a/README.md +++ b/README.md @@ -26,7 +26,7 @@ Django Standardized Image Field implements the following features: ## Installation -Simply install the latest stable package using the following command +Simply install the latest stable package using the following command: ```bash pip install django-stdimage From f6d953b0cd480a037964b259d379e8d1b2ab9b88 Mon Sep 17 00:00:00 2001 From: J Harley <502818+julzhk@users.noreply.github.com> Date: Tue, 3 May 2022 09:09:14 -0300 Subject: [PATCH 65/98] Update README.md Co-authored-by: Johannes Maron --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index cac50c5..c602c24 100644 --- a/README.md +++ b/README.md @@ -44,7 +44,7 @@ Now it's instally you can use either: `StdImageField` or `JPEGField`. [ImageField](https://docs.djangoproject.com/en/dev/ref/models/fields/#imagefield) except that you can specify different size variations. -The `JPEGField` is the same as the `StdImageField` but all images are +The `JPEGField` is identical to the `StdImageField` but all images are converted to JPEGs, no matter what type the original file is. ### Variations From 7db39615f709dccf839f90503b2baa76cbd48896 Mon Sep 17 00:00:00 2001 From: Johannes Maron Date: Sat, 21 May 2022 11:53:17 +0200 Subject: [PATCH 66/98] Update CI pipline (#288) --- .github/workflows/ci.yml | 27 ++++++++++++--------------- .github/workflows/release.yml | 10 ++++++---- setup.cfg | 16 +++++++--------- 3 files changed, 25 insertions(+), 28 deletions(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 3cdbc39..3070c08 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -46,16 +46,14 @@ jobs: - run: python -m pip install -r lint-requirements.txt - run: ${{ matrix.lint-command }} - dist: runs-on: ubuntu-latest steps: - - name: Install gettext - run: sudo apt install gettext -y - - uses: actions/setup-python@v3 - - run: python -m pip install --upgrade pip setuptools wheel twine readme-renderer - uses: actions/checkout@v3 - - run: python setup.py sdist bdist_wheel + - uses: actions/setup-python@v3 + - run: sudo apt install gettext -y + - run: python -m pip install --upgrade pip build wheel twine readme-renderer + - run: python -m build --sdist --wheel - run: python -m twine check dist/* - uses: actions/upload-artifact@v3 with: @@ -73,11 +71,11 @@ jobs: - "3.9" - "3.10" django-version: - - "3.2a" - - "4.0a" + - "3.2" + - "4.0" extra: - - "" - - "progressbar" + - "test" + - "test,progressbar" steps: - name: Set up Python ${{ matrix.python-version }} uses: actions/setup-python@v3 @@ -85,10 +83,9 @@ jobs: python-version: ${{ matrix.python-version }} - run: sudo apt install gettext -y - uses: actions/checkout@v3 - - run: python -m pip install --upgrade pip setuptools codecov wheel - - run: python -m pip install .[${{ matrix.extra }}] + - run: python -m pip install --upgrade pip codecov + - run: python -m pip install -e .[${{ matrix.extra }}] if: ${{ matrix.extra }} - - run: python -m pip install django~=${{ matrix.django-version }} - - name: Test with pytest - run: python setup.py test + - run: python -m pip install django~=${{ matrix.django-version }}a + - run: python -m pytest - run: codecov diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml index ff70343..19f0b4e 100644 --- a/.github/workflows/release.yml +++ b/.github/workflows/release.yml @@ -1,10 +1,12 @@ -name: PyPi Release +name: Release -on: [release] +on: + release: + types: [published] jobs: - build: + PyPi: runs-on: ubuntu-latest steps: - uses: actions/checkout@v3 @@ -14,5 +16,5 @@ jobs: - run: python -m build --sdist --wheel - run: python -m twine upload dist/* env: - TWINE_USERNAME: ${{ secrets.TWINE_USERNAME }} + TWINE_USERNAME: __token__ TWINE_PASSWORD: ${{ secrets.TWINE_PASSWORD }} diff --git a/setup.cfg b/setup.cfg index 10e8e2b..e6adaf7 100644 --- a/setup.cfg +++ b/setup.cfg @@ -38,11 +38,6 @@ install_requires = setup_requires = setuptools_scm - pytest-runner -tests_require = - pytest - pytest-cov - pytest-django [options.package_data] * = *.txt, *.rst, *.html, *.po @@ -52,20 +47,23 @@ exclude = tests [options.extras_require] +test = + pytest + pytest-cov + pytest-django progressbar = progressbar2>=3.0.0 [bdist_wheel] universal = 1 -[aliases] -test = pytest - [tool:pytest] +testpaths = + tests norecursedirs=venv env .eggs DJANGO_SETTINGS_MODULE=tests.settings addopts = --cov=stdimage --nomigrations --tb=short filterwarnings = - error + ignore:DeprecationWarning [coverage:run] source = . From 62dbd15f1e1e6b07199fbe2be552a81d73053842 Mon Sep 17 00:00:00 2001 From: Johannes Maron Date: Sat, 21 May 2022 11:55:00 +0200 Subject: [PATCH 67/98] Fix Pillow ANTIALIAS deprecation warning --- setup.cfg | 2 +- stdimage/models.py | 3 ++- tests/test_utils.py | 4 ++-- 3 files changed, 5 insertions(+), 4 deletions(-) diff --git a/setup.cfg b/setup.cfg index e6adaf7..d93790f 100644 --- a/setup.cfg +++ b/setup.cfg @@ -63,7 +63,7 @@ norecursedirs=venv env .eggs DJANGO_SETTINGS_MODULE=tests.settings addopts = --cov=stdimage --nomigrations --tb=short filterwarnings = - ignore:DeprecationWarning + error [coverage:run] source = . diff --git a/stdimage/models.py b/stdimage/models.py index 97ff514..ff13cff 100644 --- a/stdimage/models.py +++ b/stdimage/models.py @@ -11,6 +11,7 @@ ImageFileDescriptor, ) from PIL import Image, ImageFile, ImageOps +from PIL.Image import Resampling from .validators import MinSizeValidator @@ -186,7 +187,7 @@ class StdImageField(ImageField): "width": None, "height": None, "crop": False, - "resample": Image.ANTIALIAS, + "resample": Resampling.LANCZOS, } def __init__( diff --git a/tests/test_utils.py b/tests/test_utils.py index 2ab2c68..7180204 100644 --- a/tests/test_utils.py +++ b/tests/test_utils.py @@ -1,7 +1,7 @@ import os import pytest -from PIL import Image +from PIL.Image import Resampling from stdimage.utils import render_variations from tests.models import ManualVariationsModel @@ -24,7 +24,7 @@ def test_render_variations(self, image_upload_file): "width": 150, "height": 150, "crop": True, - "resample": Image.ANTIALIAS, + "resample": Resampling.LANCZOS, } }, ) From c8c389f7a9b9b4bcb0521e9ec68a3893826c672b Mon Sep 17 00:00:00 2001 From: Johannes Maron Date: Sat, 21 May 2022 11:48:02 +0200 Subject: [PATCH 68/98] Add migrations to enable a smooth transition to django-pictures We to migrate from django-stimage to pictures, we need to include variations into the migration model state. This allows deleting obsolite files during the migration. --- stdimage/models.py | 13 +++++++++++++ 1 file changed, 13 insertions(+) diff --git a/stdimage/models.py b/stdimage/models.py index ff13cff..528bc4c 100644 --- a/stdimage/models.py +++ b/stdimage/models.py @@ -307,6 +307,19 @@ def save_form_data(self, instance, data): file.delete(save=False) super().save_form_data(instance, data) + def deconstruct(self): + name, path, args, kwargs = super().deconstruct() + return ( + name, + path, + args, + { + **kwargs, + "variations": self._variations, + "force_min_size": self.force_min_size, + }, + ) + class JPEGFieldFile(StdImageFieldFile): @classmethod From 0730fccdb5223e93b225e112dbaada05c3ce8097 Mon Sep 17 00:00:00 2001 From: Johannes Maron Date: Sat, 21 May 2022 12:02:46 +0200 Subject: [PATCH 69/98] Set developent status classifiert to inactive --- setup.cfg | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/setup.cfg b/setup.cfg index d93790f..54c817c 100644 --- a/setup.cfg +++ b/setup.cfg @@ -9,7 +9,7 @@ url = https://github.com/codingjoe/django-stdimage license = MIT license_file = LICENSE classifier = - Development Status :: 5 - Production/Stable + Development Status :: 7 - Inactive Environment :: Web Environment Framework :: Django Topic :: Multimedia :: Graphics :: Graphics Conversion From 0c5b5e58e966e125d5c35d8fb2199983a94cdc10 Mon Sep 17 00:00:00 2001 From: Johannes Maron Date: Sat, 21 May 2022 12:23:40 +0200 Subject: [PATCH 70/98] Add deprecation warning and migration notes. --- README.md | 85 ++++++++++++++++++++++++++++++++++++++++++++-- setup.cfg | 2 +- stdimage/models.py | 9 +++++ 3 files changed, 93 insertions(+), 3 deletions(-) diff --git a/README.md b/README.md index c602c24..77fe5f6 100644 --- a/README.md +++ b/README.md @@ -4,11 +4,92 @@ # Django Standardized Image Field +This package has been deprecated in favor of [django-pictures][django-pictures]. + +## Migration Instructions + +First, make sure you understand the differences between the two packages and +how to serve images in a modern web application via the [picture][picture-tag]-Element. + +Next, follow the setup instructions for [django-pictures][django-pictures]. + +Once you are set up, change your models to use the new `PictureField` and provide the + `aspect_ratios` you'd like to serve. Do create migrations just yet. + +This step should be followed by changing your templates and frontend. +The new placeholders feature for local development should help you +to do this almost effortlessly. + +Finally, run `makemigrations` and replace the `AlterField` operation with +`AlterPictureField`. + +We highly recommend to use Django's `image_width` and `image_height` fields, to avoid +unnecessary IO. If you can add these fields to your model, you can use the following +snippet to populate them: + +```python +import django.core.files.storage +from django.db import migrations, models +import pictures.models +from pictures.migrations import AlterPictureField + +def forward(apps, schema_editor): + for obj in apps.get_model("my-app.MyModel").objects.all().iterator(): + obj.image_width = obj.logo.width + obj.image_height = obj.logo.height + obj.save(update_fields=["image_height", "image_width"]) + +def backward(apps, schema_editor): + apps.get_model("my-app.MyModel").objects.all().update( + image_width=None, + image_height=None, + ) + +class Migration(migrations.Migration): + dependencies = [ + ('my-app', '0001_initial'), + ] + + operations = [ + migrations.AddField( + model_name="mymodel", + name="image_height", + field=models.PositiveIntegerField(editable=False, null=True), + ), + migrations.AddField( + model_name="mymodel", + name="image_width", + field=models.PositiveIntegerField(editable=False, null=True), + ), + migrations.RunPython(forward, backward), + AlterPictureField( + model_name="mymodel", + name="image", + field=pictures.models.PictureField( + aspect_ratios=["3/2", "3/1"], + breakpoints={"desktop": 1024, "mobile": 576}, + container_width=1200, + file_types=["WEBP"], + grid_columns=12, + height_field="image_height", + pixel_densities=[1, 2], + storage=django.core.files.storage.FileSystemStorage(), + upload_to="pictures/", + verbose_name="image", + width_field="image_width", + ), + ), + ] +``` + +[django-pictures]: https://github.com/codingjoe/django-pictures +[picture-tag]: https://developer.mozilla.org/en-US/docs/Web/HTML/Element/picture + ## Why would I want this? This is a drop-in replacement for the [Django ImageField](https://docs.djangoproject.com/en/1.8/ref/models/fields/#django.db.models.ImageField) that provides a standardized way to handle image uploads. It is designed to be as easy to use as possible, and to provide a consistent interface for all image fields. -It allows images to be presented in various size variants (eg:thumbnails, mid, and hi-res versions) +It allows images to be presented in various size variants (eg:thumbnails, mid, and hi-res versions) and it provides a way to handle images that are too large with validators. @@ -103,7 +184,7 @@ You can use a function for the `upload_to` argument. Using [Django Dynamic Filen This allows images to be given unique paths and filenames based on the model instance. -Example +Example ```python from django.db import models diff --git a/setup.cfg b/setup.cfg index 54c817c..5262f42 100644 --- a/setup.cfg +++ b/setup.cfg @@ -63,7 +63,7 @@ norecursedirs=venv env .eggs DJANGO_SETTINGS_MODULE=tests.settings addopts = --cov=stdimage --nomigrations --tb=short filterwarnings = - error + ignore::DeprecationWarning [coverage:run] source = . diff --git a/stdimage/models.py b/stdimage/models.py index 528bc4c..bed00d7 100644 --- a/stdimage/models.py +++ b/stdimage/models.py @@ -1,5 +1,6 @@ import logging import os +import warnings from io import BytesIO from django.core.files.base import ContentFile @@ -18,6 +19,14 @@ logger = logging.getLogger() +warnings.warn( + "The django-stdimage is deprecated in favor of django-pictures.\n" + "Migration instructions are available in the README:\n" + "https://github.com/codingjoe/django-stdimage#migration-instructions", + DeprecationWarning, +) + + class StdImageFileDescriptor(ImageFileDescriptor): """The variation property of the field is accessible in instance cases.""" From 3e473c12b52b0eb89cb625074f84911370976bd1 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?J=C3=A9r=C3=B4me=20Lebleu?= Date: Thu, 12 May 2022 14:52:05 +0200 Subject: [PATCH 71/98] Fix #229 -- Delete old file after validation is passed Previously files were deleted even if the from validation failed. Co-Authored-By: codingjoe --- stdimage/models.py | 15 ++++++++++++++- tests/forms.py | 6 ++++++ tests/models.py | 6 +++++- tests/test_forms.py | 13 +++++++++++++ 4 files changed, 38 insertions(+), 2 deletions(-) diff --git a/stdimage/models.py b/stdimage/models.py index bed00d7..6e0083d 100644 --- a/stdimage/models.py +++ b/stdimage/models.py @@ -264,6 +264,9 @@ def __init__( super().__init__(verbose_name=verbose_name, name=name, **kwargs) + # The attribute name of the old file to use on the model object + self._old_attname = "_old_%s" % name + def add_variation(self, name, params): variation = self.def_variation.copy() variation["kwargs"] = {} @@ -313,9 +316,19 @@ def save_form_data(self, instance, data): if self.delete_orphans and (data is False or data is not None): file = getattr(instance, self.name) if file and file._committed and file != data: - file.delete(save=False) + # Store the old file which should be deleted if the new one is valid + setattr(instance, self._old_attname, file) super().save_form_data(instance, data) + def pre_save(self, model_instance, add): + if hasattr(model_instance, self._old_attname): + # Delete the old file and its variations from the storage + old_file = getattr(model_instance, self._old_attname) + old_file.delete_variations() + old_file.storage.delete(old_file.name) + delattr(model_instance, self._old_attname) + return super().pre_save(model_instance, add) + def deconstruct(self): name, path, args, kwargs = super().deconstruct() return ( diff --git a/tests/forms.py b/tests/forms.py index c70347d..ff3927f 100644 --- a/tests/forms.py +++ b/tests/forms.py @@ -7,3 +7,9 @@ class ThumbnailModelForm(forms.ModelForm): class Meta: model = models.ThumbnailModel fields = "__all__" + + +class MinSizeModelForm(forms.ModelForm): + class Meta: + model = models.MinSizeModel + fields = "__all__" diff --git a/tests/models.py b/tests/models.py index 68a702f..4e91627 100644 --- a/tests/models.py +++ b/tests/models.py @@ -95,7 +95,11 @@ class MaxSizeModel(models.Model): class MinSizeModel(models.Model): - image = StdImageField(upload_to=upload_to, validators=[MinSizeValidator(200, 200)]) + image = StdImageField( + upload_to=upload_to, + delete_orphans=True, + validators=[MinSizeValidator(200, 200)], + ) class ForceMinSizeModel(models.Model): diff --git a/tests/test_forms.py b/tests/test_forms.py index 81b3360..03629b0 100644 --- a/tests/test_forms.py +++ b/tests/test_forms.py @@ -45,3 +45,16 @@ def test_save_form_data__none(self, db): obj = form.save() assert obj.image assert os.path.exists(org_path) + + def test_save_form_data__invalid(self, db): + instance = models.MinSizeModel.objects.create( + image=self.fixtures["600x400.jpg"] + ) + org_path = instance.image.path + assert os.path.exists(org_path) + form = forms.MinSizeModelForm( + files={"image": self.fixtures["100.gif"]}, + instance=instance, + ) + assert not form.is_valid() + assert os.path.exists(org_path) From b4eef1c28b1fd0a5aa32ace8b8d84470cf996c1f Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Wed, 15 Jun 2022 12:00:26 +0200 Subject: [PATCH 72/98] Bump actions/setup-python from 3 to 4 (#297) * Bump actions/setup-python from 3 to 4 Bumps [actions/setup-python](https://github.com/actions/setup-python) from 3 to 4. - [Release notes](https://github.com/actions/setup-python/releases) - [Commits](https://github.com/actions/setup-python/compare/v3...v4) --- updated-dependencies: - dependency-name: actions/setup-python dependency-type: direct:production update-type: version-update:semver-major ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> Co-authored-by: Johannes Maron --- .github/workflows/ci.yml | 14 ++++++++++---- .github/workflows/release.yml | 4 +++- 2 files changed, 13 insertions(+), 5 deletions(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 3070c08..f1072c5 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -11,7 +11,9 @@ jobs: msgcheck: runs-on: ubuntu-latest steps: - - uses: actions/setup-python@v3 + - uses: actions/setup-python@v4 + with: + python-version: "3.10" - uses: actions/checkout@v3 - run: sudo apt install -y gettext aspell libenchant-dev - uses: actions/cache@v3 @@ -35,7 +37,9 @@ jobs: - "pydocstyle ." runs-on: ubuntu-latest steps: - - uses: actions/setup-python@v3 + - uses: actions/setup-python@v4 + with: + python-version: "3.10" - uses: actions/checkout@v3 - uses: actions/cache@v3 with: @@ -50,7 +54,9 @@ jobs: runs-on: ubuntu-latest steps: - uses: actions/checkout@v3 - - uses: actions/setup-python@v3 + - uses: actions/setup-python@v4 + with: + python-version: "3.10" - run: sudo apt install gettext -y - run: python -m pip install --upgrade pip build wheel twine readme-renderer - run: python -m build --sdist --wheel @@ -78,7 +84,7 @@ jobs: - "test,progressbar" steps: - name: Set up Python ${{ matrix.python-version }} - uses: actions/setup-python@v3 + uses: actions/setup-python@v4 with: python-version: ${{ matrix.python-version }} - run: sudo apt install gettext -y diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml index 19f0b4e..4ee1915 100644 --- a/.github/workflows/release.yml +++ b/.github/workflows/release.yml @@ -10,7 +10,9 @@ jobs: runs-on: ubuntu-latest steps: - uses: actions/checkout@v3 - - uses: actions/setup-python@v3 + - uses: actions/setup-python@v4 + with: + python-version: "3.10" - run: sudo apt-get install gettext -y - run: python -m pip install --upgrade pip build wheel twine - run: python -m build --sdist --wheel From 5215f9db99d47ae3ef42a9dc80f210972609ed79 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Tue, 28 Jun 2022 21:09:29 +0000 Subject: [PATCH 73/98] Bump black from 22.3.0 to 22.6.0 Bumps [black](https://github.com/psf/black) from 22.3.0 to 22.6.0. - [Release notes](https://github.com/psf/black/releases) - [Changelog](https://github.com/psf/black/blob/main/CHANGES.md) - [Commits](https://github.com/psf/black/compare/22.3.0...22.6.0) --- updated-dependencies: - dependency-name: black dependency-type: direct:production update-type: version-update:semver-minor ... Signed-off-by: dependabot[bot] --- lint-requirements.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lint-requirements.txt b/lint-requirements.txt index 7aae3f5..b90e490 100644 --- a/lint-requirements.txt +++ b/lint-requirements.txt @@ -1,5 +1,5 @@ bandit==1.7.4 -black==22.3.0 +black==22.6.0 flake8==4.0.1 isort==5.10.1 msgcheck==4.0.0 From f8be2e9828500dea58ab057b486c00018ef19965 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 1 Aug 2022 21:11:17 +0000 Subject: [PATCH 74/98] Bump flake8 from 4.0.1 to 5.0.2 Bumps [flake8](https://github.com/pycqa/flake8) from 4.0.1 to 5.0.2. - [Release notes](https://github.com/pycqa/flake8/releases) - [Commits](https://github.com/pycqa/flake8/compare/4.0.1...5.0.2) --- updated-dependencies: - dependency-name: flake8 dependency-type: direct:production update-type: version-update:semver-major ... Signed-off-by: dependabot[bot] --- lint-requirements.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lint-requirements.txt b/lint-requirements.txt index b90e490..9a16eec 100644 --- a/lint-requirements.txt +++ b/lint-requirements.txt @@ -1,6 +1,6 @@ bandit==1.7.4 black==22.6.0 -flake8==4.0.1 +flake8==5.0.2 isort==5.10.1 msgcheck==4.0.0 pydocstyle==6.1.1 From be30d1a708a875cbaa5a5fafd96a602db5c0ef52 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Tue, 2 Aug 2022 21:07:01 +0000 Subject: [PATCH 75/98] Bump flake8 from 5.0.2 to 5.0.3 Bumps [flake8](https://github.com/pycqa/flake8) from 5.0.2 to 5.0.3. - [Release notes](https://github.com/pycqa/flake8/releases) - [Commits](https://github.com/pycqa/flake8/compare/5.0.2...5.0.3) --- updated-dependencies: - dependency-name: flake8 dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] --- lint-requirements.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lint-requirements.txt b/lint-requirements.txt index 9a16eec..4495c42 100644 --- a/lint-requirements.txt +++ b/lint-requirements.txt @@ -1,6 +1,6 @@ bandit==1.7.4 black==22.6.0 -flake8==5.0.2 +flake8==5.0.3 isort==5.10.1 msgcheck==4.0.0 pydocstyle==6.1.1 From 3cb50a9ff64aeaa05ef87629251bcaa5d3fcc3d9 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Thu, 4 Aug 2022 21:08:32 +0000 Subject: [PATCH 76/98] Bump flake8 from 5.0.3 to 5.0.4 Bumps [flake8](https://github.com/pycqa/flake8) from 5.0.3 to 5.0.4. - [Release notes](https://github.com/pycqa/flake8/releases) - [Commits](https://github.com/pycqa/flake8/compare/5.0.3...5.0.4) --- updated-dependencies: - dependency-name: flake8 dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] --- lint-requirements.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lint-requirements.txt b/lint-requirements.txt index 4495c42..305be9d 100644 --- a/lint-requirements.txt +++ b/lint-requirements.txt @@ -1,6 +1,6 @@ bandit==1.7.4 black==22.6.0 -flake8==5.0.3 +flake8==5.0.4 isort==5.10.1 msgcheck==4.0.0 pydocstyle==6.1.1 From 3ba5a669ddc12feee84de109c904ab41e5893c66 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Thu, 1 Sep 2022 21:10:17 +0000 Subject: [PATCH 77/98] Bump black from 22.6.0 to 22.8.0 Bumps [black](https://github.com/psf/black) from 22.6.0 to 22.8.0. - [Release notes](https://github.com/psf/black/releases) - [Changelog](https://github.com/psf/black/blob/main/CHANGES.md) - [Commits](https://github.com/psf/black/compare/22.6.0...22.8.0) --- updated-dependencies: - dependency-name: black dependency-type: direct:production update-type: version-update:semver-minor ... Signed-off-by: dependabot[bot] --- lint-requirements.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lint-requirements.txt b/lint-requirements.txt index 305be9d..fc89439 100644 --- a/lint-requirements.txt +++ b/lint-requirements.txt @@ -1,5 +1,5 @@ bandit==1.7.4 -black==22.6.0 +black==22.8.0 flake8==5.0.4 isort==5.10.1 msgcheck==4.0.0 From b2bac24273d1bd732d10c127253688c11b76210c Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Fri, 7 Oct 2022 21:09:39 +0000 Subject: [PATCH 78/98] Bump black from 22.8.0 to 22.10.0 Bumps [black](https://github.com/psf/black) from 22.8.0 to 22.10.0. - [Release notes](https://github.com/psf/black/releases) - [Changelog](https://github.com/psf/black/blob/main/CHANGES.md) - [Commits](https://github.com/psf/black/compare/22.8.0...22.10.0) --- updated-dependencies: - dependency-name: black dependency-type: direct:production update-type: version-update:semver-minor ... Signed-off-by: dependabot[bot] --- lint-requirements.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lint-requirements.txt b/lint-requirements.txt index fc89439..9ff7507 100644 --- a/lint-requirements.txt +++ b/lint-requirements.txt @@ -1,5 +1,5 @@ bandit==1.7.4 -black==22.8.0 +black==22.10.0 flake8==5.0.4 isort==5.10.1 msgcheck==4.0.0 From fcaad7ef1d3df9aea666601268c86b425ccff07d Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Wed, 23 Nov 2022 21:04:33 +0000 Subject: [PATCH 79/98] Bump flake8 from 5.0.4 to 6.0.0 Bumps [flake8](https://github.com/pycqa/flake8) from 5.0.4 to 6.0.0. - [Release notes](https://github.com/pycqa/flake8/releases) - [Commits](https://github.com/pycqa/flake8/compare/5.0.4...6.0.0) --- updated-dependencies: - dependency-name: flake8 dependency-type: direct:production update-type: version-update:semver-major ... Signed-off-by: dependabot[bot] --- lint-requirements.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lint-requirements.txt b/lint-requirements.txt index 9ff7507..f333a90 100644 --- a/lint-requirements.txt +++ b/lint-requirements.txt @@ -1,6 +1,6 @@ bandit==1.7.4 black==22.10.0 -flake8==5.0.4 +flake8==6.0.0 isort==5.10.1 msgcheck==4.0.0 pydocstyle==6.1.1 From b816c03426266b7b6471e433b279803756cb177e Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Fri, 9 Dec 2022 21:01:48 +0000 Subject: [PATCH 80/98] Bump black from 22.10.0 to 22.12.0 Bumps [black](https://github.com/psf/black) from 22.10.0 to 22.12.0. - [Release notes](https://github.com/psf/black/releases) - [Changelog](https://github.com/psf/black/blob/main/CHANGES.md) - [Commits](https://github.com/psf/black/compare/22.10.0...22.12.0) --- updated-dependencies: - dependency-name: black dependency-type: direct:production update-type: version-update:semver-minor ... Signed-off-by: dependabot[bot] --- lint-requirements.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lint-requirements.txt b/lint-requirements.txt index f333a90..cdfb313 100644 --- a/lint-requirements.txt +++ b/lint-requirements.txt @@ -1,5 +1,5 @@ bandit==1.7.4 -black==22.10.0 +black==22.12.0 flake8==6.0.0 isort==5.10.1 msgcheck==4.0.0 From 775058a27a295542a7b9d30410b5a5dd61122ea0 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 12 Dec 2022 21:03:23 +0000 Subject: [PATCH 81/98] Bump isort from 5.10.1 to 5.11.1 Bumps [isort](https://github.com/pycqa/isort) from 5.10.1 to 5.11.1. - [Release notes](https://github.com/pycqa/isort/releases) - [Changelog](https://github.com/PyCQA/isort/blob/main/CHANGELOG.md) - [Commits](https://github.com/pycqa/isort/compare/5.10.1...5.11.1) --- updated-dependencies: - dependency-name: isort dependency-type: direct:production update-type: version-update:semver-minor ... Signed-off-by: dependabot[bot] --- lint-requirements.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lint-requirements.txt b/lint-requirements.txt index cdfb313..764cc68 100644 --- a/lint-requirements.txt +++ b/lint-requirements.txt @@ -1,6 +1,6 @@ bandit==1.7.4 black==22.12.0 flake8==6.0.0 -isort==5.10.1 +isort==5.11.1 msgcheck==4.0.0 pydocstyle==6.1.1 From fc36b733cf953865733f6edc0dde54b6b92d9fc5 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Tue, 13 Dec 2022 21:03:16 +0000 Subject: [PATCH 82/98] Bump isort from 5.11.1 to 5.11.2 Bumps [isort](https://github.com/pycqa/isort) from 5.11.1 to 5.11.2. - [Release notes](https://github.com/pycqa/isort/releases) - [Changelog](https://github.com/PyCQA/isort/blob/main/CHANGELOG.md) - [Commits](https://github.com/pycqa/isort/compare/5.11.1...5.11.2) --- updated-dependencies: - dependency-name: isort dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] --- lint-requirements.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lint-requirements.txt b/lint-requirements.txt index 764cc68..3c490b1 100644 --- a/lint-requirements.txt +++ b/lint-requirements.txt @@ -1,6 +1,6 @@ bandit==1.7.4 black==22.12.0 flake8==6.0.0 -isort==5.11.1 +isort==5.11.2 msgcheck==4.0.0 pydocstyle==6.1.1 From 2d40a5168feef7575120ee66c46bfb5ab109b8a7 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Thu, 22 Dec 2022 21:02:00 +0000 Subject: [PATCH 83/98] Bump isort from 5.11.2 to 5.11.4 Bumps [isort](https://github.com/pycqa/isort) from 5.11.2 to 5.11.4. - [Release notes](https://github.com/pycqa/isort/releases) - [Changelog](https://github.com/PyCQA/isort/blob/main/CHANGELOG.md) - [Commits](https://github.com/pycqa/isort/compare/5.11.2...5.11.4) --- updated-dependencies: - dependency-name: isort dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] --- lint-requirements.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lint-requirements.txt b/lint-requirements.txt index 3c490b1..7452f0e 100644 --- a/lint-requirements.txt +++ b/lint-requirements.txt @@ -1,6 +1,6 @@ bandit==1.7.4 black==22.12.0 flake8==6.0.0 -isort==5.11.2 +isort==5.11.4 msgcheck==4.0.0 pydocstyle==6.1.1 From 9aa5c6ac4e08fa31094528972eac6f7569cf0c87 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Tue, 3 Jan 2023 21:03:17 +0000 Subject: [PATCH 84/98] Bump pydocstyle from 6.1.1 to 6.2.2 Bumps [pydocstyle](https://github.com/PyCQA/pydocstyle) from 6.1.1 to 6.2.2. - [Release notes](https://github.com/PyCQA/pydocstyle/releases) - [Changelog](https://github.com/PyCQA/pydocstyle/blob/master/docs/release_notes.rst) - [Commits](https://github.com/PyCQA/pydocstyle/compare/6.1.1...6.2.2) --- updated-dependencies: - dependency-name: pydocstyle dependency-type: direct:production update-type: version-update:semver-minor ... Signed-off-by: dependabot[bot] --- lint-requirements.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lint-requirements.txt b/lint-requirements.txt index 7452f0e..f85f6b6 100644 --- a/lint-requirements.txt +++ b/lint-requirements.txt @@ -3,4 +3,4 @@ black==22.12.0 flake8==6.0.0 isort==5.11.4 msgcheck==4.0.0 -pydocstyle==6.1.1 +pydocstyle==6.2.2 From 00cf902499a53112a26a02f11617397758f1cd53 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 9 Jan 2023 21:03:01 +0000 Subject: [PATCH 85/98] Bump pydocstyle from 6.2.2 to 6.2.3 Bumps [pydocstyle](https://github.com/PyCQA/pydocstyle) from 6.2.2 to 6.2.3. - [Release notes](https://github.com/PyCQA/pydocstyle/releases) - [Changelog](https://github.com/PyCQA/pydocstyle/blob/master/docs/release_notes.rst) - [Commits](https://github.com/PyCQA/pydocstyle/compare/6.2.2...6.2.3) --- updated-dependencies: - dependency-name: pydocstyle dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] --- lint-requirements.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lint-requirements.txt b/lint-requirements.txt index f85f6b6..9ed3f40 100644 --- a/lint-requirements.txt +++ b/lint-requirements.txt @@ -3,4 +3,4 @@ black==22.12.0 flake8==6.0.0 isort==5.11.4 msgcheck==4.0.0 -pydocstyle==6.2.2 +pydocstyle==6.2.3 From 1075bfa40d2e3427ccd9cc172c631dc58e15f216 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Tue, 17 Jan 2023 21:01:45 +0000 Subject: [PATCH 86/98] Bump pydocstyle from 6.2.3 to 6.3.0 Bumps [pydocstyle](https://github.com/PyCQA/pydocstyle) from 6.2.3 to 6.3.0. - [Release notes](https://github.com/PyCQA/pydocstyle/releases) - [Changelog](https://github.com/PyCQA/pydocstyle/blob/master/docs/release_notes.rst) - [Commits](https://github.com/PyCQA/pydocstyle/compare/6.2.3...6.3.0) --- updated-dependencies: - dependency-name: pydocstyle dependency-type: direct:production update-type: version-update:semver-minor ... Signed-off-by: dependabot[bot] --- lint-requirements.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lint-requirements.txt b/lint-requirements.txt index 9ed3f40..3e2b541 100644 --- a/lint-requirements.txt +++ b/lint-requirements.txt @@ -3,4 +3,4 @@ black==22.12.0 flake8==6.0.0 isort==5.11.4 msgcheck==4.0.0 -pydocstyle==6.2.3 +pydocstyle==6.3.0 From cea0f4e8b44f22291ba34ab9986dbc215260e7e8 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 30 Jan 2023 21:01:57 +0000 Subject: [PATCH 87/98] Bump isort from 5.11.4 to 5.12.0 Bumps [isort](https://github.com/pycqa/isort) from 5.11.4 to 5.12.0. - [Release notes](https://github.com/pycqa/isort/releases) - [Changelog](https://github.com/PyCQA/isort/blob/main/CHANGELOG.md) - [Commits](https://github.com/pycqa/isort/compare/5.11.4...5.12.0) --- updated-dependencies: - dependency-name: isort dependency-type: direct:production update-type: version-update:semver-minor ... Signed-off-by: dependabot[bot] --- lint-requirements.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lint-requirements.txt b/lint-requirements.txt index 3e2b541..a681fcd 100644 --- a/lint-requirements.txt +++ b/lint-requirements.txt @@ -1,6 +1,6 @@ bandit==1.7.4 black==22.12.0 flake8==6.0.0 -isort==5.11.4 +isort==5.12.0 msgcheck==4.0.0 pydocstyle==6.3.0 From 0dcee913073c2a541234aa6a9daf26ea03578a03 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Wed, 1 Feb 2023 21:02:52 +0000 Subject: [PATCH 88/98] Bump black from 22.12.0 to 23.1.0 Bumps [black](https://github.com/psf/black) from 22.12.0 to 23.1.0. - [Release notes](https://github.com/psf/black/releases) - [Changelog](https://github.com/psf/black/blob/main/CHANGES.md) - [Commits](https://github.com/psf/black/compare/22.12.0...23.1.0) --- updated-dependencies: - dependency-name: black dependency-type: direct:production update-type: version-update:semver-major ... Signed-off-by: dependabot[bot] --- lint-requirements.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lint-requirements.txt b/lint-requirements.txt index a681fcd..0a6ca91 100644 --- a/lint-requirements.txt +++ b/lint-requirements.txt @@ -1,5 +1,5 @@ bandit==1.7.4 -black==22.12.0 +black==23.1.0 flake8==6.0.0 isort==5.12.0 msgcheck==4.0.0 From 17e45ed2167901d2fc2a48f4a557a8c326d17031 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Fri, 10 Mar 2023 21:57:14 +0000 Subject: [PATCH 89/98] Bump bandit from 1.7.4 to 1.7.5 Bumps [bandit](https://github.com/PyCQA/bandit) from 1.7.4 to 1.7.5. - [Release notes](https://github.com/PyCQA/bandit/releases) - [Commits](https://github.com/PyCQA/bandit/compare/1.7.4...1.7.5) --- updated-dependencies: - dependency-name: bandit dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] --- lint-requirements.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lint-requirements.txt b/lint-requirements.txt index 0a6ca91..cbc6a6d 100644 --- a/lint-requirements.txt +++ b/lint-requirements.txt @@ -1,4 +1,4 @@ -bandit==1.7.4 +bandit==1.7.5 black==23.1.0 flake8==6.0.0 isort==5.12.0 From c0e60b05168f2ef33fdeb3d311a39e4989af4dde Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Wed, 29 Mar 2023 21:57:42 +0000 Subject: [PATCH 90/98] Bump black from 23.1.0 to 23.3.0 Bumps [black](https://github.com/psf/black) from 23.1.0 to 23.3.0. - [Release notes](https://github.com/psf/black/releases) - [Changelog](https://github.com/psf/black/blob/main/CHANGES.md) - [Commits](https://github.com/psf/black/compare/23.1.0...23.3.0) --- updated-dependencies: - dependency-name: black dependency-type: direct:production update-type: version-update:semver-minor ... Signed-off-by: dependabot[bot] --- lint-requirements.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lint-requirements.txt b/lint-requirements.txt index cbc6a6d..e4f279c 100644 --- a/lint-requirements.txt +++ b/lint-requirements.txt @@ -1,5 +1,5 @@ bandit==1.7.5 -black==23.1.0 +black==23.3.0 flake8==6.0.0 isort==5.12.0 msgcheck==4.0.0 From fbdd69f78f7335ac5a435d9986695d04a5d9e90b Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Tue, 11 Jul 2023 21:10:01 +0000 Subject: [PATCH 91/98] Bump black from 23.3.0 to 23.7.0 Bumps [black](https://github.com/psf/black) from 23.3.0 to 23.7.0. - [Release notes](https://github.com/psf/black/releases) - [Changelog](https://github.com/psf/black/blob/main/CHANGES.md) - [Commits](https://github.com/psf/black/compare/23.3.0...23.7.0) --- updated-dependencies: - dependency-name: black dependency-type: direct:production update-type: version-update:semver-minor ... Signed-off-by: dependabot[bot] --- lint-requirements.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lint-requirements.txt b/lint-requirements.txt index e4f279c..05f4804 100644 --- a/lint-requirements.txt +++ b/lint-requirements.txt @@ -1,5 +1,5 @@ bandit==1.7.5 -black==23.3.0 +black==23.7.0 flake8==6.0.0 isort==5.12.0 msgcheck==4.0.0 From 7100350161c540dcd949ab2cb1ea47b1e9de0208 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 31 Jul 2023 21:33:00 +0000 Subject: [PATCH 92/98] Bump flake8 from 6.0.0 to 6.1.0 Bumps [flake8](https://github.com/pycqa/flake8) from 6.0.0 to 6.1.0. - [Commits](https://github.com/pycqa/flake8/compare/6.0.0...6.1.0) --- updated-dependencies: - dependency-name: flake8 dependency-type: direct:production update-type: version-update:semver-minor ... Signed-off-by: dependabot[bot] --- lint-requirements.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lint-requirements.txt b/lint-requirements.txt index 05f4804..27126cc 100644 --- a/lint-requirements.txt +++ b/lint-requirements.txt @@ -1,6 +1,6 @@ bandit==1.7.5 black==23.7.0 -flake8==6.0.0 +flake8==6.1.0 isort==5.12.0 msgcheck==4.0.0 pydocstyle==6.3.0 From 3ad53aeda50da50088f1c1c216bcdce11d1338f1 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 4 Sep 2023 21:38:34 +0000 Subject: [PATCH 93/98] Bump actions/checkout from 3 to 4 Bumps [actions/checkout](https://github.com/actions/checkout) from 3 to 4. - [Release notes](https://github.com/actions/checkout/releases) - [Changelog](https://github.com/actions/checkout/blob/main/CHANGELOG.md) - [Commits](https://github.com/actions/checkout/compare/v3...v4) --- updated-dependencies: - dependency-name: actions/checkout dependency-type: direct:production update-type: version-update:semver-major ... Signed-off-by: dependabot[bot] --- .github/workflows/ci.yml | 8 ++++---- .github/workflows/release.yml | 2 +- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index f1072c5..3f89486 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -14,7 +14,7 @@ jobs: - uses: actions/setup-python@v4 with: python-version: "3.10" - - uses: actions/checkout@v3 + - uses: actions/checkout@v4 - run: sudo apt install -y gettext aspell libenchant-dev - uses: actions/cache@v3 with: @@ -40,7 +40,7 @@ jobs: - uses: actions/setup-python@v4 with: python-version: "3.10" - - uses: actions/checkout@v3 + - uses: actions/checkout@v4 - uses: actions/cache@v3 with: path: ~/.cache/pip @@ -53,7 +53,7 @@ jobs: dist: runs-on: ubuntu-latest steps: - - uses: actions/checkout@v3 + - uses: actions/checkout@v4 - uses: actions/setup-python@v4 with: python-version: "3.10" @@ -88,7 +88,7 @@ jobs: with: python-version: ${{ matrix.python-version }} - run: sudo apt install gettext -y - - uses: actions/checkout@v3 + - uses: actions/checkout@v4 - run: python -m pip install --upgrade pip codecov - run: python -m pip install -e .[${{ matrix.extra }}] if: ${{ matrix.extra }} diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml index 4ee1915..a71d600 100644 --- a/.github/workflows/release.yml +++ b/.github/workflows/release.yml @@ -9,7 +9,7 @@ jobs: PyPi: runs-on: ubuntu-latest steps: - - uses: actions/checkout@v3 + - uses: actions/checkout@v4 - uses: actions/setup-python@v4 with: python-version: "3.10" From 207b7ac9a35f6f7ef8a4c5311f01423e0dbf8649 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 11 Sep 2023 21:40:05 +0000 Subject: [PATCH 94/98] Bump black from 23.7.0 to 23.9.1 Bumps [black](https://github.com/psf/black) from 23.7.0 to 23.9.1. - [Release notes](https://github.com/psf/black/releases) - [Changelog](https://github.com/psf/black/blob/main/CHANGES.md) - [Commits](https://github.com/psf/black/compare/23.7.0...23.9.1) --- updated-dependencies: - dependency-name: black dependency-type: direct:production update-type: version-update:semver-minor ... Signed-off-by: dependabot[bot] --- lint-requirements.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lint-requirements.txt b/lint-requirements.txt index 27126cc..821eac4 100644 --- a/lint-requirements.txt +++ b/lint-requirements.txt @@ -1,5 +1,5 @@ bandit==1.7.5 -black==23.7.0 +black==23.9.1 flake8==6.1.0 isort==5.12.0 msgcheck==4.0.0 From bf0ff6857a4fd67edc1141a55b07d213adab12a8 Mon Sep 17 00:00:00 2001 From: Johannes Maron Date: Wed, 11 Oct 2023 10:07:51 +0200 Subject: [PATCH 95/98] Update to libenchate 2 --- .github/workflows/ci.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 3f89486..9ad71f1 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -15,7 +15,7 @@ jobs: with: python-version: "3.10" - uses: actions/checkout@v4 - - run: sudo apt install -y gettext aspell libenchant-dev + - run: sudo apt install -y gettext aspell libenchant-2-dev - uses: actions/cache@v3 with: path: ~/.cache/pip From a1427a5cc78a2f183822d34f9331046f38f2e61b Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Tue, 17 Oct 2023 21:50:29 +0000 Subject: [PATCH 96/98] Bump black from 23.9.1 to 23.10.0 Bumps [black](https://github.com/psf/black) from 23.9.1 to 23.10.0. - [Release notes](https://github.com/psf/black/releases) - [Changelog](https://github.com/psf/black/blob/main/CHANGES.md) - [Commits](https://github.com/psf/black/compare/23.9.1...23.10.0) --- updated-dependencies: - dependency-name: black dependency-type: direct:production update-type: version-update:semver-minor ... Signed-off-by: dependabot[bot] --- lint-requirements.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lint-requirements.txt b/lint-requirements.txt index 821eac4..9279c0e 100644 --- a/lint-requirements.txt +++ b/lint-requirements.txt @@ -1,5 +1,5 @@ bandit==1.7.5 -black==23.9.1 +black==23.10.0 flake8==6.1.0 isort==5.12.0 msgcheck==4.0.0 From bc9af2adf043f6457198d2142b84d522813e5852 Mon Sep 17 00:00:00 2001 From: Denis Cornehl Date: Mon, 6 Nov 2023 18:25:07 +0100 Subject: [PATCH 97/98] Fix deepcopy & pickle for unsaved model instances & empty image fields (#324) --- stdimage/models.py | 8 ++++---- tests/test_models.py | 14 ++++++++++++++ 2 files changed, 18 insertions(+), 4 deletions(-) diff --git a/stdimage/models.py b/stdimage/models.py index 6e0083d..dd429d8 100644 --- a/stdimage/models.py +++ b/stdimage/models.py @@ -158,9 +158,9 @@ def __getstate__(self): state = super().__getstate__() state["variations"] = {} for variation_name in self.field.variations: - variation = getattr(self, variation_name) - variation_state = variation.__getstate__() - state["variations"][variation_name] = variation_state + if variation := getattr(self, variation_name, None): + variation_state = variation.__getstate__() + state["variations"][variation_name] = variation_state return state def __setstate__(self, state): @@ -207,7 +207,7 @@ def __init__( render_variations=True, force_min_size=False, delete_orphans=False, - **kwargs + **kwargs, ): """ Standardized ImageField for Django. diff --git a/tests/test_models.py b/tests/test_models.py index e8d47f2..e234521 100644 --- a/tests/test_models.py +++ b/tests/test_models.py @@ -174,6 +174,20 @@ def test_defer(self, db, django_assert_num_queries): deferred.image assert instance.image.thumbnail == deferred.image.thumbnail + @pytest.mark.django_db + def test_variations_deepcopy_unsaved(self): + instance_original = ResizeModel(image=self.fixtures["600x400.jpg"]) + instance = deepcopy(instance_original) + assert isinstance(instance.image, StdImageFieldFile) + assert instance.image == instance_original.image + + @pytest.mark.django_db + def test_variations_deepcopy_without_image(self): + instance_original = ThumbnailModel.objects.create(image=None) + instance = deepcopy(instance_original) + assert isinstance(instance.image, StdImageFieldFile) + assert instance.image == instance_original.image + @pytest.mark.django_db def test_variations_deepcopy(self): """Tests test_variations() with a deep copied object""" From 59ff17674de24483c6cddd64f99e47871792f6c7 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Fri, 15 Mar 2024 21:29:11 +0000 Subject: [PATCH 98/98] Bump black from 23.10.0 to 24.3.0 Bumps [black](https://github.com/psf/black) from 23.10.0 to 24.3.0. - [Release notes](https://github.com/psf/black/releases) - [Changelog](https://github.com/psf/black/blob/main/CHANGES.md) - [Commits](https://github.com/psf/black/compare/23.10.0...24.3.0) --- updated-dependencies: - dependency-name: black dependency-type: direct:production update-type: version-update:semver-major ... Signed-off-by: dependabot[bot] --- lint-requirements.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lint-requirements.txt b/lint-requirements.txt index 9279c0e..e0936be 100644 --- a/lint-requirements.txt +++ b/lint-requirements.txt @@ -1,5 +1,5 @@ bandit==1.7.5 -black==23.10.0 +black==24.3.0 flake8==6.1.0 isort==5.12.0 msgcheck==4.0.0