django-camomilla-cms 6.0.0b16__py2.py3-none-any.whl → 6.0.0b17__py2.py3-none-any.whl

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 (62) hide show
  1. camomilla/__init__.py +1 -1
  2. camomilla/contrib/modeltranslation/hvad_migration.py +9 -9
  3. camomilla/dynamic_pages_urls.py +6 -2
  4. camomilla/managers/pages.py +87 -2
  5. camomilla/model_api.py +6 -4
  6. camomilla/models/menu.py +9 -4
  7. camomilla/models/page.py +178 -117
  8. camomilla/openapi/schema.py +15 -10
  9. camomilla/redirects.py +10 -0
  10. camomilla/serializers/base/__init__.py +4 -4
  11. camomilla/serializers/fields/__init__.py +5 -17
  12. camomilla/serializers/fields/related.py +5 -3
  13. camomilla/serializers/mixins/__init__.py +23 -240
  14. camomilla/serializers/mixins/fields.py +20 -0
  15. camomilla/serializers/mixins/filter_fields.py +9 -8
  16. camomilla/serializers/mixins/json.py +34 -0
  17. camomilla/serializers/mixins/language.py +32 -0
  18. camomilla/serializers/mixins/nesting.py +35 -0
  19. camomilla/serializers/mixins/optimize.py +91 -0
  20. camomilla/serializers/mixins/ordering.py +34 -0
  21. camomilla/serializers/mixins/page.py +58 -0
  22. camomilla/{contrib/rest_framework/serializer.py → serializers/mixins/translation.py} +16 -56
  23. camomilla/serializers/utils.py +3 -3
  24. camomilla/serializers/validators.py +6 -2
  25. camomilla/settings.py +10 -2
  26. camomilla/storages/default.py +7 -1
  27. camomilla/templates/defaults/parts/menu.html +1 -1
  28. camomilla/templatetags/menus.py +3 -0
  29. camomilla/theme/__init__.py +1 -1
  30. camomilla/theme/{admin.py → admin/__init__.py} +22 -20
  31. camomilla/theme/admin/pages.py +46 -0
  32. camomilla/theme/admin/translations.py +13 -0
  33. camomilla/theme/apps.py +1 -5
  34. camomilla/translation.py +7 -1
  35. camomilla/urls.py +2 -5
  36. camomilla/utils/query_parser.py +42 -23
  37. camomilla/utils/translation.py +47 -5
  38. camomilla/views/base/__init__.py +35 -5
  39. camomilla/views/medias.py +1 -1
  40. camomilla/views/mixins/__init__.py +17 -76
  41. camomilla/views/mixins/bulk_actions.py +22 -0
  42. camomilla/views/mixins/language.py +33 -0
  43. camomilla/views/mixins/optimize.py +18 -0
  44. camomilla/views/mixins/pagination.py +11 -8
  45. camomilla/views/mixins/permissions.py +6 -0
  46. camomilla/views/pages.py +12 -2
  47. {django_camomilla_cms-6.0.0b16.dist-info → django_camomilla_cms-6.0.0b17.dist-info}/METADATA +23 -16
  48. {django_camomilla_cms-6.0.0b16.dist-info → django_camomilla_cms-6.0.0b17.dist-info}/RECORD +60 -43
  49. {django_camomilla_cms-6.0.0b16.dist-info → django_camomilla_cms-6.0.0b17.dist-info}/WHEEL +1 -1
  50. tests/test_camomilla_filters.py +1 -1
  51. tests/test_media.py +98 -65
  52. tests/test_menu.py +97 -0
  53. tests/test_model_api_register.py +393 -0
  54. tests/test_pages.py +343 -0
  55. tests/test_query_parser.py +1 -2
  56. tests/test_templates_context.py +111 -0
  57. tests/utils/api.py +0 -1
  58. tests/utils/media.py +9 -0
  59. camomilla/contrib/rest_framework/__init__.py +0 -0
  60. camomilla/serializers/fields/json.py +0 -48
  61. {django_camomilla_cms-6.0.0b16.dist-info → django_camomilla_cms-6.0.0b17.dist-info/licenses}/LICENSE +0 -0
  62. {django_camomilla_cms-6.0.0b16.dist-info → django_camomilla_cms-6.0.0b17.dist-info}/top_level.txt +0 -0
@@ -1,8 +1,38 @@
1
- from ..mixins import OptimViewMixin, PaginateStackMixin, OrderingMixin, CamomillaBasePermissionMixin
1
+ from ..mixins import (
2
+ OptimViewMixin,
3
+ PaginateStackMixin,
4
+ OrderingMixin,
5
+ CamomillaBasePermissionMixin,
6
+ )
2
7
  from rest_framework import viewsets
8
+ from rest_framework.metadata import SimpleMetadata
9
+ from structured.contrib.restframework import StructuredJSONField
3
10
 
4
11
 
5
- class BaseModelViewset(
6
- CamomillaBasePermissionMixin, OptimViewMixin, OrderingMixin, PaginateStackMixin, viewsets.ModelViewSet
7
- ):
8
- pass
12
+ base_viewset_classes = [
13
+ CamomillaBasePermissionMixin,
14
+ OptimViewMixin,
15
+ OrderingMixin,
16
+ PaginateStackMixin,
17
+ viewsets.ModelViewSet,
18
+ ]
19
+
20
+
21
+ class BaseViewMetadata(SimpleMetadata):
22
+
23
+ def get_field_info(self, field):
24
+ field_info = super().get_field_info(field)
25
+ if isinstance(field, StructuredJSONField):
26
+ field_info["schema"] = field.schema.json_schema()
27
+ field_info["type"] = "structured-json"
28
+ return field_info
29
+
30
+ def get_serializer_info(self, serializer):
31
+ info = super().get_serializer_info(serializer)
32
+ if hasattr(serializer, "plain_to_nest"):
33
+ info.update(serializer.plain_to_nest(info))
34
+ return info
35
+
36
+
37
+ class BaseModelViewset(*base_viewset_classes):
38
+ metadata_class = BaseViewMetadata
camomilla/views/medias.py CHANGED
@@ -61,7 +61,7 @@ class MediaFolderViewSet(
61
61
  ).data
62
62
  media_data = self.format_output(
63
63
  *self.handle_pagination_stack(media_queryset),
64
- SerializerClass=MediaListSerializer
64
+ SerializerClass=MediaListSerializer,
65
65
  )
