From ff5558106a82ba4b7d025c9e1d323f7f11003aad Mon Sep 17 00:00:00 2001 From: vchrisb Date: Wed, 17 Nov 2021 14:45:51 +0100 Subject: [PATCH] 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"""