diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 07799f2..c6569c7 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -8,26 +8,13 @@ on: jobs: - analyze: - name: CodeQL - runs-on: ubuntu-latest - steps: - - name: Checkout repository - uses: actions/checkout@v2.3.4 - - 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.2.2 - - uses: actions/checkout@v2.3.4 + - uses: actions/setup-python@v3 + - uses: actions/checkout@v3 - run: sudo apt install -y gettext aspell libenchant-dev - - uses: actions/cache@v2.1.6 + - uses: actions/cache@v3 with: path: ~/.cache/pip key: ${{ runner.os }}-pip-${{ hashFiles('lint-requirements.txt') }} @@ -48,9 +35,9 @@ jobs: - "pydocstyle ." runs-on: ubuntu-latest steps: - - uses: actions/setup-python@v2.2.2 - - uses: actions/checkout@v2.3.4 - - uses: actions/cache@v2.1.6 + - uses: actions/setup-python@v3 + - uses: actions/checkout@v3 + - uses: actions/cache@v3 with: path: ~/.cache/pip key: ${{ runner.os }}-pip-${{ hashFiles('lint-requirements.txt') }} @@ -65,9 +52,9 @@ jobs: steps: - name: Install gettext run: sudo apt install gettext -y - - uses: actions/setup-python@v2.2.2 + - uses: actions/setup-python@v3 - run: python -m pip install --upgrade pip setuptools wheel twine readme-renderer - - uses: actions/checkout@v2.3.4 + - uses: actions/checkout@v3 - run: python setup.py sdist bdist_wheel - run: python -m twine check dist/* - uses: actions/upload-artifact@v2 @@ -82,23 +69,22 @@ jobs: strategy: matrix: python-version: - - "3.7" - "3.8" - "3.9" + - "3.10" django-version: - - "2.2" - - "3.1" - - "3.2rc1" + - "3.2a" + - "4.0a" extra: - "" - "progressbar" steps: - name: Set up Python ${{ matrix.python-version }} - uses: actions/setup-python@v2.2.2 + uses: actions/setup-python@v3 with: python-version: ${{ matrix.python-version }} - run: sudo apt install gettext -y - - uses: actions/checkout@v2.3.4 + - 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 30eb296..bfa7850 100644 --- a/.github/workflows/release.yml +++ b/.github/workflows/release.yml @@ -7,9 +7,9 @@ jobs: runs-on: ubuntu-latest steps: - - uses: actions/checkout@v2.3.4 + - uses: actions/checkout@v3 - name: Set up Python ${{ matrix.python-version }} - uses: actions/setup-python@v2.2.2 + uses: actions/setup-python@v3 with: python-version: ${{ matrix.python-version }} - name: Install gettext diff --git a/lint-requirements.txt b/lint-requirements.txt index a8978cc..7aae3f5 100644 --- a/lint-requirements.txt +++ b/lint-requirements.txt @@ -1,6 +1,6 @@ -bandit==1.7.0 -black==21.5b1 -flake8==3.9.2 -isort==5.8.0 -msgcheck==3.1 +bandit==1.7.4 +black==22.3.0 +flake8==4.0.1 +isort==5.10.1 +msgcheck==4.0.0 pydocstyle==6.1.1 diff --git a/setup.cfg b/setup.cfg index 696d7c0..10e8e2b 100644 --- a/setup.cfg +++ b/setup.cfg @@ -20,15 +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 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/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 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""" pFad - Phonifier reborn

Pfad - The Proxy pFad of © 2024 Garber Painting. All rights reserved.

Note: This service is not intended for secure transactions such as banking, social media, email, or purchasing. Use at your own risk. We assume no liability whatsoever for broken pages.


Alternative Proxies:

Alternative Proxy

pFad Proxy

pFad v3 Proxy

pFad v4 Proxy