66
66
  return {
67
67
  "folders": folder_data,
@@ -1,76 +1,17 @@
1
- from rest_framework import status
2
- from rest_framework.decorators import action
3
- from rest_framework.response import Response
4
- from .pagination import *
5
- from .ordering import *
6
- from ...permissions import CamomillaBasePermissions
7
- from django.utils import translation
8
-
9
-
10
- class GetUserLanguageMixin(object):
11
- def _get_user_language(self, request):
12
- self.active_language = request.GET.get(
13
- "language",
14
- request.GET.get(
15
- "language_code", translation.get_language_from_request(request)
16
- ),
17
- )
18
- self.language_fallbacks = True
19
- if (
20
- len(self.active_language.split("-")) == 2
21
- and self.active_language.split("-")[0] == "nofallbacks"
22
- ):
23
- self.language_fallbacks = False
24
- self.active_language = self.active_language.split("-")[1]
25
- translation.activate(self.active_language)
26
- return self.active_language
27
-
28
- def initialize_request(self, request, *args, **kwargs):
29
- self._get_user_language(request)
30
- return super().initialize_request(request, *args, **kwargs)
31
-
32
- def get_queryset(self):
33
- if hasattr(super(), "get_queryset"):
34
- return super().get_queryset()
35
- return self.model.objects.all()
36
-
37
-
38
- class CamomillaBasePermissionMixin:
39
- def get_permissions(self):
40
- return [*super().get_permissions(), CamomillaBasePermissions()]
41
-
42
-
43
- class OptimViewMixin:
44
- def get_serializer_class(self):
45
- if hasattr(self, "action_serializers"):
46
- if self.action in self.action_serializers:
47
- return self.action_serializers[self.action]
48
- return super().get_serializer_class()
49
-
50
- def get_serializer_context(self):
51
- return {"request": self.request, "action": self.action}
52
-
53
- def get_queryset(self):
54
- queryset = super().get_queryset()
55
- serializer = self.get_serializer_class()
56
- if hasattr(serializer, "optimize_qs"):
57
- queryset = serializer.optimize_qs(queryset, context=self.get_serializer_context())
58
- return queryset
59
-
60
-
61
- class BulkDeleteMixin(object):
62
- @action(
63
- detail=False, methods=["post"], permission_classes=(CamomillaBasePermissions,)
64
- )
65
- def bulk_delete(self, request):
66
- try:
67
- self.model.objects.filter(pk__in=request.data).delete()
68
- return Response(
69
- {"detail": "Eliminazione multipla andata a buon fine"},
70
- status=status.HTTP_200_OK,
71
- )
72
- except Exception:
73
- return Response(
74
- {"detail": "Eliminazione multipla non riuscita"},
75
- status=status.HTTP_500_INTERNAL_SERVER_ERROR,
76
- )
1
+ from .bulk_actions import BulkDeleteMixin
2
+ from .language import GetUserLanguageMixin
3
+ from .optimize import OptimViewMixin
4
+ from .ordering import OrderingMixin
5
+ from .pagination import PaginateStackMixin, TrigramSearchMixin
6
+ from .permissions import CamomillaBasePermissionMixin
7
+
8
+
9
+ __all__ = [
10
+ "BulkDeleteMixin",
11
+ "GetUserLanguageMixin",
12
+ "OptimViewMixin",
13
+ "OrderingMixin",
14
+ "PaginateStackMixin",
15
+ "TrigramSearchMixin",
16
+ "CamomillaBasePermissionMixin",
17
+ ]
@@ -0,0 +1,22 @@
1
+ from rest_framework import status
2
+ from rest_framework.decorators import action
3
+ from rest_framework.response import Response
4
+ from ...permissions import CamomillaBasePermissions
5
+
6
+
7
+ class BulkDeleteMixin(object):
8
+ @action(
9
+ detail=False, methods=["post"], permission_classes=(CamomillaBasePermissions,)
10
+ )
11
+ def bulk_delete(self, request):
12
+ try:
13
+ self.model.objects.filter(pk__in=request.data).delete()
14
+ return Response(
15
+ {"detail": "Eliminazione multipla andata a buon fine"},
16
+ status=status.HTTP_200_OK,
17
+ )
18
+ except Exception:
19
+ return Response(
20
+ {"detail": "Eliminazione multipla non riuscita"},
21
+ status=status.HTTP_500_INTERNAL_SERVER_ERROR,
22
+ )
@@ -0,0 +1,33 @@
1
+ from django.utils import translation
2
+ from camomilla import settings
3
+
4
+
5
+ class GetUserLanguageMixin:
6
+ def _get_user_language(self, request):
7
+ active_language_from_request = translation.get_language_from_request(request)
8
+ active_language = (
9
+ active_language_from_request
10
+ if active_language_from_request
11
+ else settings.DEFAULT_LANGUAGE
12
+ )
13
+ active_language = request.GET.get("language_code", active_language)
14
+ active_language = request.GET.get("language", active_language)
15
+ self.active_language = active_language
16
+ self.language_fallbacks = True
17
+ if (
18
+ len(self.active_language.split("-")) == 2
19
+ and self.active_language.split("-")[0] == "nofallbacks"
20
+ ):
21
+ self.language_fallbacks = False
22
+ self.active_language = self.active_language.split("-")[1]
23
+ translation.activate(self.active_language)
24
+ return self.active_language
25
+
26
+ def initialize_request(self, request, *args, **kwargs):
27
+ self._get_user_language(request)
28
+ return super().initialize_request(request, *args, **kwargs)
29
+
30
+ def get_queryset(self):
31
+ if hasattr(super(), "get_queryset"):
32
+ return super().get_queryset()
33
+ return self.model.objects.all()
@@ -0,0 +1,18 @@
1
+ class OptimViewMixin:
2
+ def get_serializer_class(self):
3
+ if hasattr(self, "action_serializers"):
4
+ if self.action in self.action_serializers:
5
+ return self.action_serializers[self.action]
6
+ return super().get_serializer_class()
7
+
8
+ def get_serializer_context(self):
9
+ return {"request": self.request, "action": self.action}
10
+
11
+ def get_queryset(self):
12
+ queryset = super().get_queryset()
13
+ serializer = self.get_serializer_class()
14
+ if hasattr(serializer, "optimize_qs"):
15
+ queryset = serializer.optimize_qs(
16
+ queryset, context=self.get_serializer_context()
17
+ )
18
+ return queryset
@@ -3,6 +3,7 @@ from django.db.models import Q
3
3
  from django.core.paginator import EmptyPage, PageNotAnInteger, Paginator
4
4
  from django.contrib.postgres.search import SearchVector, SearchQuery, TrigramSimilarity
5
5
  from camomilla.utils.query_parser import ConditionParser
6
+ from django.conf import settings
6
7
 
7
8
 
8
9
  class TrigramSearchMixin:
@@ -33,10 +34,6 @@ class PaginateStackMixin:
33
34
  list_handler, "shared_model", getattr(list_handler, "model", None)
34
35
  )
