Skip to content

Commit 4a1ea93

Browse files
authored
build: update build systems and lint
1 parent c8d17e2 commit 4a1ea93

36 files changed

+1254
-851
lines changed

.github/workflows/lint.yml

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
name: Lint
2+
3+
on:
4+
pull_request:
5+
branches:
6+
- main
7+
8+
jobs:
9+
lint:
10+
runs-on: ubuntu-latest
11+
steps:
12+
- uses: actions/checkout@v3
13+
- uses: psf/black@stable

.github/workflows/test.yml

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -50,9 +50,8 @@ jobs:
5050
- name: Install Dependencies
5151
run: |
5252
python -m pip install --upgrade pip
53-
pip install -r requirements.txt
53+
pip install .[test]
5454
pip install psycopg2
55-
pip install playwright
5655
pip install django==${{ matrix.django-version }}
5756
5857
- name: Ensure browsers are installed

.gitignore

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,3 +5,4 @@ __pycache__
55
media/
66
build
77
*.egg-info
8+
dist

.pre-commit-config.yaml

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
repos:
2+
- repo: https://github.com/psf/black-pre-commit-mirror
3+
rev: 24.3.0
4+
hooks:
5+
- id: black
6+
7+
- repo: https://github.com/PyCQA/isort
8+
rev: 5.13.2
9+
hooks:
10+
- id: isort

image_uploader_widget/admin.py

Lines changed: 18 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,9 @@
11
from django import forms
22
from django.contrib import admin
33

4+
45
class ImageUploaderInline(admin.StackedInline):
5-
template = 'admin/edit_inline/image_uploader.html'
6+
template = "admin/edit_inline/image_uploader.html"
67
extra = 0
78
add_image_text = ""
89
drop_text = ""
@@ -17,19 +18,19 @@ def get_add_image_text(self):
1718

1819
def get_drop_text(self):
1920
return self.drop_text
20-
21+
2122
def get_empty_text(self):
2223
return self.empty_text
2324

2425
def get_empty_icon(self):
2526
return self.empty_icon
26-
27+
2728
def get_drop_icon(self):
2829
return self.drop_icon
2930

3031
def get_add_icon(self):
3132
return self.add_icon
32-
33+
3334
def get_accept(self):
3435
return self.accept
3536

