Skip to content

Commit a6a2b8c

Browse files
committed
apply ruff format
1 parent 41db358 commit a6a2b8c

15 files changed

Lines changed: 364 additions & 257 deletions

File tree

admin_async_upload/fields.py

Lines changed: 10 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,7 @@ class FormResumableFileField(fields.FileField):
1111
def to_python(self, data):
1212
if self.required:
1313
if not data or data == "None":
14-
raise ValidationError(self.error_messages['empty'])
14+
raise ValidationError(self.error_messages["empty"])
1515
return data
1616

1717

@@ -20,17 +20,18 @@ class FormResumableMultipleFileField(fields.Field):
2020
Form field that handles multiple file uploads via resumable.js.
2121
Stores file paths as a JSON array and returns a list of file paths.
2222
"""
23+
2324
widget = ResumableAdminWidget
2425

2526
def to_python(self, data):
2627
"""Convert JSON string to Python list of file paths."""
27-
if not data or data in ['None', 'False', None]:
28+
if not data or data in ["None", "False", None]:
2829
return []
29-
30+
3031
# If already a list, return it
3132
if isinstance(data, list):
3233
return data
33-
34+
3435
# Try to parse as JSON
3536
try:
3637
parsed = json.loads(data)
@@ -49,19 +50,19 @@ def clean(self, value):
4950
"""
5051
# Convert to Python type (list of file paths)
5152
value = self.to_python(value)
52-
53+
5354
# Run validation
5455
self.validate(value)
55-
56+
5657
# Run any custom validators
5758
self.run_validators(value)
58-
59+
5960
return value
6061

6162
def prepare_value(self, value):
6263
"""Convert Python list to JSON string for rendering."""
6364
if value is None:
64-
return ''
65+
return ""
6566
if isinstance(value, str):
6667
return value
6768
if isinstance(value, list):
@@ -71,5 +72,4 @@ def prepare_value(self, value):
7172
def validate(self, value):
7273
"""Validate that all file paths in the list are valid."""
7374
if self.required and not value:
74-
raise ValidationError(self.error_messages['required'])
75-
75+
raise ValidationError(self.error_messages["required"])

admin_async_upload/files.py

Lines changed: 24 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -25,7 +25,7 @@ def __init__(self, field, user, params):
2525
self.user = user
2626
self.params = params
2727
self.chunk_suffix = "_part_"
28-
self.chunk_folder = getattr(settings, 'ADMIN_RESUMABLE_CHUNK_FOLDER', '')
28+
self.chunk_folder = getattr(settings, "ADMIN_RESUMABLE_CHUNK_FOLDER", "")
2929

3030
@cached_property
3131
def resumable_storage(self):
@@ -46,7 +46,9 @@ def storage_filename(self):
4646
instance = self.field.model.objects.filter(pk=instance_id).first()
4747
else:
4848
instance = None
49-
return self.resumable_storage.full_filename(self.filename, self.upload_to, instance=instance)
49+
return self.resumable_storage.full_filename(
50+
self.filename, self.upload_to, instance=instance
51+
)
5052

5153
@property
5254
def upload_to(self):
@@ -57,8 +59,11 @@ def chunk_exists(self):
5759
"""
5860
Checks if the requested chunk exists.
5961
"""
60-
return self.chunk_storage.exists(self.current_chunk_name) and \
61-
self.chunk_storage.size(self.current_chunk_name) == int(self.params.get('resumableCurrentChunkSize'))
62+
return self.chunk_storage.exists(
63+
self.current_chunk_name
64+
) and self.chunk_storage.size(self.current_chunk_name) == int(
65+
self.params.get("resumableCurrentChunkSize")
66+
)
6267

