django-camomilla-cms 6.0.0b14__py2.py3-none-any.whl → 6.0.0b16__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 (51) hide show
  1. camomilla/__init__.py +1 -1
  2. camomilla/dynamic_pages_urls.py +2 -1
  3. camomilla/fields/__init__.py +1 -3
  4. camomilla/managers/pages.py +22 -33
  5. camomilla/model_api.py +9 -4
  6. camomilla/models/media.py +1 -1
  7. camomilla/models/menu.py +23 -11
  8. camomilla/models/page.py +76 -38
  9. camomilla/openapi/schema.py +4 -0
  10. camomilla/serializers/base/__init__.py +3 -1
  11. camomilla/serializers/fields/__init__.py +2 -2
  12. camomilla/serializers/fields/json.py +2 -2
  13. camomilla/serializers/fields/related.py +5 -1
  14. camomilla/serializers/mixins/__init__.py +56 -18
  15. camomilla/serializers/mixins/filter_fields.py +56 -0
  16. camomilla/serializers/utils.py +3 -1
  17. camomilla/serializers/validators.py +9 -5
  18. camomilla/settings.py +0 -4
  19. camomilla/storages/default.py +6 -0
  20. camomilla/storages/optimize.py +2 -2
  21. camomilla/storages/overwrite.py +2 -2
  22. camomilla/templates/defaults/parts/menu.html +1 -1
  23. camomilla/theme/__init__.py +1 -1
  24. camomilla/theme/admin.py +1 -1
  25. camomilla/translation.py +1 -1
  26. camomilla/utils/query_parser.py +148 -0
  27. camomilla/utils/setters.py +37 -0
  28. camomilla/views/base/__init__.py +2 -2
  29. camomilla/views/menus.py +0 -3
  30. camomilla/views/mixins/__init__.py +9 -2
  31. camomilla/views/mixins/pagination.py +4 -13
  32. {django_camomilla_cms-6.0.0b14.dist-info → django_camomilla_cms-6.0.0b16.dist-info}/METADATA +2 -3
  33. {django_camomilla_cms-6.0.0b14.dist-info → django_camomilla_cms-6.0.0b16.dist-info}/RECORD +46 -40
  34. {django_camomilla_cms-6.0.0b14.dist-info → django_camomilla_cms-6.0.0b16.dist-info}/WHEEL +1 -1
  35. tests/fixtures/__init__.py +17 -0
  36. tests/test_api.py +2 -11
  37. tests/test_camomilla_filters.py +7 -13
  38. tests/test_media.py +80 -0
  39. tests/test_model_api.py +68 -0
  40. tests/test_model_api_permissions.py +39 -0
  41. tests/test_query_parser.py +59 -0
  42. tests/test_utils.py +64 -64
  43. tests/utils/__init__.py +0 -0
  44. tests/utils/api.py +29 -0
  45. camomilla/structured/__init__.py +0 -125
  46. camomilla/structured/cache.py +0 -202
  47. camomilla/structured/fields.py +0 -150
  48. camomilla/structured/models.py +0 -47
  49. camomilla/structured/utils.py +0 -114
  50. {django_camomilla_cms-6.0.0b14.dist-info → django_camomilla_cms-6.0.0b16.dist-info}/LICENSE +0 -0
  51. {django_camomilla_cms-6.0.0b14.dist-info → django_camomilla_cms-6.0.0b16.dist-info}/top_level.txt +0 -0
