meringue 1.2.0.dev2__tar.gz → 1.2.0.dev4__tar.gz
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- meringue-1.2.0.dev4/AUTHORS +1 -0
- {meringue-1.2.0.dev2 → meringue-1.2.0.dev4}/PKG-INFO +11 -10
- {meringue-1.2.0.dev2 → meringue-1.2.0.dev4}/README.md +5 -5
- {meringue-1.2.0.dev2 → meringue-1.2.0.dev4}/meringue/__init__.py +1 -1
- meringue-1.2.0.dev4/meringue/api/handlers.py +38 -0
- {meringue-1.2.0.dev2 → meringue-1.2.0.dev4}/meringue/api/utils.py +13 -1
- {meringue-1.2.0.dev2 → meringue-1.2.0.dev4}/meringue/conf/default_settings.py +12 -1
- meringue-1.2.0.dev4/meringue/protected/__init__.py +5 -0
- meringue-1.2.0.dev4/meringue/protected/apps.py +8 -0
- meringue-1.2.0.dev4/meringue/protected/fields.py +49 -0
- meringue-1.2.0.dev4/meringue/protected/views.py +57 -0
- {meringue-1.2.0.dev2 → meringue-1.2.0.dev4}/pyproject.toml +58 -45
- meringue-1.2.0.dev2/AUTHORS +0 -1
- meringue-1.2.0.dev2/meringue/api/handlers.py +0 -25
- {meringue-1.2.0.dev2 → meringue-1.2.0.dev4}/.gitignore +0 -0
- {meringue-1.2.0.dev2 → meringue-1.2.0.dev4}/LICENSE +0 -0
- {meringue-1.2.0.dev2 → meringue-1.2.0.dev4}/meringue/api/__init__.py +0 -0
- {meringue-1.2.0.dev2 → meringue-1.2.0.dev4}/meringue/api/apps.py +0 -0
- {meringue-1.2.0.dev2 → meringue-1.2.0.dev4}/meringue/api/docs/__init__.py +0 -0
- {meringue-1.2.0.dev2 → meringue-1.2.0.dev4}/meringue/api/docs/patchers.py +0 -0
- {meringue-1.2.0.dev2 → meringue-1.2.0.dev4}/meringue/api/docs/views.py +0 -0
- {meringue-1.2.0.dev2 → meringue-1.2.0.dev4}/meringue/api/routers.py +0 -0
- {meringue-1.2.0.dev2 → meringue-1.2.0.dev4}/meringue/conf/__init__.py +0 -0
- {meringue-1.2.0.dev2 → meringue-1.2.0.dev4}/meringue/core/__init__.py +0 -0
- {meringue-1.2.0.dev2 → meringue-1.2.0.dev4}/meringue/core/apps.py +0 -0
- {meringue-1.2.0.dev2 → meringue-1.2.0.dev4}/meringue/core/locale/en/LC_MESSAGES/django.po +0 -0
- {meringue-1.2.0.dev2 → meringue-1.2.0.dev4}/meringue/core/locale/ru/LC_MESSAGES/django.po +0 -0
- {meringue-1.2.0.dev2 → meringue-1.2.0.dev4}/meringue/core/models.py +0 -0
- {meringue-1.2.0.dev2 → meringue-1.2.0.dev4}/meringue/core/options.py +0 -0
- {meringue-1.2.0.dev2 → meringue-1.2.0.dev4}/meringue/core/query.py +0 -0
- {meringue-1.2.0.dev2 → meringue-1.2.0.dev4}/meringue/core/templatetags/__init__.py +0 -0
- {meringue-1.2.0.dev2 → meringue-1.2.0.dev4}/meringue/core/templatetags/meringue_base.py +0 -0
- {meringue-1.2.0.dev2 → meringue-1.2.0.dev4}/meringue/core/translation.py +0 -0
- {meringue-1.2.0.dev2 → meringue-1.2.0.dev4}/meringue/core/upload_handlers.py +0 -0
- {meringue-1.2.0.dev2 → meringue-1.2.0.dev4}/meringue/core/utils/__init__.py +0 -0
- {meringue-1.2.0.dev2 → meringue-1.2.0.dev4}/meringue/core/utils/crypt.py +0 -0
- {meringue-1.2.0.dev2 → meringue-1.2.0.dev4}/meringue/core/utils/datetime.py +0 -0
- {meringue-1.2.0.dev2 → meringue-1.2.0.dev4}/meringue/core/utils/frontend.py +0 -0
- {meringue-1.2.0.dev2 → meringue-1.2.0.dev4}/meringue/core/views.py +0 -0
- {meringue-1.2.0.dev2 → meringue-1.2.0.dev4}/meringue/thumbnail/__init__.py +0 -0
- {meringue-1.2.0.dev2 → meringue-1.2.0.dev4}/meringue/thumbnail/actions.py +0 -0
- {meringue-1.2.0.dev2 → meringue-1.2.0.dev4}/meringue/thumbnail/apps.py +0 -0
- {meringue-1.2.0.dev2 → meringue-1.2.0.dev4}/meringue/thumbnail/constants.py +0 -0
- {meringue-1.2.0.dev2 → meringue-1.2.0.dev4}/meringue/thumbnail/drf_fields.py +0 -0
- {meringue-1.2.0.dev2 → meringue-1.2.0.dev4}/meringue/thumbnail/exceptions.py +0 -0
- {meringue-1.2.0.dev2 → meringue-1.2.0.dev4}/meringue/thumbnail/generators.py +0 -0
- {meringue-1.2.0.dev2 → meringue-1.2.0.dev4}/meringue/thumbnail/images.py +0 -0
- {meringue-1.2.0.dev2 → meringue-1.2.0.dev4}/meringue/thumbnail/properties.py +0 -0
- {meringue-1.2.0.dev2 → meringue-1.2.0.dev4}/meringue/thumbnail/shortcuts.py +0 -0
- {meringue-1.2.0.dev2 → meringue-1.2.0.dev4}/meringue/thumbnail/storage.py +0 -0
- {meringue-1.2.0.dev2 → meringue-1.2.0.dev4}/meringue/thumbnail/templatetags/__init__.py +0 -0
- {meringue-1.2.0.dev2 → meringue-1.2.0.dev4}/meringue/thumbnail/templatetags/m_thumbnails.py +0 -0
- {meringue-1.2.0.dev2 → meringue-1.2.0.dev4}/meringue/thumbnail/types.py +0 -0
|
@@ -0,0 +1 @@
|
|
|
1
|
+
Dmitry Dobrynin <dd@tovarisch.engineer>
|
|
@@ -1,13 +1,12 @@
|
|
|
1
|
-
Metadata-Version: 2.
|
|
1
|
+
Metadata-Version: 2.3
|
|
2
2
|
Name: meringue
|
|
3
|
-
Version: 1.2.0.
|
|
3
|
+
Version: 1.2.0.dev4
|
|
4
4
|
Summary: A set of various functionality for a Django based web application.
|
|
5
|
-
Project-URL:
|
|
6
|
-
Project-URL: Documentation, https://dd.github.io/Meringue/
|
|
5
|
+
Project-URL: Documentation, https://dd.github.io/Meringue
|
|
7
6
|
Project-URL: Repository, https://github.com/dd/Meringue
|
|
8
7
|
Project-URL: Changelog, https://github.com/dd/Meringue/blob/master/CHANGELOG.md
|
|
9
8
|
Project-URL: Bug Tracker, https://github.com/dd/Meringue/issues
|
|
10
|
-
Author-email: Dmitry Dobrynin <dd@
|
|
9
|
+
Author-email: Dmitry Dobrynin <dd@tovarisch.engineer>
|
|
11
10
|
License-Expression: LGPL-3.0
|
|
12
11
|
License-File: AUTHORS
|
|
13
12
|
License-File: LICENSE
|
|
@@ -47,6 +46,8 @@ Classifier: Topic :: Internet :: WWW/HTTP :: WSGI
|
|
|
47
46
|
Classifier: Topic :: Software Development :: Libraries
|
|
48
47
|
Requires-Python: >=3.10
|
|
49
48
|
Requires-Dist: django>=1.11.17
|
|
49
|
+
Provides-Extra: cryptodome
|
|
50
|
+
Requires-Dist: pycryptodome==3.20.0; extra == 'cryptodome'
|
|
50
51
|
Provides-Extra: drf
|
|
51
52
|
Requires-Dist: djangorestframework<4,>=3.13; extra == 'drf'
|
|
52
53
|
Provides-Extra: drf-spectacular
|
|
@@ -85,7 +86,7 @@ Description-Content-Type: text/markdown
|
|
|
85
86
|
<img src="https://img.shields.io/github/actions/workflow/status/dd/Meringue/test.yml?logo=github&label=tests" alt="Tests - Running" />
|
|
86
87
|
</a>
|
|
87
88
|
<a href="https://codecov.io/gh/dd/Meringue" >
|
|
88
|
-
<img src="https://codecov.io/gh/dd/Meringue/branch/
|
|
89
|
+
<img src="https://codecov.io/gh/dd/Meringue/branch/master/graph/badge.svg?token=HV1QGD74EK" alt="Tests - Coverage" />
|
|
89
90
|
</a>
|
|
90
91
|
</p>
|
|
91
92
|
<p align="center">
|
|
@@ -109,15 +110,15 @@ Description-Content-Type: text/markdown
|
|
|
109
110
|
</a>
|
|
110
111
|
</p>
|
|
111
112
|
|
|
112
|
-
Full documentation for the project is available at [dd.github.io/Meringue](https://dd.github.io/Meringue/).
|
|
113
|
-
|
|
114
113
|
Package with various functional (such as mixins, form utils, upload handlers and other) for Django Framework.
|
|
115
114
|
|
|
116
115
|
This library is a set of various functionality that I use from project to project.
|
|
117
116
|
|
|
118
117
|
The main task of this package is to clean up this functionality, test it, and also organize the documentation so that colleagues can understand how and what works.
|
|
119
118
|
|
|
120
|
-
However, if someone decides to use this functionality in their project, and even more so to add functionality or change the implementation to a more correct, beautiful or understandable one, I will only be happy, do not worry and feel free to write to me by [mail](mailto:dd@
|
|
119
|
+
However, if someone decides to use this functionality in their project, and even more so to add functionality or change the implementation to a more correct, beautiful or understandable one, I will only be happy, do not worry and feel free to write to me by [mail](mailto:dd@tovarisch.engineer), create an [issue](https://github.com/dd/Meringue/issues) or [pull request](https://github.com/dd/Meringue/pulls) on [github](https://github.com/dd/Meringue).
|
|
120
|
+
|
|
121
|
+
Read more in the [documentation](https://dd.github.io/Meringue/).
|
|
121
122
|
|
|
122
123
|
|
|
123
124
|
## Roadmap
|
|
@@ -133,7 +134,7 @@ Adding new functionality. Can change.
|
|
|
133
134
|
* [ ] Tests
|
|
134
135
|
* [ ] Docs
|
|
135
136
|
* [ ] Functionality similar to that described in the previous paragraph only for video.
|
|
136
|
-
* [
|
|
137
|
+
* [x] Functionality for loading private files available through [nginx internal](http://nginx.org/en/docs/http/ngx_http_core_module.html#internal).
|
|
137
138
|
|
|
138
139
|
|
|
139
140
|
## Contributing
|
|
@@ -28,7 +28,7 @@
|
|
|
28
28
|
<img src="https://img.shields.io/github/actions/workflow/status/dd/Meringue/test.yml?logo=github&label=tests" alt="Tests - Running" />
|
|
29
29
|
</a>
|
|
30
30
|
<a href="https://codecov.io/gh/dd/Meringue" >
|
|
31
|
-
<img src="https://codecov.io/gh/dd/Meringue/branch/
|
|
31
|
+
<img src="https://codecov.io/gh/dd/Meringue/branch/master/graph/badge.svg?token=HV1QGD74EK" alt="Tests - Coverage" />
|
|
32
32
|
</a>
|
|
33
33
|
</p>
|
|
34
34
|
<p align="center">
|
|
@@ -52,15 +52,15 @@
|
|
|
52
52
|
</a>
|
|
53
53
|
</p>
|
|
54
54
|
|
|
55
|
-
Full documentation for the project is available at [dd.github.io/Meringue](https://dd.github.io/Meringue/).
|
|
56
|
-
|
|
57
55
|
Package with various functional (such as mixins, form utils, upload handlers and other) for Django Framework.
|
|
58
56
|
|
|
59
57
|
This library is a set of various functionality that I use from project to project.
|
|
60
58
|
|
|
61
59
|
The main task of this package is to clean up this functionality, test it, and also organize the documentation so that colleagues can understand how and what works.
|
|
62
60
|
|
|
63
|
-
However, if someone decides to use this functionality in their project, and even more so to add functionality or change the implementation to a more correct, beautiful or understandable one, I will only be happy, do not worry and feel free to write to me by [mail](mailto:dd@
|
|
61
|
+
However, if someone decides to use this functionality in their project, and even more so to add functionality or change the implementation to a more correct, beautiful or understandable one, I will only be happy, do not worry and feel free to write to me by [mail](mailto:dd@tovarisch.engineer), create an [issue](https://github.com/dd/Meringue/issues) or [pull request](https://github.com/dd/Meringue/pulls) on [github](https://github.com/dd/Meringue).
|
|
62
|
+
|
|
63
|
+
Read more in the [documentation](https://dd.github.io/Meringue/).
|
|
64
64
|
|
|
65
65
|
|
|
66
66
|
## Roadmap
|
|
@@ -76,7 +76,7 @@ Adding new functionality. Can change.
|
|
|
76
76
|
* [ ] Tests
|
|
77
77
|
* [ ] Docs
|
|
78
78
|
* [ ] Functionality similar to that described in the previous paragraph only for video.
|
|
79
|
-
* [
|
|
79
|
+
* [x] Functionality for loading private files available through [nginx internal](http://nginx.org/en/docs/http/ngx_http_core_module.html#internal).
|
|
80
80
|
|
|
81
81
|
|
|
82
82
|
## Contributing
|
|
@@ -0,0 +1,38 @@
|
|
|
1
|
+
from django.core.exceptions import PermissionDenied
|
|
2
|
+
from django.http.response import Http404
|
|
3
|
+
|
|
4
|
+
from rest_framework import exceptions
|
|
5
|
+
from rest_framework import views
|
|
6
|
+
|
|
7
|
+
from meringue.api.utils import render_error_details
|
|
8
|
+
|
|
9
|
+
try:
|
|
10
|
+
from rest_framework_simplejwt.exceptions import DetailDictMixin
|
|
11
|
+
except ImportError:
|
|
12
|
+
DetailDictMixin = None
|
|
13
|
+
|
|
14
|
+
|
|
15
|
+
def exception_handler(exc, context):
|
|
16
|
+
"""
|
|
17
|
+
Error handler returning message and error code pairs.
|
|
18
|
+
|
|
19
|
+
The handler is a wrapper over the standard handler `rest_framework.views.exception_handler`.
|
|
20
|
+
"""
|
|
21
|
+
|
|
22
|
+
response = views.exception_handler(exc, context)
|
|
23
|
+
|
|
24
|
+
if response is None:
|
|
25
|
+
return response
|
|
26
|
+
|
|
27
|
+
if isinstance(exc, (Http404, PermissionDenied)):
|
|
28
|
+
# django Http404 and PermissionDenied errors are substituted for drf errors,
|
|
29
|
+
# in `rest_framework.views.exception_handler` method.
|
|
30
|
+
response.data = render_error_details(response.data["detail"])
|
|
31
|
+
|
|
32
|
+
elif DetailDictMixin and isinstance(exc, DetailDictMixin):
|
|
33
|
+
response.data = render_error_details(exc)
|
|
34
|
+
|
|
35
|
+
elif isinstance(exc, exceptions.APIException):
|
|
36
|
+
response.data = render_error_details(exc.detail)
|
|
37
|
+
|
|
38
|
+
return response
|
|
@@ -1,5 +1,10 @@
|
|
|
1
1
|
from rest_framework.exceptions import ErrorDetail
|
|
2
2
|
|
|
3
|
+
try:
|
|
4
|
+
from rest_framework_simplejwt.exceptions import DetailDictMixin
|
|
5
|
+
except ImportError:
|
|
6
|
+
DetailDictMixin = None
|
|
7
|
+
|
|
3
8
|
|
|
4
9
|
def render_error_details(error_detail: list | dict | ErrorDetail) -> list | dict:
|
|
5
10
|
"""
|
|
@@ -14,7 +19,14 @@ def render_error_details(error_detail: list | dict | ErrorDetail) -> list | dict
|
|
|
14
19
|
Returns:
|
|
15
20
|
Rendered errors.
|
|
16
21
|
"""
|
|
17
|
-
|
|
22
|
+
|
|
23
|
+
if DetailDictMixin and isinstance(error_detail, DetailDictMixin):
|
|
24
|
+
return {
|
|
25
|
+
"message": error_detail.detail["detail"],
|
|
26
|
+
"code": error_detail.detail["code"],
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
elif isinstance(error_detail, list):
|
|
18
30
|
error_list = [render_error_details(e) for e in error_detail]
|
|
19
31
|
return error_list
|
|
20
32
|
|
|
@@ -42,7 +42,7 @@ Domain for generating absolute links
|
|
|
42
42
|
|
|
43
43
|
# API ##############################################################################################
|
|
44
44
|
|
|
45
|
-
API_ENABLE_ROOT_VIEW: Final[
|
|
45
|
+
API_ENABLE_ROOT_VIEW: Final[bool] = settings.DEBUG
|
|
46
46
|
"""
|
|
47
47
|
Option to enable or disable the root view of the [Router][meringue.api.routers.MeringueRouter]
|
|
48
48
|
"""
|
|
@@ -114,3 +114,14 @@ THUMBNAIL_DEFAULT_FORMAT: Final[str] = "PNG"
|
|
|
114
114
|
"""
|
|
115
115
|
Default thumbnail image format.
|
|
116
116
|
"""
|
|
117
|
+
|
|
118
|
+
|
|
119
|
+
# PROTECTED ########################################################################################
|
|
120
|
+
|
|
121
|
+
PROTECTED_SERVE_WITH_NGINX: Final[bool] = not settings.DEBUG
|
|
122
|
+
"""
|
|
123
|
+
The option implies the distribution of protected files by nginx. Instead of serving the file in
|
|
124
|
+
response.
|
|
125
|
+
|
|
126
|
+
The view [protected_file_view][meringue.protected.views.protected_file_view] adds the X-Accel-Redirect header with a link to the file.
|
|
127
|
+
"""
|
|
@@ -0,0 +1,49 @@
|
|
|
1
|
+
from django.contrib.contenttypes.models import ContentType
|
|
2
|
+
from django.db.models.fields.files import FileField
|
|
3
|
+
from django.db.models.fields.files import FieldFile
|
|
4
|
+
from django.db.models.fields.files import ImageField
|
|
5
|
+
from django.db.models.fields.files import ImageFieldFile
|
|
6
|
+
from django.urls import reverse
|
|
7
|
+
|
|
8
|
+
|
|
9
|
+
class ProtectedFileMixin:
|
|
10
|
+
@property
|
|
11
|
+
def url(self):
|
|
12
|
+
self._require_file()
|
|
13
|
+
result_url = reverse(
|
|
14
|
+
"meringue-protected-file",
|
|
15
|
+
kwargs={
|
|
16
|
+
"contenttype_id": ContentType.objects.get_for_model(self.instance.__class__).id,
|
|
17
|
+
"field": self.field.name,
|
|
18
|
+
"pk": self.instance.pk,
|
|
19
|
+
},
|
|
20
|
+
)
|
|
21
|
+
return result_url
|
|
22
|
+
|
|
23
|
+
@property
|
|
24
|
+
def original_url(self):
|
|
25
|
+
self._require_file()
|
|
26
|
+
return self.storage.url(self.name)
|
|
27
|
+
|
|
28
|
+
|
|
29
|
+
class ProtectedFieldFile(ProtectedFileMixin, FieldFile):
|
|
30
|
+
pass
|
|
31
|
+
|
|
32
|
+
|
|
33
|
+
class ProtectedFileField(FileField):
|
|
34
|
+
attr_class = ProtectedFieldFile
|
|
35
|
+
|
|
36
|
+
def __init__(self, verbose_name=None, name=None, upload_to="protected", storage=None, **kwargs):
|
|
37
|
+
super().__init__(verbose_name, name, upload_to, storage, **kwargs)
|
|
38
|
+
|
|
39
|
+
|
|
40
|
+
class ProtectedImageFieldFile(ProtectedFileMixin, ImageFieldFile):
|
|
41
|
+
pass
|
|
42
|
+
|
|
43
|
+
|
|
44
|
+
class ProtectedImageField(ImageField):
|
|
45
|
+
attr_class = ProtectedImageFieldFile
|
|
46
|
+
|
|
47
|
+
def __init__(self, verbose_name=None, name=None, width_field=None, height_field=None, **kwargs):
|
|
48
|
+
kwargs.setdefault("upload_to", "protected")
|
|
49
|
+
super().__init__(verbose_name, name, width_field, height_field, **kwargs)
|
|
@@ -0,0 +1,57 @@
|
|
|
1
|
+
import mimetypes
|
|
2
|
+
from pathlib import Path
|
|
3
|
+
from urllib.parse import quote
|
|
4
|
+
from urllib.parse import urljoin
|
|
5
|
+
|
|
6
|
+
from django.conf import settings
|
|
7
|
+
from django.contrib.contenttypes.models import ContentType
|
|
8
|
+
from django.core.exceptions import PermissionDenied
|
|
9
|
+
from django.http import FileResponse
|
|
10
|
+
from django.http import Http404
|
|
11
|
+
from django.http import HttpResponse
|
|
12
|
+
|
|
13
|
+
from meringue.conf import m_settings
|
|
14
|
+
from meringue.protected.fields import ProtectedFieldFile
|
|
15
|
+
from meringue.protected.fields import ProtectedImageFieldFile
|
|
16
|
+
|
|
17
|
+
|
|
18
|
+
def protected_file_view(request, contenttype_id, field, pk):
|
|
19
|
+
"""
|
|
20
|
+
В продакшен моде вьха редиректит на урл файла, где нжинкс отдаёт этот файл
|
|
21
|
+
Защита работает за счёт параметра internal
|
|
22
|
+
https://nginx.org/en/docs/http/ngx_http_core_module.html#internal
|
|
23
|
+
|
|
24
|
+
```conf
|
|
25
|
+
location /media/protected/ {
|
|
26
|
+
internal;
|
|
27
|
+
alias /home/rpl/rpl-2023-back/public/media/protected/;
|
|
28
|
+
}
|
|
29
|
+
```
|
|
30
|
+
"""
|
|
31
|
+
|
|
32
|
+
contenttype = ContentType.objects.get(id=contenttype_id)
|
|
33
|
+
|
|
34
|
+
if not request.user.has_perm(f"{contenttype.app_label}.view_{contenttype.model}"):
|
|
35
|
+
raise PermissionDenied()
|
|
36
|
+
|
|
37
|
+
model = contenttype.model_class().objects.get(pk=pk)
|
|
38
|
+
file = getattr(model, field)
|
|
39
|
+
|
|
40
|
+
if not file:
|
|
41
|
+
raise Http404()
|
|
42
|
+
|
|
43
|
+
if m_settings.PROTECTED_SERVE_WITH_NGINX:
|
|
44
|
+
file_name = Path(file.name).name
|
|
45
|
+
response = HttpResponse()
|
|
46
|
+
response["Content-Type"] = mimetypes.guess_type(file.path)[0]
|
|
47
|
+
response["Content-Disposition"] = f"inline; filename={quote(file_name)}"
|
|
48
|
+
|
|
49
|
+
if isinstance(file, ProtectedFieldFile | ProtectedImageFieldFile):
|
|
50
|
+
redirect_url = file.original_url
|
|
51
|
+
else:
|
|
52
|
+
redirect_url = file.url
|
|
53
|
+
|
|
54
|
+
response["X-Accel-Redirect"] = redirect_url
|
|
55
|
+
return response
|
|
56
|
+
|
|
57
|
+
return FileResponse(open(file.path, "rb"))
|
|
@@ -9,7 +9,7 @@ readme = "README.md"
|
|
|
9
9
|
requires-python = ">=3.10"
|
|
10
10
|
license = "LGPL-3.0"
|
|
11
11
|
authors = [
|
|
12
|
-
{ name = "Dmitry Dobrynin", email = "dd@
|
|
12
|
+
{ name = "Dmitry Dobrynin", email = "dd@tovarisch.engineer" },
|
|
13
13
|
]
|
|
14
14
|
keywords = ["django", "utils"]
|
|
15
15
|
classifiers = [
|
|
@@ -57,10 +57,10 @@ dynamic = ["version"]
|
|
|
57
57
|
modeltranslation = ["django-modeltranslation>=0.17,<0.19"]
|
|
58
58
|
drf = ["djangorestframework>=3.13,<4"]
|
|
59
59
|
drf-spectacular = ["drf-spectacular>=0.26.3,<1"]
|
|
60
|
+
cryptodome = ["pycryptodome==3.20.0"]
|
|
60
61
|
|
|
61
62
|
[project.urls]
|
|
62
|
-
"
|
|
63
|
-
"Documentation" = "https://dd.github.io/Meringue/"
|
|
63
|
+
"Documentation" = "https://dd.github.io/Meringue"
|
|
64
64
|
"Repository" = "https://github.com/dd/Meringue"
|
|
65
65
|
"Changelog" = "https://github.com/dd/Meringue/blob/master/CHANGELOG.md"
|
|
66
66
|
"Bug Tracker" = "https://github.com/dd/Meringue/issues"
|
|
@@ -83,21 +83,21 @@ exclude = [
|
|
|
83
83
|
|
|
84
84
|
[tool.hatch.envs.default]
|
|
85
85
|
description = "Dev environment"
|
|
86
|
-
python = "3.
|
|
86
|
+
python = "3.12"
|
|
87
87
|
dependencies = [
|
|
88
|
-
"pre-commit==3.
|
|
89
|
-
"ipython==8.
|
|
90
|
-
"django==4.2",
|
|
91
|
-
"pytz==2023.3",
|
|
88
|
+
"pre-commit==3.5.0",
|
|
89
|
+
"ipython==8.17.1",
|
|
90
|
+
"django==4.2.7",
|
|
91
|
+
"pytz==2023.3.post1",
|
|
92
92
|
"django-modeltranslation==0.18.11",
|
|
93
|
-
"pycryptodome==3.
|
|
93
|
+
"pycryptodome==3.20.0",
|
|
94
94
|
"djangorestframework==3.14.0",
|
|
95
|
-
"drf-spectacular==0.26.
|
|
96
|
-
"Pillow==10.
|
|
95
|
+
"drf-spectacular==0.26.5",
|
|
96
|
+
"Pillow==10.1.0",
|
|
97
97
|
]
|
|
98
98
|
[tool.hatch.envs.default.env-vars]
|
|
99
|
-
DJANGO_SETTINGS_MODULE =
|
|
100
|
-
PYTHONPATH =
|
|
99
|
+
DJANGO_SETTINGS_MODULE = "test_project.settings"
|
|
100
|
+
PYTHONPATH = "."
|
|
101
101
|
[tool.hatch.envs.default.scripts]
|
|
102
102
|
precommit_install = "pre-commit install {args}"
|
|
103
103
|
precommit_uninstall = "pre-commit uninstall {args}"
|
|
@@ -114,11 +114,12 @@ init = [
|
|
|
114
114
|
"precommit_install",
|
|
115
115
|
]
|
|
116
116
|
remove = [
|
|
117
|
+
"git config --local --remove-section gitflow.branch",
|
|
118
|
+
"git config --local --remove-section gitflow.prefix",
|
|
119
|
+
"git config --local --remove-section gitflow.path",
|
|
117
120
|
"precommit_uninstall",
|
|
118
121
|
]
|
|
119
|
-
makemessages =
|
|
120
|
-
"cd meringue/core && django-admin makemessages -l en -l ru --no-obsolete {args}",
|
|
121
|
-
]
|
|
122
|
+
makemessages = "cd meringue/core && django-admin makemessages -l en -l ru --no-obsolete {args}"
|
|
122
123
|
compilemessages = "cd meringue && django-admin compilemessages -l en -l ru {args}"
|
|
123
124
|
|
|
124
125
|
[tool.hatch.envs.lint]
|
|
@@ -126,8 +127,8 @@ description = "Lint environment"
|
|
|
126
127
|
detached = true
|
|
127
128
|
python = "3.11"
|
|
128
129
|
dependencies = [
|
|
129
|
-
"ruff==0.
|
|
130
|
-
"black==
|
|
130
|
+
"ruff==0.3.4",
|
|
131
|
+
"black==24.3.0",
|
|
131
132
|
]
|
|
132
133
|
[tool.hatch.envs.lint.scripts]
|
|
133
134
|
check = [
|
|
@@ -144,20 +145,22 @@ description = "Tests environment"
|
|
|
144
145
|
detached = true
|
|
145
146
|
python = "3.11"
|
|
146
147
|
dependencies = [
|
|
147
|
-
"pytest==7.4.
|
|
148
|
+
"pytest==7.4.2",
|
|
148
149
|
"pytest-django==4.5.2",
|
|
149
150
|
"pytest-cov==4.1.0",
|
|
150
|
-
"Faker==19.
|
|
151
|
+
"Faker==19.6.1",
|
|
151
152
|
"django==4.2",
|
|
152
|
-
"pytz==2023.3",
|
|
153
|
+
"pytz==2023.3.post1",
|
|
153
154
|
"django-modeltranslation==0.18.11",
|
|
154
|
-
"pycryptodome==3.
|
|
155
|
+
"pycryptodome==3.20.0",
|
|
155
156
|
"djangorestframework==3.14.0",
|
|
157
|
+
"djangorestframework-simplejwt==5.3.1",
|
|
156
158
|
"drf-spectacular==0.26.4",
|
|
159
|
+
"pillow==10.3.0",
|
|
157
160
|
]
|
|
158
161
|
[tool.hatch.envs.test.env-vars]
|
|
159
|
-
DJANGO_SETTINGS_MODULE =
|
|
160
|
-
PYTHONPATH =
|
|
162
|
+
DJANGO_SETTINGS_MODULE = "test_project.settings"
|
|
163
|
+
PYTHONPATH = "."
|
|
161
164
|
[tool.hatch.envs.test.scripts]
|
|
162
165
|
check = "pytest {args:--cov=meringue --cov-report term-missing}"
|
|
163
166
|
makemigrations = "django-admin makemigrations {args}"
|
|
@@ -166,56 +169,66 @@ makemigrations = "django-admin makemigrations {args}"
|
|
|
166
169
|
description = "Test matrix environment"
|
|
167
170
|
detached = true
|
|
168
171
|
dependencies = [
|
|
169
|
-
"pytest==7.4.
|
|
172
|
+
"pytest==7.4.2",
|
|
170
173
|
"pytest-django==4.5.2",
|
|
171
174
|
"pytest-cov==4.1.0", # for ci tests with cover
|
|
172
|
-
"Faker==19.
|
|
173
|
-
"pytz==2023.3",
|
|
174
|
-
"pycryptodome==3.
|
|
175
|
+
"Faker==19.6.1",
|
|
176
|
+
"pytz==2023.3.post1",
|
|
177
|
+
"pycryptodome==3.20.0",
|
|
175
178
|
"drf-spectacular==0.26.4",
|
|
179
|
+
"pillow==10.3.0",
|
|
176
180
|
]
|
|
177
181
|
[tool.hatch.envs.mtest.overrides]
|
|
178
182
|
matrix.django.dependencies = [
|
|
179
183
|
{ value = "django~={matrix:django}" },
|
|
180
184
|
{ value = "django-modeltranslation=={matrix:modeltranslation}" },
|
|
181
185
|
{ value = "djangorestframework=={matrix:djangorestframework}" },
|
|
186
|
+
{ value = "djangorestframework-simplejwt=={matrix:simplejwt}" },
|
|
182
187
|
]
|
|
183
188
|
[tool.hatch.envs.mtest.env-vars]
|
|
184
|
-
DJANGO_SETTINGS_MODULE =
|
|
185
|
-
PYTHONPATH =
|
|
189
|
+
DJANGO_SETTINGS_MODULE = "test_project.settings"
|
|
190
|
+
PYTHONPATH = "."
|
|
186
191
|
[tool.hatch.envs.mtest.scripts]
|
|
187
192
|
check = "pytest {args:-q}"
|
|
188
193
|
[[tool.hatch.envs.mtest.matrix]]
|
|
189
194
|
python = ["3.10", "3.11"]
|
|
190
195
|
django = ["2.0"]
|
|
191
|
-
modeltranslation = ["0.17.
|
|
192
|
-
djangorestframework = ["3.13.
|
|
196
|
+
modeltranslation = ["0.17.0"]
|
|
197
|
+
djangorestframework = ["3.13.0"]
|
|
198
|
+
simplejwt = ["5.2.0"]
|
|
199
|
+
[[tool.hatch.envs.mtest.matrix]]
|
|
200
|
+
python = ["3.10", "3.11"]
|
|
201
|
+
django = ["3.0"]
|
|
202
|
+
modeltranslation = ["0.17.0"]
|
|
203
|
+
djangorestframework = ["3.13.0", "3.14.0", "3.15.0"]
|
|
204
|
+
simplejwt = ["5.2.0", "5.3.0"]
|
|
193
205
|
[[tool.hatch.envs.mtest.matrix]]
|
|
194
206
|
python = ["3.10", "3.11"]
|
|
195
|
-
django = ["
|
|
196
|
-
modeltranslation = ["0.
|
|
207
|
+
django = ["4.0"]
|
|
208
|
+
modeltranslation = ["0.17.0"]
|
|
197
209
|
djangorestframework = ["3.14.0"]
|
|
210
|
+
simplejwt = ["5.2.0", "5.3.0"]
|
|
198
211
|
|
|
199
212
|
[tool.hatch.envs.docs]
|
|
200
213
|
description = "Docs environment"
|
|
201
214
|
detached = true
|
|
202
215
|
python = "3.11"
|
|
203
216
|
dependencies = [
|
|
204
|
-
"mkdocs[i18n]==1.5.
|
|
205
|
-
"mkdocs-literate-nav==0.6.
|
|
206
|
-
"mkdocs-material==9.
|
|
207
|
-
"mkdocs-git-revision-date-localized-plugin==1.2.
|
|
208
|
-
"mkdocs-git-authors-plugin==0.
|
|
209
|
-
"mkdocstrings[python]==0.
|
|
210
|
-
"black==
|
|
211
|
-
"mkdocs-minify-plugin==0.
|
|
217
|
+
"mkdocs[i18n]==1.5.3",
|
|
218
|
+
"mkdocs-literate-nav==0.6.1",
|
|
219
|
+
"mkdocs-material==9.5.16",
|
|
220
|
+
"mkdocs-git-revision-date-localized-plugin==1.2.4",
|
|
221
|
+
"mkdocs-git-authors-plugin==0.8.0",
|
|
222
|
+
"mkdocstrings[python]==0.24.1",
|
|
223
|
+
"black==24.3.0",
|
|
224
|
+
"mkdocs-minify-plugin==0.8.0",
|
|
212
225
|
"mkdocs-gen-files==0.5.0",
|
|
213
|
-
"Pygments==2.
|
|
226
|
+
"Pygments==2.17.2",
|
|
214
227
|
"mike==1.1.2",
|
|
215
|
-
"linkchecker==10.
|
|
228
|
+
"linkchecker==10.4.0",
|
|
216
229
|
]
|
|
217
230
|
[tool.hatch.envs.docs.env-vars]
|
|
218
|
-
MERINGUE_MKDOCS_ENABLE_MINIFY =
|
|
231
|
+
MERINGUE_MKDOCS_ENABLE_MINIFY = "false"
|
|
219
232
|
MKDOCS_CONFIG = "mkdocs.yml"
|
|
220
233
|
[tool.hatch.envs.docs.scripts]
|
|
221
234
|
build = "mkdocs build --config-file {env:MKDOCS_CONFIG} --clean --strict {args}"
|
meringue-1.2.0.dev2/AUTHORS
DELETED
|
@@ -1 +0,0 @@
|
|
|
1
|
-
Dmitry Dobrynin <dd@manin.space>
|
|
@@ -1,25 +0,0 @@
|
|
|
1
|
-
from rest_framework import exceptions
|
|
2
|
-
from rest_framework import views
|
|
3
|
-
|
|
4
|
-
from meringue.api.utils import render_error_details
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
def exception_handler(exc, context):
|
|
8
|
-
"""
|
|
9
|
-
Error handler returning message and error code pairs.
|
|
10
|
-
|
|
11
|
-
The handler is a wrapper over the standard handler `rest_framework.views.exception_handler`.
|
|
12
|
-
"""
|
|
13
|
-
response = views.exception_handler(exc, context)
|
|
14
|
-
|
|
15
|
-
if response is None:
|
|
16
|
-
return response
|
|
17
|
-
|
|
18
|
-
if isinstance(exc, exceptions.APIException):
|
|
19
|
-
if isinstance(exc.detail, list):
|
|
20
|
-
response.data = [render_error_details(e) for e in exc.detail]
|
|
21
|
-
|
|
22
|
-
elif isinstance(exc.detail, dict):
|
|
23
|
-
response.data = {f: render_error_details(e) for f, e in exc.detail.items()}
|
|
24
|
-
|
|
25
|
-
return response
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|