6368
@property
6469
def chunk_names(self):
@@ -72,10 +77,9 @@ def chunk_names(self):
7277
# chunks folder doesn't exist yet
7378
return chunks
7479
for file in files:
75-
if fnmatch.fnmatch(file, '%s%s*' % (self.filename,
76-
self.chunk_suffix)):
80+
if fnmatch.fnmatch(file, "%s%s*" % (self.filename, self.chunk_suffix)):
7781
if self.chunk_folder:
78-
chunks.append(self.chunk_folder + '/' + file)
82+
chunks.append(self.chunk_folder + "/" + file)
7983
else:
8084
chunks.append(file)
8185
return chunks
@@ -86,7 +90,7 @@ def current_chunk_name(self):
8690
chunk_name = "%s%s%s" % (
8791
self.filename,
8892
self.chunk_suffix,
89-
self.params.get('resumableChunkNumber').zfill(4)
93+
self.params.get("resumableChunkNumber").zfill(4),
9094
)
9195
if self.chunk_folder:
9296
return "%s/%s" % (self.chunk_folder, chunk_name)
@@ -97,11 +101,10 @@ def chunks(self):
97101
Iterates over all stored chunks.
98102
"""
99103
# TODO: add user identifier to chunk name
100-
files = sorted(self.chunk_storage.listdir('')[1])
104+
files = sorted(self.chunk_storage.listdir("")[1])
101105
for file in files:
102-
if fnmatch.fnmatch(file, '%s%s*' % (self.filename,
103-
self.chunk_suffix)):
104-
yield self.chunk_storage.open(file, 'rb').read()
106+
if fnmatch.fnmatch(file, "%s%s*" % (self.filename, self.chunk_suffix)):
107+
yield self.chunk_storage.open(file, "rb").read()
105108

106109
def delete_chunks(self):
107110
[self.chunk_storage.delete(chunk) for chunk in self.chunk_names]
@@ -112,7 +115,7 @@ def file(self):
112115
Merges file and returns its file pointer.
113116
"""
114117
if not self.is_complete:
115-
raise Exception('Chunk(s) still missing')
118+
raise Exception("Chunk(s) still missing")
116119
outfile = tempfile.NamedTemporaryFile("w+b")
117120
for chunk in self.chunk_names:
118121
outfile.write(self.chunk_storage.open(chunk).read())
@@ -124,18 +127,18 @@ def filename(self):
124127
Gets the filename.
125128
"""
126129
# TODO: add user identifier to chunk name
127-
filename = self.params.get('resumableFilename')
128-
if '/' in filename:
129-
raise Exception('Invalid filename')
130-
value = "%s_%s" % (self.params.get('resumableTotalSize'), filename)
130+
filename = self.params.get("resumableFilename")
131+
if "/" in filename:
132+
raise Exception("Invalid filename")
133+
value = "%s_%s" % (self.params.get("resumableTotalSize"), filename)
131134
return value
132135

133136
@property
134137
def is_complete(self):
135138
"""
136139
Checks if all chunks are already stored.
137140
"""
138-
return int(self.params.get('resumableTotalSize')) == self.size
141+
return int(self.params.get("resumableTotalSize")) == self.size
139142

140143
def process_chunk(self, file):
141144
"""
@@ -160,6 +163,8 @@ def collect(self):
160163
Saves the complete file to persistent storage and deletes chunks.
161164
Returns the actual filename in persistent storage.
162165
"""
163-
actual_filename = self.persistent_storage.save(self.storage_filename, File(self.file))
166+
actual_filename = self.persistent_storage.save(
167+
self.storage_filename, File(self.file)
168+
)
164169
self.delete_chunks()
165170
return actual_filename

admin_async_upload/models.py

Lines changed: 11 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -4,22 +4,25 @@
44

55

66
class AsyncFileField(models.FileField):
7-
87
def __init__(self, *args, **kwargs):
9-
self.max_files = kwargs.pop('max_files', None)
8+
self.max_files = kwargs.pop("max_files", None)
109
super(AsyncFileField, self).__init__(*args, **kwargs)
11-
10+
1211
def deconstruct(self):
1312
name, path, args, kwargs = super(AsyncFileField, self).deconstruct()
1413
if self.max_files is not None:
15-
kwargs['max_files'] = self.max_files
14+
kwargs["max_files"] = self.max_files
1615
return name, path, args, kwargs
1716

1817
def formfield(self, **kwargs):
19-
defaults = {'form_class': FormResumableFileField}
18+
defaults = {"form_class": FormResumableFileField}
2019
if self.model and self.name:
21-
defaults['widget'] = ResumableAdminWidget(attrs={
22-
'model': self.model,
23-
'field_name': self.name, 'max_files': getattr(self, 'max_files', None)})
20+
defaults["widget"] = ResumableAdminWidget(
21+
attrs={
22+
"model": self.model,
23+
"field_name": self.name,
24+
"max_files": getattr(self, "max_files", None),
25+
}
26+
)
2427
kwargs.update(defaults)
2528
return super(AsyncFileField, self).formfield(**kwargs)

admin_async_upload/storage.py

Lines changed: 21 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
import datetime
22

33
import posixpath
4+
45
try:
56
from django.core.files.storage import storages, InvalidStorageError
67
except ImportError:
@@ -13,11 +14,14 @@
1314

1415

1516
class ResumableStorage(object):
16-
1717
def __init__(self):
1818
# For backward compatibility, still check old settings
19-
self.persistent_storage_name = getattr(settings, 'ADMIN_RESUMABLE_STORAGE', None)
20-
self.chunk_storage_name = getattr(settings, 'ADMIN_RESUMABLE_CHUNK_STORAGE', None)
19+
self.persistent_storage_name = getattr(
20+
settings, "ADMIN_RESUMABLE_STORAGE", None
21+
)
22+
self.chunk_storage_name = getattr(
23+
settings, "ADMIN_RESUMABLE_CHUNK_STORAGE", None
24+
)
2125

2226
def get_chunk_storage(self, *args, **kwargs):
2327
"""
@@ -35,24 +39,29 @@ def get_chunk_storage(self, *args, **kwargs):
3539
except (KeyError, InvalidStorageError):
3640
# Not a STORAGES key, treat as class path
3741
from django.core.files.storage import get_storage_class
42+
3843
storage_class = get_storage_class(self.chunk_storage_name)
3944
return storage_class(*args, **kwargs)
4045
else:
4146
# Older Django - use get_storage_class
4247
from django.core.files.storage import get_storage_class
48+
4349
storage_class = get_storage_class(self.chunk_storage_name)
4450
return storage_class(*args, **kwargs)
4551
else:
4652
# Default to local FileSystemStorage for performance
4753
# (chunks should not be written to remote storage like S3)
4854
if storages:
4955
from django.core.files.storage import FileSystemStorage
56+
5057
return FileSystemStorage(*args, **kwargs)
5158
else:
5259
from django.core.files.storage import get_storage_class
53-
storage_class = get_storage_class('django.core.files.storage.FileSystemStorage')
60+
61+
storage_class = get_storage_class(
62+
"django.core.files.storage.FileSystemStorage"
63+
)
5464
return storage_class(*args, **kwargs)
55-
5665