@@ -1,47 +0,0 @@
1
- from inspect import isclass
2
- from typing import Any, Dict, Tuple, get_origin
3
-
4
- import pydantic._internal._model_construction
5
- from django.db.models import Model as DjangoModel
6
- from pydantic import BaseModel as PyDBaseModel
7
- from pydantic import Field, model_validator
8
- from typing_extensions import Annotated
9
-
10
- from .fields import ForeignKey, QuerySet
11
- from .utils import get_type, map_method_aliases
12
-
13
-
14
- class BaseModelMeta(pydantic._internal._model_construction.ModelMetaclass):
15
- def __new__(
16
- mcs, name: str, bases: Tuple[type], namespaces: Dict[str, Any], **kwargs
17
- ):
18
- annotations: dict = namespaces.get("__annotations__", {})
19
- for base in bases:
20
- for base_ in base.__mro__:
21
- if base_ is PyDBaseModel:
22
- break
23
- annotations.update(base_.__annotations__)
24
-
25
- for field in annotations:
26
- annotation = annotations[field]
27
- origin = get_origin(annotation)
28
- if isclass(annotation) and issubclass(annotation, DjangoModel):
29
- annotations[field] = ForeignKey[annotation]
30
- elif isclass(origin) and issubclass(origin, QuerySet):
31
- annotations[field] = Annotated[
32
- annotation,
33
- Field(default_factory=get_type(annotation)._default_manager.none),
34
- ]
35
- namespaces["__annotations__"] = annotations
36
- return map_method_aliases(
37
- super().__new__(mcs, name, bases, namespaces, **kwargs)
38
- )
39
-
40
-
41
- class BaseModel(PyDBaseModel, metaclass=BaseModelMeta):
42
- @model_validator(mode="before")
43
- @classmethod
44
- def build_cache(cls, data: Any) -> Any:
45
- from camomilla.structured.cache import CacheBuilder
46
-
47
- return CacheBuilder.from_model(cls).inject_cache(data)
@@ -1,114 +0,0 @@
1
- from typing import Any, Generic, Sequence
2
- from typing_extensions import TypeVar, get_args
3
- from django.core.exceptions import ImproperlyConfigured
4
- from camomilla.utils.getters import pointed_getter
5
-
6
-
7
- T = TypeVar("T")
8
-
9
-
10
- class _LazyType:
11
- def __init__(self, path):
12
- self.path = path
13
-
14
- def evaluate(self, base_cls):
15
- module, type_name = self._evaluate_path(self.path, base_cls)
16
- return self._import(module, type_name)
17
-
18
- def _evaluate_path(self, relative_path, base_cls):
19
- base_module = base_cls.__module__
20
-
21
- modules = self._get_modules(relative_path, base_module)
22
-
23
- type_name = modules.pop()
24
- module = ".".join(modules)
25
- if not module:
26
- module = base_module
27
- return module, type_name
28
-
29
- def _get_modules(self, relative_path, base_module):
30
- canonical_path = relative_path.lstrip(".")
31
- canonical_modules = canonical_path.split(".")
32
-
33
- if not relative_path.startswith("."):
34
- return canonical_modules
35
-
36
- parents_amount = len(relative_path) - len(canonical_path)
37
- parent_modules = base_module.split(".")
38
- parents_amount = max(0, parents_amount - 1)
39
- if parents_amount > len(parent_modules):
40
- raise ValueError(f"Can't evaluate path '{relative_path}'")
41
- return parent_modules[: parents_amount * -1] + canonical_modules
42
-
43
- def _import(self, module_name, type_name):
44
- module = __import__(module_name, fromlist=[type_name])
45
- try:
46
- return getattr(module, type_name)
47
- except AttributeError:
48
- raise ValueError(f"Can't find type '{module_name}.{type_name}'.")
49
-
50
-
51
- def get_type(source: Generic[T], raise_exception=True) -> T:
52
- try:
53
- return get_args(source)[0]
54
- except IndexError:
55
- if raise_exception:
56
- raise ImproperlyConfigured(
57
- "Must provide a Model class for ForeignKey fields."
58
- )
59
- else:
60
- return None
61
-
62
-
63
- def get_type_eval(source: Generic[T], model: Any, raise_exception=True) -> T:
64
- type = get_type(source, raise_exception)
65
- if isinstance(type, str):
66
- return _LazyType(type).evaluate(model)
67
-
68
-
69
- def set_key(data, key, val):
70
- if isinstance(data, Sequence):
71
- key = int(key)
72
- if key < len(data):
73
- data[key] = val
74
- else:
75
- data.append(val)
76
- return data
77
- elif isinstance(data, dict):
78
- data[key] = val
79
- else:
80
- setattr(data, key, val)
81
- return data
82
-
83
-
84
- def get_key(data, key, default):
85
- if isinstance(data, Sequence):
86
- try:
87
- return data[int(key)]
88
- except IndexError:
89
- return default
90
- return pointed_getter(data, key, default)
91
-
92
-
93
- def pointed_setter(data, path, value):
94
- path = path.split(".")
95
- key = path.pop(0)
96
- if not len(path):
97
- return set_key(data, key, value)
98
- default = [] if path[0].isdigit() else {}
99
- return set_key(
100
- data, key, pointed_setter(get_key(data, key, default), ".".join(path), value)
101
- )
102
-
103
-
104
- def map_method_aliases(new_cls):
105
- method_aliases = {
106
- "validate_python": "model_validate",
107
- "validate_json": "model_validate_json",
108
- # "dump_python": "model_dump",
109
- # "dump_json": "model_dump_json",
110
- "json_schema": "model_json_schema",
111
- }
112
- for alias_name, target_name in method_aliases.items():
113
- setattr(new_cls, alias_name, getattr(new_cls, target_name))
114
- return new_cls