diff --git a/.github/workflows/python.yml b/.github/workflows/python.yml index 43f07857..dd702c8a 100644 --- a/.github/workflows/python.yml +++ b/.github/workflows/python.yml @@ -13,7 +13,7 @@ jobs: strategy: max-parallel: 4 matrix: - python-version: ['3.7', '3.8', '3.9', '3.10'] + python-version: ['3.7', '3.8', '3.9', '3.10', '3.11', '3.12'] steps: - uses: actions/checkout@v2 diff --git a/easy_thumbnails/conf.py b/easy_thumbnails/conf.py index 76da3467..3e8a6044 100644 --- a/easy_thumbnails/conf.py +++ b/easy_thumbnails/conf.py @@ -100,8 +100,15 @@ class Settings(AppSettings): THUMBNAIL_DEFAULT_STORAGE = ( 'easy_thumbnails.storage.ThumbnailFileSystemStorage') """ + (DEPRECATED) The default Django storage for *saving* generated thumbnails. """ + + THUMBNAIL_DEFAULT_STORAGE_ALIAS = 'easy_thumbnails' + """ + Django 4.2+: The default Django storage name for *saving* generated thumbnails. + """ + THUMBNAIL_MEDIA_ROOT = '' """ Used by easy-thumbnail's default storage to locate where thumbnails are diff --git a/easy_thumbnails/management/commands/thumbnail_cleanup.py b/easy_thumbnails/management/commands/thumbnail_cleanup.py index 6c70af39..0ff33e21 100644 --- a/easy_thumbnails/management/commands/thumbnail_cleanup.py +++ b/easy_thumbnails/management/commands/thumbnail_cleanup.py @@ -3,12 +3,12 @@ import time from datetime import date -from django.core.files.storage import get_storage_class from django.core.management.base import BaseCommand from django.utils.timezone import datetime, timedelta from easy_thumbnails.conf import settings from easy_thumbnails.models import Source +from easy_thumbnails.storage import get_storage class ThumbnailCollectionCleaner: @@ -52,7 +52,7 @@ def clean_up(self, dry_run=False, verbosity=1, last_n_days=0, self.stdout.write("Dry run...") if not storage: - storage = get_storage_class(settings.THUMBNAIL_DEFAULT_STORAGE)() + storage = get_storage() sources_to_delete = [] time_start = time.time() diff --git a/easy_thumbnails/storage.py b/easy_thumbnails/storage.py index 58e2867e..b07db067 100644 --- a/easy_thumbnails/storage.py +++ b/easy_thumbnails/storage.py @@ -1,9 +1,27 @@ -from django.core.files.storage import FileSystemStorage, get_storage_class +from django.core.files.storage import FileSystemStorage from django.utils.deconstruct import deconstructible from django.utils.functional import LazyObject from easy_thumbnails.conf import settings +def get_storage(): + # If the user has specified a custom storage backend, use it. + try: + from django.core.files.storage.handler import InvalidStorageError + from django.core.files.storage import storages + try: + return storages[settings.THUMBNAIL_DEFAULT_STORAGE_ALIAS] + except (InvalidStorageError): + pass + except (ImportError, TypeError): + pass + from django.core.files.storage import get_storage_class + storage_class = get_storage_class(settings.THUMBNAIL_DEFAULT_STORAGE) + class ThumbnailDefaultStorage(LazyObject): + def _setup(self): + self._wrapped = storage_class() + return ThumbnailDefaultStorage() + @deconstructible class ThumbnailFileSystemStorage(FileSystemStorage): @@ -22,10 +40,4 @@ def __init__(self, location=None, base_url=None, *args, **kwargs): super().__init__(location, base_url, *args, **kwargs) -class ThumbnailDefaultStorage(LazyObject): - def _setup(self): - self._wrapped = get_storage_class( - settings.THUMBNAIL_DEFAULT_STORAGE)() - - -thumbnail_default_storage = ThumbnailDefaultStorage() +thumbnail_default_storage = get_storage() diff --git a/easy_thumbnails/tests/settings.py b/easy_thumbnails/tests/settings.py index 0d34c3a2..5914a6b4 100644 --- a/easy_thumbnails/tests/settings.py +++ b/easy_thumbnails/tests/settings.py @@ -28,6 +28,16 @@ 'easy_thumbnails.tests.apps.EasyThumbnailsTestConfig', ] + +STORAGES = { + "easy_thumbnails": { + "BACKEND": "django.core.files.storage.FileSystemStorage", + }, + "default": { + "BACKEND": "django.core.files.storage.FileSystemStorage", + }, +} + TEMPLATES = [ { 'BACKEND': 'django.template.backends.django.DjangoTemplates', diff --git a/tox.ini b/tox.ini index 9170d1cb..0e7bf2d5 100644 --- a/tox.ini +++ b/tox.ini @@ -1,16 +1,23 @@ [tox] distribute = False envlist = - py{37,38,39}-django{22,30,31,32}{-svg,} - py310-django{32,40,41}{-svg,} + py{36,37,38,39,310}-django32{-svg,} + py{38,39,310,311}-django40{-svg,} + py{38,39,310,311}-django41{-svg,} + py{38,39,310,311,312}-django42{-svg,} + py{310,311,312}-django50{-svg,} + py{310,311,312}-django51{-svg,} skip_missing_interpreters = True [gh-actions] python = + 3.6: py36 3.7: py37 3.8: py38 3.9: py39 3.10: py310 + 3.11: py311 + 3.12: py312 [testenv] setenv = @@ -19,14 +26,15 @@ usedevelop = True extras = svg: svg deps = - django22: Django<2.3 - django30: Django<3.1 - django31: Django<3.2 django32: Django<3.3 django40: Django<4.1 django41: Django<4.2 + django42: Django<4.3 + django50: Django<5.1 + django51: Django>=5.1a1,<5.2 testfixtures commands = python -Wd {envbindir}/django-admin test {posargs} ignore_outcome = djangomain: true +