5766
def get_persistent_storage(self, *args, **kwargs):
5867
"""
@@ -66,17 +75,21 @@ def get_persistent_storage(self, *args, **kwargs):
6675
if self.persistent_storage_name:
6776
# If a specific storage backend is configured, use it
6877
from django.core.files.storage import get_storage_class
78+
6979
storage_class = get_storage_class(self.persistent_storage_name)
7080
return storage_class(*args, **kwargs)
7181
else:
7282
# Use default storage from STORAGES setting
73-
return storages['default']
83+
return storages["default"]
7484
else:
7585
# Fallback for older Django versions
7686
from django.core.files.storage import get_storage_class
7787

78-
persistent_storage_class_name = self.persistent_storage_name or \
79-
getattr(settings, 'DEFAULT_FILE_STORAGE', 'django.core.files.storage.FileSystemStorage')
88+
persistent_storage_class_name = self.persistent_storage_name or getattr(
89+
settings,
90+
"DEFAULT_FILE_STORAGE",
91+
"django.core.files.storage.FileSystemStorage",
92+
)
8093
storage_class = get_storage_class(persistent_storage_class_name)
8194

8295
return storage_class(*args, **kwargs)

admin_async_upload/urls.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,5 +3,5 @@
33
from . import views
44

55
urlpatterns = [
6-
path('upload/', views.admin_resumable, name='admin_resumable'),
6+
path("upload/", views.admin_resumable, name="admin_resumable"),
77
]

admin_async_upload/validators.py

Lines changed: 36 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -12,11 +12,18 @@ class StorageFileValidator(object):
1212
Any validation must happen either on the client-side or requires upload to be completed
1313
and file saved in application storage.
1414
"""
15+
1516
messages = {
16-
'file': _(u"File {name} does not exist."),
17-
'extension': _(u"Extension {extension} not allowed. Allowed extensions are: {allowed_extensions}"),
18-
'min_size': _(u"File {name} too small ({size} bytes). The minimum file size is {min_size} bytes."),
19-
'max_size': _(u"File {name} too large ({size} bytes). The maximum file size is {max_size} bytes."),
17+
"file": _("File {name} does not exist."),
18+
"extension": _(
19+
"Extension {extension} not allowed. Allowed extensions are: {allowed_extensions}"
20+
),
21+
"min_size": _(
22+
"File {name} too small ({size} bytes). The minimum file size is {min_size} bytes."
23+
),
24+
"max_size": _(
25+
"File {name} too large ({size} bytes). The maximum file size is {max_size} bytes."
26+
),
2027
}
2128

2229
def __init__(self, min_size=0, max_size=None, allowed_extensions=None):
@@ -30,34 +37,42 @@ def get_storage(self):
3037
def validate_extension(self, value):
3138
ext = splitext(value)[1].lower()
3239
if self.allowed_extensions and ext not in self.allowed_extensions:
33-
message = self.messages['extension'].format(**{
34-
'extension': ext,
35-
'allowed_extensions': ', '.join(self.allowed_extensions)
36-
})
40+
message = self.messages["extension"].format(
41+
**{
42+
"extension": ext,
43+
"allowed_extensions": ", ".join(self.allowed_extensions),
44+
}
45+
)
3746
raise ValidationError(message)
3847

3948
def validate_exists(self, value, storage):
4049
if not storage.exists(value):
41-
message = self.messages['file'].format(**{
42-
'name': value,
43-
})
50+
message = self.messages["file"].format(
51+
**{
52+
"name": value,
53+
}
54+
)
4455
raise ValidationError(message)
4556

4657
def validate_size(self, value, storage):
4758
size = storage.size(value)
4859
if size > self.max_size:
49-
message = self.messages['max_size'].format(**{
50-
'name': value,
51-
'size': size,
52-
'max_size': self.max_size,
53-
})
60+
message = self.messages["max_size"].format(
61+
**{
62+
"name": value,
63+
"size": size,
64+
"max_size": self.max_size,
65+
}
66+
)
5467
raise ValidationError(message)
5568
elif size < self.min_size:
56-
message = self.messages['min_size'].format(**{
57-
'name': value,
58-
'size': size,
59-
'min_size': self.min_size,
60-
})
69+
message = self.messages["min_size"].format(
70+
**{
71+
"name": value,
72+
"size": size,
73+
"min_size": self.min_size,
74+
}
75+
)
6176
raise ValidationError(message)
6277

6378
def __call__(self, value):

0 commit comments

Comments
 (0)