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.
Files changed (53) hide show
  1. meringue-1.2.0.dev4/AUTHORS +1 -0
  2. {meringue-1.2.0.dev2 → meringue-1.2.0.dev4}/PKG-INFO +11 -10
  3. {meringue-1.2.0.dev2 → meringue-1.2.0.dev4}/README.md +5 -5
  4. {meringue-1.2.0.dev2 → meringue-1.2.0.dev4}/meringue/__init__.py +1 -1
  5. meringue-1.2.0.dev4/meringue/api/handlers.py +38 -0
  6. {meringue-1.2.0.dev2 → meringue-1.2.0.dev4}/meringue/api/utils.py +13 -1
  7. {meringue-1.2.0.dev2 → meringue-1.2.0.dev4}/meringue/conf/default_settings.py +12 -1
  8. meringue-1.2.0.dev4/meringue/protected/__init__.py +5 -0
  9. meringue-1.2.0.dev4/meringue/protected/apps.py +8 -0
  10. meringue-1.2.0.dev4/meringue/protected/fields.py +49 -0
  11. meringue-1.2.0.dev4/meringue/protected/views.py +57 -0
  12. {meringue-1.2.0.dev2 → meringue-1.2.0.dev4}/pyproject.toml +58 -45
  13. meringue-1.2.0.dev2/AUTHORS +0 -1
  14. meringue-1.2.0.dev2/meringue/api/handlers.py +0 -25
  15. {meringue-1.2.0.dev2 → meringue-1.2.0.dev4}/.gitignore +0 -0
  16. {meringue-1.2.0.dev2 → meringue-1.2.0.dev4}/LICENSE +0 -0
  17. {meringue-1.2.0.dev2 → meringue-1.2.0.dev4}/meringue/api/__init__.py +0 -0
  18. {meringue-1.2.0.dev2 → meringue-1.2.0.dev4}/meringue/api/apps.py +0 -0
  19. {meringue-1.2.0.dev2 → meringue-1.2.0.dev4}/meringue/api/docs/__init__.py +0 -0
  20. {meringue-1.2.0.dev2 → meringue-1.2.0.dev4}/meringue/api/docs/patchers.py +0 -0
  21. {meringue-1.2.0.dev2 → meringue-1.2.0.dev4}/meringue/api/docs/views.py +0 -0
  22. {meringue-1.2.0.dev2 → meringue-1.2.0.dev4}/meringue/api/routers.py +0 -0
  23. {meringue-1.2.0.dev2 → meringue-1.2.0.dev4}/meringue/conf/__init__.py +0 -0
  24. {meringue-1.2.0.dev2 → meringue-1.2.0.dev4}/meringue/core/__init__.py +0 -0
  25. {meringue-1.2.0.dev2 → meringue-1.2.0.dev4}/meringue/core/apps.py +0 -0
  26. {meringue-1.2.0.dev2 → meringue-1.2.0.dev4}/meringue/core/locale/en/LC_MESSAGES/django.po +0 -0
  27. {meringue-1.2.0.dev2 → meringue-1.2.0.dev4}/meringue/core/locale/ru/LC_MESSAGES/django.po +0 -0
  28. {meringue-1.2.0.dev2 → meringue-1.2.0.dev4}/meringue/core/models.py +0 -0
  29. {meringue-1.2.0.dev2 → meringue-1.2.0.dev4}/meringue/core/options.py +0 -0
  30. {meringue-1.2.0.dev2 → meringue-1.2.0.dev4}/meringue/core/query.py +0 -0
  31. {meringue-1.2.0.dev2 → meringue-1.2.0.dev4}/meringue/core/templatetags/__init__.py +0 -0
  32. {meringue-1.2.0.dev2 → meringue-1.2.0.dev4}/meringue/core/templatetags/meringue_base.py +0 -0
  33. {meringue-1.2.0.dev2 → meringue-1.2.0.dev4}/meringue/core/translation.py +0 -0
  34. {meringue-1.2.0.dev2 → meringue-1.2.0.dev4}/meringue/core/upload_handlers.py +0 -0
  35. {meringue-1.2.0.dev2 → meringue-1.2.0.dev4}/meringue/core/utils/__init__.py +0 -0
  36. {meringue-1.2.0.dev2 → meringue-1.2.0.dev4}/meringue/core/utils/crypt.py +0 -0
  37. {meringue-1.2.0.dev2 → meringue-1.2.0.dev4}/meringue/core/utils/datetime.py +0 -0
  38. {meringue-1.2.0.dev2 → meringue-1.2.0.dev4}/meringue/core/utils/frontend.py +0 -0
  39. {meringue-1.2.0.dev2 → meringue-1.2.0.dev4}/meringue/core/views.py +0 -0
  40. {meringue-1.2.0.dev2 → meringue-1.2.0.dev4}/meringue/thumbnail/__init__.py +0 -0
  41. {meringue-1.2.0.dev2 → meringue-1.2.0.dev4}/meringue/thumbnail/actions.py +0 -0
  42. {meringue-1.2.0.dev2 → meringue-1.2.0.dev4}/meringue/thumbnail/apps.py +0 -0
  43. {meringue-1.2.0.dev2 → meringue-1.2.0.dev4}/meringue/thumbnail/constants.py +0 -0
  44. {meringue-1.2.0.dev2 → meringue-1.2.0.dev4}/meringue/thumbnail/drf_fields.py +0 -0
  45. {meringue-1.2.0.dev2 → meringue-1.2.0.dev4}/meringue/thumbnail/exceptions.py +0 -0
  46. {meringue-1.2.0.dev2 → meringue-1.2.0.dev4}/meringue/thumbnail/generators.py +0 -0
  47. {meringue-1.2.0.dev2 → meringue-1.2.0.dev4}/meringue/thumbnail/images.py +0 -0
  48. {meringue-1.2.0.dev2 → meringue-1.2.0.dev4}/meringue/thumbnail/properties.py +0 -0
  49. {meringue-1.2.0.dev2 → meringue-1.2.0.dev4}/meringue/thumbnail/shortcuts.py +0 -0
  50. {meringue-1.2.0.dev2 → meringue-1.2.0.dev4}/meringue/thumbnail/storage.py +0 -0
  51. {meringue-1.2.0.dev2 → meringue-1.2.0.dev4}/meringue/thumbnail/templatetags/__init__.py +0 -0
  52. {meringue-1.2.0.dev2 → meringue-1.2.0.dev4}/meringue/thumbnail/templatetags/m_thumbnails.py +0 -0
  53. {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
1
+ Metadata-Version: 2.3
2
2
  Name: meringue
3
- Version: 1.2.0.dev2
3
+ Version: 1.2.0.dev4
4
4
  Summary: A set of various functionality for a Django based web application.
5
- Project-URL: Homepage, https://github.com/dd/Meringue
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@manin.space>
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/release/1.0.0/graph/badge.svg?token=HV1QGD74EK" alt="Tests - Coverage" />
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@manin.space), 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).
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
- * [ ] Functionality for loading private files available through [nginx internal](http://nginx.org/en/docs/http/ngx_http_core_module.html#internal).
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/release/1.0.0/graph/badge.svg?token=HV1QGD74EK" alt="Tests - Coverage" />
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@manin.space), 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).
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
- * [ ] Functionality for loading private files available through [nginx internal](http://nginx.org/en/docs/http/ngx_http_core_module.html#internal).
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
@@ -1,4 +1,4 @@
1
- __version__ = "1.2.0.dev2"
1
+ __version__ = "1.2.0.dev4"
2
2
  """
3
3
  To update the version, use [hatch version](https://hatch.pypa.io/latest/version/#updating)
4
4
 
@@ -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
- if isinstance(error_detail, list):
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[str] = settings.DEBUG
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,5 @@
1
+ import django
2
+
3
+
4
+ if django.VERSION < (3, 2):
5
+ default_app_config = "meringue.protected.apps.Config"
@@ -0,0 +1,8 @@
1
+ from django.apps import AppConfig
2
+ from django.utils.translation import gettext_lazy as _
3
+
4
+
5
+ class Config(AppConfig):
6
+ name = "meringue.protected"
7
+ verbose_name = _("Protected")
8
+ label = "meringue_protected"
@@ -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@manin.space" },
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
- "Homepage" = "https://github.com/dd/Meringue"
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.11"
86
+ python = "3.12"
87
87
  dependencies = [
88
- "pre-commit==3.3.3",
89
- "ipython==8.14.0",
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.18.0",
93
+ "pycryptodome==3.20.0",
94
94
  "djangorestframework==3.14.0",
95
- "drf-spectacular==0.26.4",
96
- "Pillow==10.0.0",
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 = 'test_project.settings'
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.0.280",
130
- "black==23.7.0",
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.0",
148
+ "pytest==7.4.2",
148
149
  "pytest-django==4.5.2",
149
150
  "pytest-cov==4.1.0",
150
- "Faker==19.2.0",
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.18.0",
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 = 'test_project.settings'
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.0",
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.2.0",
173
- "pytz==2023.3",
174
- "pycryptodome==3.18.0",
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 = 'test_project.settings'
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.7"]
192
- djangorestframework = ["3.13.1"]
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 = ["3.0", "4.0"]
196
- modeltranslation = ["0.18.11"]
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.1",
205
- "mkdocs-literate-nav==0.6.0",
206
- "mkdocs-material==9.1.21",
207
- "mkdocs-git-revision-date-localized-plugin==1.2.0",
208
- "mkdocs-git-authors-plugin==0.7.2",
209
- "mkdocstrings[python]==0.22.0",
210
- "black==23.7.0",
211
- "mkdocs-minify-plugin==0.7.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.15.1",
226
+ "Pygments==2.17.2",
214
227
  "mike==1.1.2",
215
- "linkchecker==10.2.1",
228
+ "linkchecker==10.4.0",
216
229
  ]
217
230
  [tool.hatch.envs.docs.env-vars]
218
- MERINGUE_MKDOCS_ENABLE_MINIFY = 'false'
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}"
@@ -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