Skip to content

Commit 1d709ae

Browse files
authored
feat: Accept new STORAGES setting, introduced in Django 4.2 (#1472)
* fix: use Django's `STORAGES` setting if it exists * fix: pyupgrade to 3.8+
1 parent 2ac8c15 commit 1d709ae

16 files changed

+43
-38
lines changed

docs/settings.rst

+3-1
Original file line numberDiff line numberDiff line change
@@ -69,7 +69,9 @@ e.g::
6969

7070
Defaults to FileSystemStorage in ``<MEDIA_ROOT>/filer_public/`` and ``<MEDIA_ROOT>/filer_public_thumbnails/`` for public files and
7171
``<MEDIA_ROOT>/../smedia/filer_private/`` and ``<MEDIA_ROOT>/../smedia/filer_private_thumbnails/`` for private files.
72-
Public storage uses ``DEFAULT_FILE_STORAGE`` as default storage backend.
72+
Public storage uses the default storage's backend. This is taken from Django's ``STORAGES``
73+
setting if it exists or, if not, from the ``DEFAULT_FILE_STORAGE`` setting for compatibility
74+
with earlier Django versions (5.0 or below).
7375

7476
``UPLOAD_TO`` is the function to generate the path relative to the storage root. The
7577
default generates a random path like ``1d/a5/1da50fee-5003-46a1-a191-b547125053a8/filename.jpg``. This

filer/admin/fileadmin.py

+1-1
Original file line numberDiff line numberDiff line change
@@ -192,7 +192,7 @@ def get_model_perms(self, request):
192192
def display_canonical(self, instance):
193193
canonical = instance.canonical_url
194194
if canonical:
195-
return mark_safe('<a href="{}">{}</a>'.format(canonical, canonical))
195+
return mark_safe(f'<a href="{canonical}">{canonical}</a>')
196196
else:
197197
return '-'
198198
display_canonical.allow_tags = True

filer/admin/folderadmin.py

+4-4
Original file line numberDiff line numberDiff line change
@@ -253,10 +253,10 @@ def directory_listing(self, request, folder_id=None, viewtype=None):
253253
self.get_queryset(request).get(id=last_folder_id)
254254
except self.model.DoesNotExist:
255255
url = reverse('admin:filer-directory_listing-root')
256-
url = "{}{}".format(url, admin_url_params_encoded(request))
256+
url = f"{url}{admin_url_params_encoded(request)}"
257257
else:
258258
url = reverse('admin:filer-directory_listing', kwargs={'folder_id': last_folder_id})
259-
url = "{}{}".format(url, admin_url_params_encoded(request))
259+
url = f"{url}{admin_url_params_encoded(request)}"
260260
return HttpResponseRedirect(url)
261261
elif folder_id is None:
262262
folder = FolderRoot()
@@ -840,7 +840,7 @@ def _format_callback(self, obj, user, admin_site, perms_needed):
840840
else:
841841
# Don't display link to edit, because it either has no
842842
# admin or is edited inline.
843-
return '{}: {}'.format(capfirst(opts.verbose_name), force_str(obj))
843+
return f'{capfirst(opts.verbose_name)}: {force_str(obj)}'
844844

845845
def _check_copy_perms(self, request, files_queryset, folders_queryset):
846846
try:
@@ -1073,7 +1073,7 @@ def _get_available_name(self, destination, name):
10731073
count = itertools.count(1)
10741074
original = name
10751075
while destination.contains_folder(name):
1076-
name = "{}_{}".format(original, next(count))
1076+
name = f"{original}_{next(count)}"
10771077
return name
10781078

10791079
def _copy_folder(self, folder, destination, suffix, overwrite):

filer/fields/file.py

+1-1
Original file line numberDiff line numberDiff line change
@@ -60,7 +60,7 @@ def render(self, name, value, attrs=None, renderer=None):
6060
hidden_input = super(ForeignKeyRawIdWidget, self).render(name, value, attrs) # grandparent super
6161
context = {
6262
'hidden_input': hidden_input,
63-
'lookup_url': '{}{}'.format(related_url, lookup_url),
63+
'lookup_url': f'{related_url}{lookup_url}',
6464
'change_url': change_url,
6565
'object': obj,
6666
'lookup_name': name,

filer/fields/folder.py

+1-1
Original file line numberDiff line numberDiff line change
@@ -54,7 +54,7 @@ def render(self, name, value, attrs=None, renderer=None):
5454
# API to determine the ID dynamically.
5555
context = {
5656
'hidden_input': hidden_input,
57-
'lookup_url': '{}{}'.format(related_url, url),
57+
'lookup_url': f'{related_url}{url}',
5858
'lookup_name': name,
5959
'span_id': css_id_description_txt,
6060
'object': obj,

filer/fields/multistorage_file.py

+1-1
Original file line numberDiff line numberDiff line change
@@ -159,7 +159,7 @@ def value_to_string(self, obj):
159159
encoded_string = base64.b64encode(payload_file.read()).decode('utf-8')
160160
return value, encoded_string
161161
except OSError:
162-
warnings.warn('The payload for "{}" is missing. No such file on disk: {}!'.format(obj.original_filename, self.storage.location))
162+
warnings.warn(f'The payload for "{obj.original_filename}" is missing. No such file on disk: {self.storage.location}!')
163163
return value
164164

165165
def to_python(self, value):

filer/models/clipboardmodels.py

+1-1
Original file line numberDiff line numberDiff line change
@@ -35,7 +35,7 @@ def append_file(self, file_obj):
3535
return True
3636

3737
def __str__(self):
38-
return "Clipboard {} of {}".format(self.id, self.user)
38+
return f"Clipboard {self.id} of {self.user}"
3939

4040

4141
class ClipboardItem(models.Model):

filer/models/filemodels.py

+3-3
Original file line numberDiff line numberDiff line change
@@ -158,9 +158,9 @@ class Meta:
158158

159159
def __str__(self):
160160
if self.name in ('', None):
161-
text = "{}".format(self.original_filename)
161+
text = f"{self.original_filename}"
162162
else:
163-
text = "{}".format(self.name)
163+
text = f"{self.name}"
164164
return text
165165

166166
@classmethod
@@ -312,7 +312,7 @@ def label(self):
312312
text = self.original_filename or 'unnamed file'
313313
else:
314314
text = self.name
315-
text = "{}".format(text)
315+
text = f"{text}"
316316
return text
317317

318318
def __lt__(self, other):

filer/models/thumbnailoptionmodels.py

+1-1
Original file line numberDiff line numberDiff line change
@@ -38,7 +38,7 @@ class Meta:
3838
verbose_name_plural = _("thumbnail options")
3939

4040
def __str__(self):
41-
return '{} -- {} x {}'.format(self.name, self.width, self.height)
41+
return f'{self.name} -- {self.width} x {self.height}'
4242

4343
@property
4444
def as_dict(self):

filer/settings.py

+4-1
Original file line numberDiff line numberDiff line change
@@ -59,7 +59,10 @@
5959
settings, 'FILER_FILE_MODELS',
6060
(FILER_IMAGE_MODEL, 'filer.File'))
6161

62-
DEFAULT_FILE_STORAGE = getattr(settings, 'DEFAULT_FILE_STORAGE', 'django.core.files.storage.FileSystemStorage')
62+
if hasattr(settings, "STORAGES") and 'default' in settings.STORAGES:
63+
DEFAULT_FILE_STORAGE = settings.STORAGES['default'].get('BACKEND', 'django.core.files.storage.FileSystemStorage')
64+
else:
65+
DEFAULT_FILE_STORAGE = getattr(settings, 'DEFAULT_FILE_STORAGE', 'django.core.files.storage.FileSystemStorage')
6366

6467
MINIMAL_FILER_STORAGES = {
6568
'public': {

filer/templatetags/filer_tags.py

+1-1
Original file line numberDiff line numberDiff line change
@@ -89,7 +89,7 @@ def filesize(bytes, format='auto1024'):
8989
unit = '{}{}'.format(base == 1024 and unit.upper() or unit,
9090
base == 1024 and 'iB' or 'B')
9191

92-
return '{} {}'.format(bytes, unit)
92+
return f'{bytes} {unit}'
9393

9494
if bytes == 0:
9595
return bytes

tests/helpers.py

+1-1
Original file line numberDiff line numberDiff line change
@@ -25,7 +25,7 @@ def create_folder_structure(depth=2, sibling=2, parent=None):
2525
depth_range.reverse()
2626
for d in depth_range:
2727
for s in range(1, sibling + 1):
28-
name = "folder: %s -- %s" % (str(d), str(s))
28+
name = "folder: {} -- {}".format(str(d), str(s))
2929
folder = Folder(name=name, parent=parent)
3030
folder.save()
3131
create_folder_structure(depth=d - 1, sibling=sibling, parent=folder)

tests/test_admin.py

+16-16
Original file line numberDiff line numberDiff line change
@@ -629,7 +629,7 @@ def test_filer_ajax_upload_file_error(self):
629629
'admin:filer-ajax_upload',
630630
kwargs={
631631
'folder_id': folder.pk + 1}
632-
) + '?filename={0}'.format(self.image_name)
632+
) + f'?filename={self.image_name}'
633633
response = self.client.post(
634634
url,
635635
data=file_obj.read(),
@@ -693,7 +693,7 @@ def test_filer_ajax_upload_without_permissions_error(self, extra_headers={}):
693693
'admin:filer-ajax_upload',
694694
kwargs={
695695
'folder_id': folder.pk}
696-
) + '?filename={0}'.format(self.image_name)
696+
) + f'?filename={self.image_name}'
697697
response = self.client.post(
698698
url,
699699
data=file_obj.read(),
@@ -759,7 +759,7 @@ def test_filer_ajax_upload_permissions_error(self, extra_headers={}):
759759
'admin:filer-ajax_upload',
760760
kwargs={
761761
'folder_id': folder.pk}
762-
) + '?filename={0}'.format(self.image_name)
762+
) + f'?filename={self.image_name}'
763763
response = self.client.post(
764764
url,
765765
data=file_obj.read(),
@@ -1103,10 +1103,10 @@ def _do_test_rename(self, url, new_name, file_obj=None, folder_obj=None):
11031103
'new_name' should be a plain string, no formatting supported.
11041104
"""
11051105
if file_obj is not None:
1106-
checkbox_name = 'file-{}'.format(file_obj.id)
1106+
checkbox_name = f'file-{file_obj.id}'
11071107
files = [file_obj]
11081108
elif folder_obj is not None:
1109-
checkbox_name = 'folder-{}'.format(folder_obj.id)
1109+
checkbox_name = f'folder-{folder_obj.id}'
11101110
# files inside this folder, non-recursive
11111111
files = File.objects.filter(folder=folder_obj)
11121112
else:
@@ -1322,9 +1322,9 @@ def test_with_permissions_disabled(self):
13221322
item_list = response.context['paginated_items'].object_list
13231323
# user sees all items: FOO, BAR, BAZ, SAMP
13241324
self.assertEqual(
1325-
set(folder.pk for folder in item_list),
1326-
set([self.foo_folder.pk, self.bar_folder.pk, self.baz_folder.pk,
1327-
self.spam_file.pk]))
1325+
{folder.pk for folder in item_list},
1326+
{self.foo_folder.pk, self.bar_folder.pk, self.baz_folder.pk, self.spam_file.pk}
1327+
)
13281328

13291329
def test_folder_ownership(self):
13301330
with SettingsOverride(filer_settings, FILER_ENABLE_PERMISSIONS=True):
@@ -1336,8 +1336,8 @@ def test_folder_ownership(self):
13361336
# he doesn't see BAR, BAZ and SPAM because he doesn't own them
13371337
# and no permission has been given
13381338
self.assertEqual(
1339-
set(folder.pk for folder in item_list),
1340-
set([self.foo_folder.pk]))
1339+
{folder.pk for folder in item_list},
1340+
{self.foo_folder.pk})
13411341

13421342
def test_with_permission_given_to_folder(self):
13431343
with SettingsOverride(filer_settings, FILER_ENABLE_PERMISSIONS=True):
@@ -1355,8 +1355,8 @@ def test_with_permission_given_to_folder(self):
13551355
item_list = response.context['paginated_items'].object_list
13561356
# user sees 2 folder : FOO, BAR
13571357
self.assertEqual(
1358-
set(folder.pk for folder in item_list),
1359-
set([self.foo_folder.pk, self.bar_folder.pk]))
1358+
{folder.pk for folder in item_list},
1359+
{self.foo_folder.pk, self.bar_folder.pk})
13601360

13611361
def test_with_permission_given_to_parent_folder(self):
13621362
with SettingsOverride(filer_settings, FILER_ENABLE_PERMISSIONS=True):
@@ -1373,9 +1373,9 @@ def test_with_permission_given_to_parent_folder(self):
13731373
item_list = response.context['paginated_items'].object_list
13741374
# user sees all items because he has permissions on the parent folder
13751375
self.assertEqual(
1376-
set(folder.pk for folder in item_list),
1377-
set([self.foo_folder.pk, self.bar_folder.pk, self.baz_folder.pk,
1378-
self.spam_file.pk]))
1376+
{folder.pk for folder in item_list},
1377+
{self.foo_folder.pk, self.bar_folder.pk, self.baz_folder.pk, self.spam_file.pk}
1378+
)
13791379

13801380
def test_search_against_owner(self):
13811381
url = reverse('admin:filer-directory_listing',
@@ -1416,7 +1416,7 @@ def test_search_special_characters(self):
14161416

14171417
# Create a file with a problematic filename
14181418
problematic_file = django.core.files.base.ContentFile('some data')
1419-
filename = u'christopher_eccleston'
1419+
filename = 'christopher_eccleston'
14201420
problematic_file.name = filename
14211421
self.spam_file = File.objects.create(
14221422
owner=self.staff_user, original_filename=filename,

tests/test_form_fields.py

+1-1
Original file line numberDiff line numberDiff line change
@@ -24,5 +24,5 @@ def test_widget_has_change_button(self):
2424
content = widget.render("foo", file.id, {})
2525

2626
self.assertIn(
27-
"/admin/filer/file/{}/change/?_edit_from_widget=1".format(file.id), content
27+
f"/admin/filer/file/{file.id}/change/?_edit_from_widget=1", content
2828
)

tests/test_migrations.py

+1-1
Original file line numberDiff line numberDiff line change
@@ -27,4 +27,4 @@ def test_for_missing_migrations(self):
2727
status_code = '0'
2828

2929
if status_code == '1':
30-
self.fail('There are missing migrations:\n {}'.format(output.getvalue()))
30+
self.fail(f'There are missing migrations:\n {output.getvalue()}')

tests/test_models.py

+3-3
Original file line numberDiff line numberDiff line change
@@ -87,19 +87,19 @@ def test_create_icons(self):
8787
self.assertEqual(len(icons), len(filer_settings.FILER_ADMIN_ICON_SIZES))
8888
for size in filer_settings.FILER_ADMIN_ICON_SIZES:
8989
self.assertEqual(os.path.basename(icons[size]),
90-
file_basename + '__%sx%s_q85_crop_subsampling-2_upscale.jpg' % (size, size))
90+
file_basename + '__{}x{}_q85_crop_subsampling-2_upscale.jpg'.format(size, size))
9191

9292
def test_access_icons_property(self):
9393
"""Test IconsMixin that calls static on a non-existent file"""
9494

95-
class CustomObj(IconsMixin, object):
95+
class CustomObj(IconsMixin):
9696
_icon = 'custom'
9797

9898
custom_obj = CustomObj()
9999
try:
100100
icons = custom_obj.icons
101101
except Exception as e:
102-
self.fail("'.icons' access raised Exception {0} unexpectedly!".format(e))
102+
self.fail(f"'.icons' access raised Exception {e} unexpectedly!")
103103
self.assertEqual(len(icons), len(filer_settings.FILER_ADMIN_ICON_SIZES))
104104

105105
def test_file_upload_public_destination(self):

0 commit comments

Comments
 (0)