35
36
 
36
- def parse_filter(self, filter):
37
- parser = ConditionParser(filter)
38
- return parser.parse_to_q()
39
-
40
37
  def handle_pagination(self, list_handler=None, items_per_page=None):
41
38
  list_handler = list_handler if list_handler is not None else self.get_queryset()
42
39
  items_per_page = int(
@@ -76,7 +73,7 @@ class PaginateStackMixin:
76
73
  filters = dict(self.request.GET).get("fltr", [])
77
74
  for filter in filters:
78
75
  try:
79
- list_handler = list_handler.filter(self.parse_filter(filter))
76
+ list_handler = list_handler.filter(ConditionParser(filter).db_query)
80
77
  except Exception:
81
78
  pass
82
79
  return list_handler
@@ -86,9 +83,15 @@ class PaginateStackMixin:
86
83
  search_string = self.request.GET.get("search", None)
87
84
  search_fields = search_fields or getattr(self, "search_fields", [])
88
85
  if search_string and len(search_fields) > 0:
89
- return list_handler.annotate(
90
- search=SearchVector(*search_fields),
91
- ).filter(search=SearchQuery(search_string))
86
+ if "sqlite" in settings.DATABASES["default"]["ENGINE"]:
87
+ filter_statement = Q()
88
+ for field in search_fields:
89
+ filter_statement |= Q(**{field + '__icontains': search_string})
90
+ return list_handler.filter(filter_statement)
91
+ else:
92
+ return list_handler.annotate(
93
+ search=SearchVector(*search_fields),
94
+ ).filter(search=SearchQuery(search_string))
92
95
 
93
96
  return list_handler
94
97
 
@@ -0,0 +1,6 @@
1
+ from camomilla.permissions import CamomillaBasePermissions
2
+
3
+
4
+ class CamomillaBasePermissionMixin:
5
+ def get_permissions(self):
6
+ return [*super().get_permissions(), CamomillaBasePermissions()]
camomilla/views/pages.py CHANGED
@@ -1,13 +1,14 @@
1
1
  from camomilla.models import Page
2
- from camomilla.models.page import UrlNode
2
+ from camomilla.models.page import UrlNode, UrlRedirect
3
3
  from camomilla.permissions import CamomillaBasePermissions
4
4
  from camomilla.serializers import PageSerializer
5
5
  from camomilla.serializers.page import UrlNodeSerializer
6
6
  from camomilla.views.base import BaseModelViewset
7
7
  from camomilla.views.decorators import active_lang
8
8
  from camomilla.views.mixins import BulkDeleteMixin, GetUserLanguageMixin
9
- from rest_framework.decorators import api_view
9
+ from rest_framework.decorators import api_view, permission_classes
10
10
  from rest_framework.response import Response
11
+ from rest_framework import permissions
11
12
  from django.shortcuts import get_object_or_404
12
13
 
13
14
 
@@ -20,6 +21,15 @@ class PageViewSet(GetUserLanguageMixin, BulkDeleteMixin, BaseModelViewset):
20
21
 
21
22
  @active_lang()
22
23
  @api_view(["GET"])
24
+ @permission_classes(
25
+ [
26
+ permissions.AllowAny,
27
+ ]
28
+ )
23
29
  def fetch_page(request, permalink=""):
30
+ redirect = UrlRedirect.find_redirect_from_url(f"/{permalink}")
31
+ if redirect:
32
+ redirect = redirect.redirect()
33
+ return Response({"redirect": redirect.url, "status": redirect.status_code})
24
34
  node = get_object_or_404(UrlNode, permalink=f"/{permalink}")
25
35
  return Response(UrlNodeSerializer(node, context={"request": request}).data)
@@ -1,30 +1,33 @@
1
- Metadata-Version: 2.1
1
+ Metadata-Version: 2.4
2
2
  Name: django-camomilla-cms
3
- Version: 6.0.0b16
3
+ Version: 6.0.0b17
4
4
  Summary: Django powered cms
5
5
  Author-email: Lotrèk <dimmitutto@lotrek.it>
6
6
  License: MIT
7
- Project-URL: Homepage, https://github.com/lotrekagency/camomilla
7
+ Project-URL: Homepage, https://github.com/camomillacms/camomilla-core
8
8
  Keywords: cms,django,api cms
9
9
  Classifier: Environment :: Web Environment
10
10
  Classifier: Framework :: Django
11
11
  Classifier: Intended Audience :: Developers
12
12
  Classifier: Programming Language :: Python
13
13
  Classifier: Programming Language :: Python :: 3
14
- Requires-Python: >=3.6
14
+ Requires-Python: <=3.13,>=3.8
15
15
  Description-Content-Type: text/markdown
16
16
  License-File: LICENSE
17
- Requires-Dist: django-modeltranslation ~=0.18.11
18
- Requires-Dist: djsuperadmin <1.0.0,>=0.9
19
- Requires-Dist: djangorestframework <4.0.0,>=3.10.0
20
- Requires-Dist: django-admin-interface <1.0.0,>=0.26.0
21
- Requires-Dist: Pillow <10.0.0,>=6.2.0
22
- Requires-Dist: django-ckeditor <7.0.0,>=5.7.1
23
- Requires-Dist: django-structured-json-field ==0.2.0
24
- Requires-Dist: python-magic <0.5,>=0.4
25
- Requires-Dist: Django >=3.2
26
-
27
- # camomilla django cms [![PyPI](https://img.shields.io/pypi/v/django-camomilla-cms?style=flat-square)](https://pypi.org/project/django-camomilla-cms) ![Codecov](https://img.shields.io/codecov/c/github/lotrekagency/camomilla?style=flat-square) ![GitHub Workflow Status](https://img.shields.io/github/workflow/status/lotrekagency/camomilla/Test,%20Coverage%20and%20Release?style=flat-square) [![GitHub](https://img.shields.io/github/license/lotrekagency/camomilla?style=flat-square)](./LICENSE)
17
+ Requires-Dist: django-modeltranslation<=0.18.12,>=0.18.7
18
+ Requires-Dist: djsuperadmin<1.0.0,>=0.9
19
+ Requires-Dist: djangorestframework<=3.14.0,>=3.10.0
20
+ Requires-Dist: django-structured-json-field>=0.4.1
21
+ Requires-Dist: Pillow>=10.0.0
22
+ Requires-Dist: django-admin-interface<1.0.0,>=0.26.0
23
+ Requires-Dist: django-ckeditor<7.0.0,>=5.7.1
24
+ Requires-Dist: django-tinymce<5.0.0,>=4.1.0
25
+ Requires-Dist: python-magic<0.5,>=0.4
26
+ Requires-Dist: Django<6,>=3.2
27
+ Requires-Dist: django_jsonform>=2.23
28
+ Dynamic: license-file
29
+
30
+ # camomilla django cms [![PyPI](https://img.shields.io/pypi/v/django-camomilla-cms?style=flat-square)](https://pypi.org/project/django-camomilla-cms) ![Codecov](https://img.shields.io/codecov/c/github/camomillacms/camomilla-core?style=flat-square) ![GitHub Workflow Status](https://img.shields.io/github/workflow/status/camomillacms/camomilla-core/Test,%20Coverage%20and%20Release?style=flat-square) [![GitHub](https://img.shields.io/github/license/camomillacms/camomilla-core?style=flat-square)](./LICENSE)
28
31
 
29
32
  ## Install
30
33
 
@@ -35,7 +38,7 @@ $ pip install django-camomilla-cms
35
38
  ## Setup
36
39
  ```shell
37
40
  $ mkdir -p camomilla_migrations
38
- $ touch camomilla_migrations.__init__.py
41
+ $ touch camomilla_migrations/__init__.py
39
42
  $ python manage.py makemigrations camomilla
40
43
  $ python manage.py migrate camomilla
41
44
  ```
@@ -70,3 +73,7 @@ INSTALLED_APPS = [
70
73
 
71
74
  pip install -r requirements-dev.txt
72
75
  make test
76
+
77
+ ## Run format with black
78
+
79
+ black camomilla
@@ -1,38 +1,37 @@
1
- camomilla/__init__.py,sha256=zHhnT2CrQaDldn3CyDbBxGqY4L0nbxsbMQLr6arZrLs,251
1
+ camomilla/__init__.py,sha256=xH1i4zwYfJScQn-ySoem00poi295diBqrVChxqcmkW8,251
2
2
  camomilla/apps.py,sha256=eUwb9ynyiRAc5OXgt7ZsAdhsCOnPCpNdIFYMheNeN-o,532
3
3
  camomilla/authentication.py,sha256=jz6tQT4PPEu-_JLox1LZrOy7EiWBb9MWaObK63MJGus,855
4
4
  camomilla/context_processors.py,sha256=cGowjDZ-oDGYn1j2Pj5QDGCqnzXAOdOwp5dmzin_FTc,165
5
5
  camomilla/defaults.py,sha256=VNQ_sbxu09AyFGNpUUYypIAyhlBhEORD36BBNj7e73I,1220
6
- camomilla/dynamic_pages_urls.py,sha256=14H47KlSxmINoJyrsul0KR7Qvk6-1uoXrD1ReV_W4h8,1056
6
+ camomilla/dynamic_pages_urls.py,sha256=wd52ktpY_LH24jTW77vII7XZ25p_Kz5MSjes8s_94-A,1278
7
7
  camomilla/exceptions.py,sha256=gLniAsK_pmsNNKGMv5Z384LXVbM8oeHcOwz4F91u1LY,111
8
- camomilla/model_api.py,sha256=1xQxDWGPQNVqa_c87pLq4gj1ZHta2IFqdeEbzErHZX8,2447
8
+ camomilla/model_api.py,sha256=-7l3fc2eN1itCMzkWA8nFaQXMmz0vs7IlGlShF-gSuo,2487
9
9
  camomilla/parsers.py,sha256=fL8XGCGPxJIZNZkPdGtnPSbDP-6-yzGOCVMuLPjkx9Y,1975
10
10
  camomilla/permissions.py,sha256=9NlBO4JMmg36vXCUjPNyq6uZxhkdrnXyIbJVLtWhGWE,1813
11
- camomilla/settings.py,sha256=GDJXDcEmyobGrP4MmEH3MAt1KBK74gXmmRR8kFuJzp0,3306
11
+ camomilla/redirects.py,sha256=ilcyHidb5Iw3jTrXMnPntr50kkl_WB3QOB0VNkIxP7A,263
12
+ camomilla/settings.py,sha256=nY-a1PRhbQ_edvNG5WyndPLWxwsRb_h4eFAjmOHvKYM,3599
12
13
  camomilla/sitemap.py,sha256=U2t5TwhB_-sEscmQZ69PZ5st3bIap8NRxzWEvCgB130,786
13
- camomilla/translation.py,sha256=-Y0Toy1D__wxMovipWVIuNx3TrfhDGffrduWYFUmYA4,1269
14
- camomilla/urls.py,sha256=YFUYcPuvnNSTnfJa_JByRWAPLgc4_R4LgqCMrmkbFpE,2217
14
+ camomilla/translation.py,sha256=_QyfTlKG6hQ_ClRfxzeJ-3oI3Nu5peJN9xFkO9Ib3As,1316
15
+ camomilla/urls.py,sha256=XgaeFoG2eXlJQve3KmFKlD-74CMLW1ziaY1mq-lrAiA,2095
15
16
  camomilla/contrib/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
16
17
  camomilla/contrib/modeltranslation/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
17
- camomilla/contrib/modeltranslation/hvad_migration.py,sha256=UanLVSlYYd_ykMC4STtYkkUMJqlFQQYhbWkoV47alM0,5403
18
- camomilla/contrib/rest_framework/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
19
- camomilla/contrib/rest_framework/serializer.py,sha256=G6SKes-8RkJKDupCNN0B2B1BQuYqS0y820oGYotxPcY,5924
18
+ camomilla/contrib/modeltranslation/hvad_migration.py,sha256=3j_q_Q85eF4iHbU4LG1Zr3LOmfmGmFiVSL-C8KvPsJQ,5409
20
19
  camomilla/fields/__init__.py,sha256=gKrJwHvUA3q_wu-OVV0hrRZmFkT4znMHrmZtpriDumw,323
21
20
  camomilla/fields/json.py,sha256=tWEDn6kwTP6pNB53djxuVPu2d57m9cIDc4ccCEfUbDQ,1938
22
21
  camomilla/management/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
23
22
  camomilla/management/commands/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
24
23
  camomilla/management/commands/regenerate_thumbnails.py,sha256=pKToASR8p8TJezGpFfuylsAHtriNueJ7xqJJxq55adY,496
25
24
  camomilla/managers/__init__.py,sha256=Zwp28E1RKafIl0FqcUi1YNHxF19IsMIvhlhS-Njg9Mw,60
26
- camomilla/managers/pages.py,sha256=ifwYuOCaX8pf1-mR71IXuE5KDl2UWtcuwmGV26Hi9EU,1129
25
+ camomilla/managers/pages.py,sha256=DYV1i5vPgxn1YzJlY3kSlsVCRgsiojLxjs2O0LylxEI,3925
27
26
  camomilla/models/__init__.py,sha256=y7Q34AGhQ1weJUKWb6XjiyUbwRnJeylOBGMErU0wqYg,147
28
27
  camomilla/models/article.py,sha256=LgkZgRsubtDV6NwBz8E2bIgKD6H3I-1QLAxEan5TYYs,1139
29
28
  camomilla/models/content.py,sha256=mIgtifb_WMIt58we5u6qWZemHvuDN1zZaBeCyzHL78A,956
30
29
  camomilla/models/media.py,sha256=pD-qldiHDOOHgux4lsivQLBcOJJrRx3a4Bg8ODNx7r0,6852
31
- camomilla/models/menu.py,sha256=zXL644mQLRxt5aLZKv66l4RGlEi-a33cwmq7xpD9S5E,3661
32
- camomilla/models/page.py,sha256=jMtnJ_leps6hnpZ52Ot_nXlgqUO5lUFshUzpYJtrRjk,17237
30
+ camomilla/models/menu.py,sha256=hUszPcn1prWCDhk4RPvbITmyhsB2CjFkaerx9t1GWnc,3766
31
+ camomilla/models/page.py,sha256=lkZPdPkl8Yxpz_NfYrpr7Myp8hB3bEAGtdJwKBR7_cg,19385
33
32
  camomilla/models/mixins/__init__.py,sha256=c2NixqvrIX4E9WGRqQbylXlqBWDXEqN9mzs_dpB0hFQ,1248
34
33
  camomilla/openapi/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
35
- camomilla/openapi/schema.py,sha256=08HaV3-X-96b15Bo1X9IJmT2bv-bCqOkVrmWpz-fesM,2381
34
+ camomilla/openapi/schema.py,sha256=C22dhKjaJ2DTK4KWFjyMJXiwe8NLy7ZTW5d-I1dqZ7g,2546
36
35
  camomilla/serializers/__init__.py,sha256=8v1GsJ_YZ6T72VnKBb5l-8K93oaLf4PIsMt-yFtK-Gk,176
37
36
  camomilla/serializers/article.py,sha256=pYVcS0KztzjzSqgruElQMMEZcqTzmQUqXrdv_Sx5Az4,401
38
37
  camomilla/serializers/content_type.py,sha256=qB2wkmkvQI6LHxfSI6auEh6M9cJRFBaHnpmkBCCzeYo,557
@@ -40,17 +39,24 @@ camomilla/serializers/media.py,sha256=H4JVpRVxXVmn_BiqrjihKXpfLm9fLmHDFIICRDGJU4
40
39
  camomilla/serializers/menu.py,sha256=TdoyXs40PqxNevnRbBbYOOX9rUv9zQGiHFNduspaZnw,552
41
40
  camomilla/serializers/page.py,sha256=NNjEypVYu_9iKqdHV_-61ea37gxiHlDP5gsloV_i6yg,1834
42
41
  camomilla/serializers/user.py,sha256=CzrHiVRvYYWNE4eNpCNKtJB7DjVqHHwIcP4NUBXMHSo,3706
43
- camomilla/serializers/utils.py,sha256=uPQNNkIMZyoPP4umWTgFHNM7KyabBZgs5r5AJyfgtJI,1105
44
- camomilla/serializers/validators.py,sha256=EX-EFg6afFr8viPKq-LHeEtRAKPVtO4kIlEymY1j2HA,2043
45
- camomilla/serializers/base/__init__.py,sha256=P2153u7T4yQSbgwIC9LJxJFnVSle3H9oEuTUNrnz9x4,869
46
- camomilla/serializers/fields/__init__.py,sha256=T_ONowldBTPfgbwFmoefY1r3TQiB2sbWQPpFvBSnzqE,681
42
+ camomilla/serializers/utils.py,sha256=XRL4CNwQDBNpX8xT7365Dw2Cyx8Kvh18GaadgjS9awk,968
43
+ camomilla/serializers/validators.py,sha256=X2uBlh348nJjUWHPtiu9XKCD7Etsdg0811a4xHLAUzU,2103
44
+ camomilla/serializers/base/__init__.py,sha256=maaL3y6tvc5Ph9y07KVcMvZVYTkzh_3aBiBnGCoi1EA,799
45
+ camomilla/serializers/fields/__init__.py,sha256=0I_E9oMtlC0H48LjStMQZiZ-Ycoy49nWK9GvA5JWxN8,145
47
46
  camomilla/serializers/fields/file.py,sha256=yjKMho2ti9TIAzo6nwyLnNPJ6GVUumL2wxhegvYqI2o,800
48
- camomilla/serializers/fields/json.py,sha256=epuvDkKqDHuXAH0jVpOkeljz7LnMJVg7RoWYioPgCNs,1873
49
- camomilla/serializers/fields/related.py,sha256=kG5_q1ckm33BVUIgPLZFa6IjL5lQ5DT8_83fUe9plc8,4989
50
- camomilla/serializers/mixins/__init__.py,sha256=lDfeIoaMqKH11QHzBNs4hA5aHBV7sJsjzGLew6tdcXU,9367
51
- camomilla/serializers/mixins/filter_fields.py,sha256=AwdV5iG-r0JFy4Wtywczu7bqA8Fb6NZyy60Y79Z6cWo,2214
47
+ camomilla/serializers/fields/related.py,sha256=qQQeUxIZSNqnVRHsXocLGmBNHjAvrlr0eDY9K2uCjWk,5069
48
+ camomilla/serializers/mixins/__init__.py,sha256=gMyFpSWHLtLTlKucP1Xk-GtBNX48CwwyY6_wEN3L9vA,640
49
+ camomilla/serializers/mixins/fields.py,sha256=h-YBHBITLGHsrXRgSYP3NBoUzJqmQ_5HhhftoFFNsKs,711
50
+ camomilla/serializers/mixins/filter_fields.py,sha256=sqnCG1hi_qfISFJvwgh37BLyQoNDifR0pU7zmJn_MW8,2236
51
+ camomilla/serializers/mixins/json.py,sha256=Iq5S7mUg5_Y4bsm6XN3ECJR07NGjCAQ21_wdxj6RgyY,1193
52
+ camomilla/serializers/mixins/language.py,sha256=VukEvPzTpKQfwB-z_RtoNIJ43N3OEgfjLpHvn9KuZDU,1205
53
+ camomilla/serializers/mixins/nesting.py,sha256=gCEU2UE_Y8e4VRnvT0AExFgwTfJm_jnSqa6l2SwZ3Mg,1432
54
+ camomilla/serializers/mixins/optimize.py,sha256=zAtbtk6kfGq9FnapqI8tVYOuMKd1IkHbAV6LffL61Z4,3845
55
+ camomilla/serializers/mixins/ordering.py,sha256=rXQOz47_U4IsMT6IBhySghcmJWMZgpPWHovDcZQG88k,1172
56
+ camomilla/serializers/mixins/page.py,sha256=Ida7dY9MQTv747_dpPGpo6u3iL5GX87z4zeVct-C36s,2132
57
+ camomilla/serializers/mixins/translation.py,sha256=Om2UT2EB4Xvp8SrIEvraY0kJXR9H54AsYBr9DKjsay8,4323
52
58
  camomilla/storages/__init__.py,sha256=ytGgX59Ar8vFfYz7eV8z-j5yO_5FqxdZM25iyLnJuSA,131
53
- camomilla/storages/default.py,sha256=KVuGPIpkM9tDHc0cYG385xkiKOwIvage5IBmdrv2uOk,188
59
+ camomilla/storages/default.py,sha256=GNzvV_JZpXMcfTkyXjw5CfK8EIBi3o-NXYBO0KAxD5M,351
54
60
  camomilla/storages/optimize.py,sha256=VGSXZigzZC8LnPTqyTOpPA2Ba9EJB_KC5bcACoRs4GA,2762
55
61
  camomilla/storages/overwrite.py,sha256=jvW3zHvXNzH9dIjeZmmfXo_O3K1ZQmLQzmlSKAOE8ZA,360
56
62
  camomilla/templates/admin/camomilla/page/change_form.html,sha256=ig7rRUtylDZMINBQuVPpZLmeB4sOTV_VtqnTgzAyxEo,251
@@ -58,17 +64,19 @@ camomilla/templates/defaults/base.html,sha256=pklt7Pif3g9d7gwgRxCQj7gniJaHD14ZqZ
58
64
  camomilla/templates/defaults/articles/default.html,sha256=1f89jBvNtTa1mPAbC91yy8CzeAjTWO3hhQsTuQW5OKg,239
59
65
  camomilla/templates/defaults/pages/default.html,sha256=bP81Qb6M56I-fBJMywWwEu_cnERtWIX28UkGrUSRU6M,144
60
66
  camomilla/templates/defaults/parts/langswitch.html,sha256=AkaQzb2KNjRYCMLUn_jE31V36rwBIwp4MneirWPiBcI,3424
61
- camomilla/templates/defaults/parts/menu.html,sha256=CSRPx78Z6D6pGtRqqaLmJetUaADrTh9rx_gqS4myndc,381
67
+ camomilla/templates/defaults/parts/menu.html,sha256=ReE-FfmfCNuNkJI33QqIfmMgLSBl3FTkWAhEa59aD3A,381
62
68
  camomilla/templates/defaults/widgets/media_select_multiple.html,sha256=k2XYou8KkPuFLnPMkPJAFJ-zGJj2Xvu6R3ZmiKa3g7Q,3727
63
69
  camomilla/templates_context/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
64
70
  camomilla/templates_context/autodiscover.py,sha256=td7SCsqg3iNPnv1HDEDEpwWgWLjy5Zmc8Nbze1_J46I,1907
65
71
  camomilla/templates_context/rendering.py,sha256=GfTR45_gC7WT7zTKPVXkBDwe22uF63A-DfZUW31woAU,3194
66
72
  camomilla/templatetags/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
67
73
  camomilla/templatetags/camomilla_filters.py,sha256=35x0-cWrRHeLhqypSLlJzEFY_fQDcRHiwZQpFgIsspE,692
68
- camomilla/templatetags/menus.py,sha256=pLFeJ1UAm3flsU9TNo2iQk4otSwZuJPr86Nf408dZ-8,862
69
- camomilla/theme/__init__.py,sha256=ZTc6bQJ8jCuKWUOkNmYh8qHpCpZ6iN55XQS_wWviAis,30
70
- camomilla/theme/admin.py,sha256=7TgNXOfIy4awtV-KkGEKsmai94qhBiykB0uJWwTZy8U,2461
71
- camomilla/theme/apps.py,sha256=ecqG8ntWdOighYOEHQOMVQpa5g_1WEzzpaaGjnOi9uA,1195
74
+ camomilla/templatetags/menus.py,sha256=7fc4f9DDqtqG6wNb5_Q0km-fq0mqvGnbpR21qO1TJUw,960
75
+ camomilla/theme/__init__.py,sha256=3ahSYJ-HBLHrW2VZ45mAM6mlZvpqDKPffxhE0EkD9as,30
76
+ camomilla/theme/apps.py,sha256=3nCSZ6d4tkx2aMNNnQQoqX8PGrrMNf4VxCxBV_JXNrA,1040
77
+ camomilla/theme/admin/__init__.py,sha256=TALAZaE-gWshSeGc6yy7VahdX5UfeCeoOE9Q5kJCEpM,2270
78
+ camomilla/theme/admin/pages.py,sha256=y3rL1nwZlytyD-YR_qqLiBAmjCAjkBY3v56V6JdhBvY,1908
79
+ camomilla/theme/admin/translations.py,sha256=iAjGM1A1aYrsz1FpeybROk6rn3Ddl_oUCwgU5oD8nSw,308
72
80
  camomilla/theme/static/admin/css/responsive.css,sha256=yGq6qXrr8xEVsXTnprIBgkX-sMGZrNf0Kkh-xDxf6yE,157
73
81
  camomilla/theme/static/admin/img/favicon.ico,sha256=qpKv_2MaGILvyihnD1Vq9Yk-ZXGkxWTW26ciMeBFMYU,15406
74
82
  camomilla/theme/static/admin/img/logo.svg,sha256=WBAORIV_LzEOdcpq7iU6d0Nu3omgk2gn05f6LnPjfWg,3238
@@ -77,39 +85,48 @@ camomilla/theme/templates/rosetta/base.html,sha256=s9Ijf1nZx8um30R5Gk3g-w-RwFGv2
77
85
  camomilla/utils/__init__.py,sha256=Ui7nzSh45UMMFtCGF1xFHKyJMNWflG_Nx72HAJHJHFM,100
78
86
  camomilla/utils/getters.py,sha256=6j18grFAZ8BC70SriycFDTQFxTnudGn0uKGA83_Rclk,798
79
87
  camomilla/utils/normalization.py,sha256=RDCZtjwpEEwjvfUjQl2bEWFKw7NxTzkXco72VeO2M9w,255
80
- camomilla/utils/query_parser.py,sha256=STNUfoKENcRM_joIKh5AVvYADppsURj9Jpf9OkUQrJU,5818
88
+ camomilla/utils/query_parser.py,sha256=TUScPzPVVJzaKdqy5NqtMOft3H5Bx6liXTVPM1yjH24,6303
81
89
  camomilla/utils/seo.py,sha256=8p_a_TGgohenpJb094tT4mMxbn2xzW0qDILuTnjNocM,3324
82
90
  camomilla/utils/setters.py,sha256=LV57SM65rL1_ZQkVzk9al_Q13lndVywXLkqgfIvgS0Y,915
83
91
  camomilla/utils/templates.py,sha256=Lv4-5019cnM30HmdZnYWiU5gxry-eFZVAhwOofGQRDs,598
84
- camomilla/utils/translation.py,sha256=HG70ki9MTBVTdAYgi6lqqFQtNm30VTvGSYepXpyb3_Y,2477
92
+ camomilla/utils/translation.py,sha256=w5tvTInDLegWBb1TnDWo09ckKY3K6hajuNNsngZIxPQ,4205
85
93
  camomilla/views/__init__.py,sha256=94QuOnnbfMMb17mruO2ydUt286-8zBmDxEPWrJv5Wog,178
86
94
  camomilla/views/articles.py,sha256=qGxebOA5iTbGGe9PfbH40YBoDPKktH8FJongg6rh2R8,571
87
95
  camomilla/views/contents.py,sha256=JxvnmgeK8JEmCMLzVG8pVq2DwvmjXtgnIdsDnn74tA4,1205
88
96
  camomilla/views/decorators.py,sha256=hR--nTGQn2mMKDrWn-0Ildzbsvp11OfoWAtedKEzmiA,982
89
97
  camomilla/views/languages.py,sha256=Rt_X7s3dbDBv4dxsQ9fnav_u0TAzzo8fGKBBx3esDsg,441
90
- camomilla/views/medias.py,sha256=S4Ak4JI6XCSu3BCZx8KOotX7TBfrIU82GPXgyP3KcZA,3001
98
+ camomilla/views/medias.py,sha256=XYa-NTLLQmSSynpfrFT3av-K_r59aRns3dTGfYMj-0Q,3002
91
99
  camomilla/views/menus.py,sha256=Kpygnf3tMKJ30gcblUES2NW83A37Vy75ecSGSvExGKM,3301
92
- camomilla/views/pages.py,sha256=KrBsKT0Z-rkBha8K3P6fVDt4vArQBxsc9rZ28j8XW9w,994
100
+ camomilla/views/pages.py,sha256=UL74_u-18QdAkjVl74AVWZbRarEdIPrANTzdcM4iqmE,1338
93
101
  camomilla/views/tags.py,sha256=XcYRlcBFSPPY32lt7POb6fWPJL_8HsTo5JcHcAOiOKw,479
94
102
  camomilla/views/users.py,sha256=_fvsKOEtep4SJLvMva2_q-HdLQT_1KlFNt4wcl3xCJk,3130
95
- camomilla/views/base/__init__.py,sha256=dWiyyRpvOWXMmBeLsfLDOCK_ZesYzBBniH71zAu6hu4,282
96
- camomilla/views/mixins/__init__.py,sha256=MEZiQf-wkY80J-f9c6GnLD2o97YefCKyn5PXW9jj8bc,2672
103
+ camomilla/views/base/__init__.py,sha256=t-7tqY_ep4Xi8YgB1sXDgNWQ5oh2YEUlfQWU5pltwJ0,1063
104
+ camomilla/views/mixins/__init__.py,sha256=Znv3fLYVy6lgu03Q_D8fTen4zMxI6VSRaLPDU8Cp7Ws,473
105
+ camomilla/views/mixins/bulk_actions.py,sha256=i0duWW6wey9m7I_V8-gPcHsbJyPEfSdMdj4h2i-CbPw,787
106
+ camomilla/views/mixins/language.py,sha256=hfnYznlVMrMLBdJ_f8dChJWENg7Kpt9m1yqavrdLm7E,1299
107
+ camomilla/views/mixins/optimize.py,sha256=iRPNkoeIIlJugk7DjJhDPaqeX7Opi7TxnUoMDnxJxUk,686
97
108
  camomilla/views/mixins/ordering.py,sha256=mh7fqPyVCVJh84Nl2pYFQouzGxa-ANF3Wqv0pCb7OVU,4779
98
- camomilla/views/mixins/pagination.py,sha256=8BY4T5aWw50LSgIbwM4X0_HWm8GFgKWKn1TUrY028No,5519
109
+ camomilla/views/mixins/pagination.py,sha256=NWerBdMyBt4Kswig4fbANqGTzsll8SJdE6a8_UIoueU,5772
110
+ camomilla/views/mixins/permissions.py,sha256=TPmR3Hoa3BjeJu9rCE_7lpLOAupue4WI42C21HTo6X4,200
111
+ django_camomilla_cms-6.0.0b17.dist-info/licenses/LICENSE,sha256=kVS7zDrNkav2hLLXbOJwVdonY2ToApTK3khyJagGQoQ,1063
99
112
  tests/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
100
113
  tests/test_api.py,sha256=t03EFDezGgm4UJl8RIVvnTUkAGTB6ptm0G2lHBQ7ljc,1833
101
- tests/test_camomilla_filters.py,sha256=9tHdxhU-Qk5c3ZWbhLQE3g1VrWKS-cGlRG258D1T9hI,1535
102
- tests/test_media.py,sha256=bBFUFWEKWIWgDxclOyAfLW5wUCERSfONtxD_OOz9KBg,2523
114
+ tests/test_camomilla_filters.py,sha256=5LlR3tctGu6qxVmOrY52AGh_ACvEzdAvkwH2v7medpo,1536
115
+ tests/test_media.py,sha256=IG-cigWxDnsq54DRVaPO2O0lcsnutfKRsqPTTR8W1E8,4183
116
+ tests/test_menu.py,sha256=HyEdDzTDsLtNzsTNGjjZ6SCrgTXRU3FkKviUOacnYRg,3582
103
117
  tests/test_model_api.py,sha256=Ne8YlXTH2cqP5gzOc8UKjJuh0t-NaKHh5Ol9krpVHQg,3768
104
118
  tests/test_model_api_permissions.py,sha256=7CSb4-yIOfycAL_vXvh1dE2whx7k0gNkWl9LO0yzy4I,1801
119
+ tests/test_model_api_register.py,sha256=9pqf7fvtniw63ZD4P2JItfDC0brD55vIrqjZ4phm_qs,14016
105
120
  tests/test_models.py,sha256=WJs8lxWZWn1l7X3a_QFVc8fF5LHTsI8bc3uhQe6-o-Q,684
106
- tests/test_query_parser.py,sha256=ebHQwjGINHy84JZZXUxrdutXtlHBhoqq7keLr5GHFik,2098
121
+ tests/test_pages.py,sha256=qIVdfmbtx7GKHyNWHhirR58gGr9zjfrrzXXkvYlLusc,11469
122
+ tests/test_query_parser.py,sha256=R9l0L2QDEDcm2b6IFUhyf7wMXLzL9RySLkzKTWRtBkE,2097
123
+ tests/test_templates_context.py,sha256=D72ufRqCGjInGGXHSNVhlJ1HcWG0zMqrAiTuiaU057k,4694
107
124
  tests/test_utils.py,sha256=o_FG7XOxLePOBfwBr4sk09gej0onWNw9t2-gSjGmgNg,3741
108
125
  tests/fixtures/__init__.py,sha256=NGj22kLV65v56IpOrOVqSkPhJePTXD4QjuuZhZSMwfQ,460
109
126
  tests/utils/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
110
- tests/utils/api.py,sha256=vnj6W3PG5a-R_uF43nv3UushpMfyG_HbqlsBXH9Ysg0,910
111
- django_camomilla_cms-6.0.0b16.dist-info/LICENSE,sha256=kVS7zDrNkav2hLLXbOJwVdonY2ToApTK3khyJagGQoQ,1063
112
- django_camomilla_cms-6.0.0b16.dist-info/METADATA,sha256=pwvWq5hO3tSBO2Qmt0TgoKJy5QY5Kko2yeaXYjubXAw,2390
113
- django_camomilla_cms-6.0.0b16.dist-info/WHEEL,sha256=OpXWERl2xLPRHTvd2ZXo_iluPEQd8uSbYkJ53NAER_Y,109
114
- django_camomilla_cms-6.0.0b16.dist-info/top_level.txt,sha256=G9VIGBmMMqC7JEckoTgXKmC6T2BR75QRkqRnngw1_lo,16
115
- django_camomilla_cms-6.0.0b16.dist-info/RECORD,,
127
+ tests/utils/api.py,sha256=TYcDXeILHtBwzwG0acwPFmiqMZnlF9VnLB0Ydhg55vA,865
128
+ tests/utils/media.py,sha256=ChsoHqwWmVYHE7teFsV9swTqBEFD0zcvQSBuKsK9G_s,298
129
+ django_camomilla_cms-6.0.0b17.dist-info/METADATA,sha256=oiU3jK3ZCjQurWBdq2vaUZgBr2OMim4RLEjSPtIVm28,2565
130
+ django_camomilla_cms-6.0.0b17.dist-info/WHEEL,sha256=oSJJyWjO7Z2XSScFQUpXG1HL-N0sFMqqeKVVbZTPkWc,109
131
+ django_camomilla_cms-6.0.0b17.dist-info/top_level.txt,sha256=G9VIGBmMMqC7JEckoTgXKmC6T2BR75QRkqRnngw1_lo,16
132
+ django_camomilla_cms-6.0.0b17.dist-info/RECORD,,
@@ -1,5 +1,5 @@
1
1
  Wheel-Version: 1.0
2
- Generator: setuptools (75.3.0)
2
+ Generator: setuptools (80.3.1)
3
3
  Root-Is-Purelib: true
4
4
  Tag: py2-none-any
5
5
  Tag: py3-none-any
@@ -38,4 +38,4 @@ class CamomillaFiltersTestCase(TestCase):
38
38
  request.META["HTTP_HOST"] = "localhost"
39
39
  page = Page.get(request)
40
40
  alt_urls = dict(alternate_urls(page, request))
41
- self.assertEqual(alt_urls, {'it': None, 'en': '/path/'})
41
+ self.assertEqual(alt_urls, {'it': None, 'en': '/path/'})