@@ -47,26 +48,29 @@ def get_formset(self, request, obj=None, **kwargs):
4748
@property
4849
def media(self):
4950
return forms.Media(
50-
js = [
51-
'admin/js/image-uploader-modal.js',
52-
'admin/js/image-uploader-inline.js',
51+
js=[
52+
"admin/js/image-uploader-modal.js",
53+
"admin/js/image-uploader-inline.js",
5354
],
54-
css = {
55-
'screen': [
56-
'admin/css/image-uploader-inline.css',
55+
css={
56+
"screen": [
57+
"admin/css/image-uploader-inline.css",
5758
]
58-
}
59+
},
5960
)
6061

62+
6163
class OrderedImageUploaderInline(ImageUploaderInline):
62-
template = 'admin/edit_inline/ordered_image_uploader.html'
64+
template = "admin/edit_inline/ordered_image_uploader.html"
6365
order_field = "order"
6466

6567
def get_order_field(self, request):
6668
return self.order_field
67-
69+
6870
def get_formset(self, request, obj=None, **kwargs):
69-
item = super(OrderedImageUploaderInline, self).get_formset(request, obj, **kwargs)
71+
item = super(OrderedImageUploaderInline, self).get_formset(
72+
request, obj, **kwargs
73+
)
7074
item.order_field = self.get_order_field(request)
7175
return item
7276

image_uploader_widget/postgres/fields.py

Lines changed: 18 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -1,29 +1,32 @@
1+
import datetime
12
import os
23
import pathlib
3-
import datetime
4-
from typing import Optional
54
import posixpath
5+
from typing import Optional
6+
7+
from django.contrib.postgres.fields import ArrayField
68
from django.core.exceptions import SuspiciousFileOperation
9+
from django.core.files.storage import Storage, default_storage
710
from django.db.models import ImageField
8-
from django.contrib.postgres.fields import ArrayField
911
from django.db.models.fields.files import FieldFile
10-
from django.core.files.storage import default_storage, Storage
12+
1113
from .forms import ImageListFormField
1214

15+
1316
def validate_file_name(name, allow_relative_path=False):
1417
# TODO: when drop support for django 3.2, remove this function
1518
# and import from django
16-
19+
1720
# Remove potentially dangerous names
18-
if os.path.basename(name) in {'', '.', '..'}:
21+
if os.path.basename(name) in {"", ".", ".."}:
1922
raise SuspiciousFileOperation("Could not derive file name from '%s'" % name)
2023

2124
if allow_relative_path:
2225
# Use PurePosixPath() because this branch is checked only in
2326
# FileField.generate_filename() where all file paths are expected to be
2427
# Unix style (with forward slashes).
2528
path = pathlib.PurePosixPath(name)
26-
if path.is_absolute() or '..' in path.parts:
29+
if path.is_absolute() or ".." in path.parts:
2730
raise SuspiciousFileOperation(
2831
"Detected path traversal attempt in '%s'" % name
2932
)
@@ -40,12 +43,14 @@ def __init__(
4043
max_length: int = 150,
4144
storage: Optional[Storage] = None,
4245
upload_to: str = "",
43-
**kwargs
46+
**kwargs,
4447
):
4548
self.max_length = max_length or 150
4649
self.storage = storage or default_storage
4750
self.upload_to = upload_to or ""
48-
kwargs['base_field'] = ImageField(max_length=self.max_length, upload_to=upload_to)
51+
kwargs["base_field"] = ImageField(
52+
max_length=self.max_length, upload_to=upload_to
53+
)
4954
super().__init__(
5055
*args,
5156
**kwargs,
@@ -63,7 +68,7 @@ def deconstruct(self):
6368
}
6469
)
6570
return name, path, args, kwargs
66-
71+
6772
def generate_filename(self, instance, filename):
6873
"""
6974
Apply (if callable) or prepend (if a string) upload_to to the filename,
@@ -78,11 +83,11 @@ def generate_filename(self, instance, filename):
7883
filename = posixpath.join(dirname, filename)
7984
filename = validate_file_name(filename, allow_relative_path=True)
8085
return self.storage.generate_filename(filename)
81-
86+
8287
def _get_file(self, instance, file):
8388
if isinstance(file, str):
8489
return FieldFile(instance, self, file)
85-
90+
8691
field_file = FieldFile(instance, self, file.name)
8792
field_file.file = file
8893
field_file._committed = False
@@ -97,7 +102,7 @@ def pre_save(self, model_instance, add):
97102
file.save(file.name, file.file, save=False)
98103

99104
return value
100-
105+
101106
def save_form_data(self, instance, data):
102107
if not data:
103108
data = []

image_uploader_widget/postgres/forms.py

Lines changed: 8 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1,18 +1,21 @@
11
from itertools import chain
2+
23
from django import forms
3-
from django.core.exceptions import ValidationError
44
from django.contrib.postgres.utils import prefix_validation_error
5+
from django.core.exceptions import ValidationError
56
from django.utils.translation import gettext_lazy as _
7+
68
from .widget import ImageUploaderArrayWidget
79

10+
811
class ImageListFormField(forms.Field):
912
default_error_messages = {
1013
"item_invalid": _("Item %(name)s in the array did not validate:"),
1114
}
12-
15+
1316
def __init__(self, **kwargs):
14-
kwargs.pop('base_field')
15-
self.max_length = kwargs.pop('max_length') or 150
17+
kwargs.pop("base_field")
18+
self.max_length = kwargs.pop("max_length") or 150
1619

1720
self.required = False
1821
self.base_field = forms.ImageField(max_length=self.max_length)
@@ -45,7 +48,7 @@ def clean(self, value):
4548
error,
4649
self.error_messages["item_invalid"],
4750
code="item_invalid",
48-
params={ "name": file_name },
51+
params={"name": file_name},
4952
)
5053
)
5154
cleaned_data.append(None)
@@ -66,4 +69,3 @@ def has_changed(self, initial, data):
6669
if initial in self.empty_values and data in self.empty_values:
6770
return False
6871
return super().has_changed(initial, data)
69-
Lines changed: 31 additions & 35 deletions
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,11 @@
11
import json
22
from typing import Any, List
3+
34
from django import forms
45
from django.contrib.postgres.forms import SplitArrayWidget
5-
from django.core.files.uploadedfile import InMemoryUploadedFile
66
from django.core.files.storage import default_storage
7+
from django.core.files.uploadedfile import InMemoryUploadedFile
8+
79

810
class ImageUploaderArrayWidget(SplitArrayWidget):
911
template_name = "postgres/widgets/image_array.html"
@@ -14,23 +16,18 @@ class ImageUploaderArrayWidget(SplitArrayWidget):
1416

1517
def get_drop_text(self):
1618
return self.drop_text
17-
19+
1820
def get_empty_text(self):
1921
return self.empty_text
2022

2123
def get_empty_icon(self):
2224
return self.empty_icon
23-
25+
2426
def get_drop_icon(self):
2527
return self.drop_icon
2628

2729
def __init__(
28-
self,
29-
drop_text = "",
30-
empty_text = "",
31-
empty_icon = "",
32-
drop_icon = "",
33-
**kwargs
30+
self, drop_text="", empty_text="", empty_icon="", drop_icon="", **kwargs
3431
):
3532
self.drop_text = drop_text
3633
self.empty_text = empty_text
@@ -48,48 +45,49 @@ def _get_image(self, path):
4845
def get_files_from_value(self, value: Any) -> List[str]:
4946
return [self._get_image(name) for name in value]
5047

51-
def get_context(self, name, value, attrs = None):
48+
def get_context(self, name, value, attrs=None):
5249
value_raw = value or []
5350
value = list(filter(None, self.get_files_from_value([*value_raw])))
5451
self.size = len(value)
55-
52+
5653
context = super(ImageUploaderArrayWidget, self).get_context(name, value, attrs)
5754
if not context:
5855
context = {}
5956

6057
for i in range(0, len(value)):
61-
context['widget']['subwidgets'][i]['value'] = value[i]
62-
context['widget']['subwidgets'][i]['value_raw'] = value_raw[i]
63-
58+
context["widget"]["subwidgets"][i]["value"] = value[i]
59+
context["widget"]["subwidgets"][i]["value_raw"] = value_raw[i]
6460

6561
return {
6662
**context,
67-
'inline_admin_formset': {
68-
'inline_formset_data': json.dumps({
69-
'name': context['widget']['name'],
70-
'options': {
71-
'prefix': context['widget']['name'],
63+
"inline_admin_formset": {
64+
"inline_formset_data": json.dumps(
65+
{
66+
"name": context["widget"]["name"],
67+
"options": {
68+
"prefix": context["widget"]["name"],
69+
},
7270
}
73-
}),
74-
'formset': {
75-
'prefix': context['widget']['name'],
71+
),
72+
"formset": {
73+
"prefix": context["widget"]["name"],
7674
},
7775
},
7876
"custom": {
7977
"drop_text": self.get_drop_text(),
8078
"empty_text": self.get_empty_text(),
8179
"empty_icon": self.get_empty_icon(),
8280
"drop_icon": self.get_drop_icon(),
83-
}
81+
},
8482
}
85-
83+
8684
def value_from_datadict(self, data, files, name):
87-
total_forms = int(data.get('images-TOTAL_FORMS'))
85+
total_forms = int(data.get("images-TOTAL_FORMS"))
8886
result = []
8987
for i in range(0, total_forms):
90-
image_file = files.get(f'images-{i}-image')
91-
image_raw = data.get(f'images-{i}-RAW')
92-
image_delete = data.get(f'images-{i}-DELETE')
88+
image_file = files.get(f"images-{i}-image")
89+
image_raw = data.get(f"images-{i}-RAW")
90+
image_delete = data.get(f"images-{i}-DELETE")
9391
if image_delete:
9492
continue
9593

@@ -103,17 +101,15 @@ def value_from_datadict(self, data, files, name):
103101
@property
104102
def needs_multipart_form(self):
105103
return True
106-
104+
107105
@property
108106
def media(self):
109107
return forms.Media(
110108
js=(
111-
'admin/js/image-uploader-modal.js',
112-
'admin/js/image-uploader-inline.js',
109+
"admin/js/image-uploader-modal.js",
110+
"admin/js/image-uploader-inline.js",
113111
),
114112
css={
115-
'screen': (
116-
'admin/css/image-uploader-inline.css',
117-
),
113+
"screen": ("admin/css/image-uploader-inline.css",),
118114
},
119-
)
115+
)

0 commit comments

Comments
 (0)