querymodelling 0.0.7__tar.gz → 0.0.9__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 (24) hide show
  1. {querymodelling-0.0.7/querymodelling.egg-info → querymodelling-0.0.9}/PKG-INFO +1 -1
  2. {querymodelling-0.0.7 → querymodelling-0.0.9}/pyproject.toml +1 -1
  3. {querymodelling-0.0.7 → querymodelling-0.0.9}/querymodelling/__version__.py +1 -1
  4. querymodelling-0.0.9/querymodelling/redis_om.py +154 -0
  5. {querymodelling-0.0.7 → querymodelling-0.0.9/querymodelling.egg-info}/PKG-INFO +1 -1
  6. {querymodelling-0.0.7 → querymodelling-0.0.9}/querymodelling.egg-info/SOURCES.txt +1 -0
  7. {querymodelling-0.0.7 → querymodelling-0.0.9}/AUTHORS.rst +0 -0
  8. {querymodelling-0.0.7 → querymodelling-0.0.9}/LICENSE +0 -0
  9. {querymodelling-0.0.7 → querymodelling-0.0.9}/README.md +0 -0
  10. {querymodelling-0.0.7 → querymodelling-0.0.9}/querymodelling/__helper__.py +0 -0
  11. {querymodelling-0.0.7 → querymodelling-0.0.9}/querymodelling/__init__.py +0 -0
  12. {querymodelling-0.0.7 → querymodelling-0.0.9}/querymodelling/base.py +0 -0
  13. {querymodelling-0.0.7 → querymodelling-0.0.9}/querymodelling/fields.py +0 -0
  14. {querymodelling-0.0.7 → querymodelling-0.0.9}/querymodelling/model.py +0 -0
  15. {querymodelling-0.0.7 → querymodelling-0.0.9}/querymodelling/pydantic.py +0 -0
  16. {querymodelling-0.0.7 → querymodelling-0.0.9}/querymodelling/sql.py +0 -0
  17. {querymodelling-0.0.7 → querymodelling-0.0.9}/querymodelling.egg-info/dependency_links.txt +0 -0
  18. {querymodelling-0.0.7 → querymodelling-0.0.9}/querymodelling.egg-info/requires.txt +0 -0
  19. {querymodelling-0.0.7 → querymodelling-0.0.9}/querymodelling.egg-info/top_level.txt +0 -0
  20. {querymodelling-0.0.7 → querymodelling-0.0.9}/setup.cfg +0 -0
  21. {querymodelling-0.0.7 → querymodelling-0.0.9}/setup.py +0 -0
  22. {querymodelling-0.0.7 → querymodelling-0.0.9}/tests/__init__.py +0 -0
  23. {querymodelling-0.0.7 → querymodelling-0.0.9}/tests/__main__.py +0 -0
  24. {querymodelling-0.0.7 → querymodelling-0.0.9}/tests/basic_test.py +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.2
2
2
  Name: querymodelling
3
- Version: 0.0.7
3
+ Version: 0.0.9
4
4
  Summary: build consistent api query models for fastapi
5
5
  Author: George Haddad
6
6
  Author-email: George Haddad <georgeh87@live.de>
@@ -11,7 +11,7 @@ testpaths = ["tests"]
11
11
 
12
12
  [project]
13
13
  name = "querymodelling"
14
- version = "0.0.7"
14
+ version = "0.0.9"
15
15
  description = "build consistent api query models for fastapi"
16
16
  readme = "README.md"
17
17
  requires-python = ">=3.11"
@@ -1,7 +1,7 @@
1
1
  __title__ = "querymodelling"
2
2
  __description__ = ""
3
3
  __url__ = "https://querymodelling.readthedocs.io"
4
- __version__ = "0.0.7"
4
+ __version__ = "0.0.9"
5
5
  __build__ = 0x023100
6
6
  __author__ = "George Haddad"
7
7
  __author_email__ = "georgeh87@live.de"
@@ -0,0 +1,154 @@
1
+ from datetime import datetime
2
+ from typing import TypeVar, Sequence, Type, Callable, ParamSpec
3
+
4
+ from .__helper__ import is_enum
5
+ from .base import get_functions, DefaultSort
6
+ from .fields import QueryField, SortField
7
+ from .model import PageQuery
8
+
9
+
10
+ T = TypeVar("T")
11
+ PK = ParamSpec("PK")
12
+ Q = TypeVar("Q", bound=PageQuery)
13
+
14
+ def sortable_by(field, field_name):
15
+ def wrapper(order: DefaultSort):
16
+ if order == "desc":
17
+ return f"-{field_name}"
18
+ if order == "asc":
19
+ return field_name
20
+ return wrapper
21
+
22
+ def create_statement(
23
+ query: Q,
24
+ t: Type[T]
25
+ ):
26
+ search_clause = get_functions(query, "query")
27
+ order_clause = get_functions(query, "sort")
28
+ statement = t.find(*search_clause)
29
+ if order_clause:
30
+ for order_clause in order_clause:
31
+ statement = statement.sort_by(order_clause)
32
+ return statement
33
+
34
+ def retrieve_paged_entries(
35
+ query: Q,
36
+ t: Type[T],
37
+ ) -> tuple[int, Sequence[T]]:
38
+ statement = create_statement(query, t)
39
+
40
+ statement = statement.copy(
41
+ offset=query.page * query.size, limit=query.size)
42
+
43
+ entries = statement.execute(exhaust_results=False)
44
+ total_elements = statement.count()
45
+
46
+ return total_elements, entries
47
+
48
+ def retrieve_entries(
49
+ query: Q,
50
+ t: Type[T]
51
+ ) -> tuple[int, Sequence[T]]:
52
+ statement = create_statement(query, t)
53
+ return statement.all()
54
+
55
+ def create_query_fields(
56
+ base_field: any,
57
+ field_name: str,
58
+ annotation: any,
59
+ operator_mapping: dict[str, Callable],
60
+ json_schema_extra: dict
61
+ ):
62
+ for operator, operator_function in operator_mapping.items():
63
+ if operator is None:
64
+ name = field_name
65
+ else:
66
+ name = f"{field_name}_{operator}"
67
+ yield (
68
+ name,
69
+ QueryField(base_field)(
70
+ operator_function,
71
+ default=None,
72
+ json_schema_extra=json_schema_extra | {
73
+ "query.operator": operator
74
+ }
75
+ ),
76
+ annotation
77
+ )
78
+
79
+ def create_callback(
80
+ base_field,
81
+ copy_field_properties: list[str] = None,
82
+ schema_extra: dict = None
83
+ ):
84
+ def auto_create_callback(
85
+ source_type: type,
86
+ field_name: str,
87
+ field,
88
+ field_info,
89
+ annotation
90
+ ):
91
+ if copy_field_properties is None and schema_extra is None:
92
+ json_schema_extra = field_info.json_schema_extra
93
+ json_schema_extra = schema_extra or {}
94
+ if copy_field_properties is not None:
95
+ for property_name in copy_field_properties:
96
+ json_schema_extra[property_name] = field_info[
97
+ property_name]
98
+
99
+ json_schema_extra = json_schema_extra | {
100
+ "query.backend": "redis",
101
+ "query.field": field_name
102
+ }
103
+
104
+ if annotation == str:
105
+ operator_mapping = {
106
+ None: lambda value: field == value,
107
+ "not": lambda value: field != value,
108
+ "startswith": lambda value: field.startswith(value),
109
+ "endswith": lambda value: field.endswith(value),
110
+ "contains": lambda value: field % value
111
+ }
112
+ yield from create_query_fields(
113
+ base_field,
114
+ field_name,
115
+ annotation,
116
+ operator_mapping,
117
+ json_schema_extra
118
+ )
119
+ elif annotation in (datetime, int):
120
+ operator_mapping = {
121
+ None: lambda value: field == value,
122
+ "from": lambda value: field >= value,
123
+ "to": lambda value: field <= value,
124
+ "not": lambda value: field != value
125
+ }
126
+ yield from create_query_fields(
127
+ base_field,
128
+ field_name,
129
+ annotation,
130
+ operator_mapping,
131
+ json_schema_extra
132
+ )
133
+ elif is_enum(annotation):
134
+ operator_mapping = {
135
+ None: lambda value: field == value,
136
+ "not": lambda value: field != value
137
+ }
138
+ yield from create_query_fields(
139
+ base_field,
140
+ field_name,
141
+ annotation,
142
+ operator_mapping,
143
+ json_schema_extra
144
+ )
145
+ yield (
146
+ f"sort_{field_name}",
147
+ SortField(base_field)(
148
+ sortable_by(source_type.__dict__[field_name], field_name),
149
+ default=None,
150
+ json_schema_extra=json_schema_extra
151
+ ),
152
+ DefaultSort
153
+ )
154
+ return auto_create_callback
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.2
2
2
  Name: querymodelling
3
- Version: 0.0.7
3
+ Version: 0.0.9
4
4
  Summary: build consistent api query models for fastapi
5
5
  Author: George Haddad
6
6
  Author-email: George Haddad <georgeh87@live.de>
@@ -10,6 +10,7 @@ querymodelling/base.py
10
10
  querymodelling/fields.py
11
11
  querymodelling/model.py
12
12
  querymodelling/pydantic.py
13
+ querymodelling/redis_om.py
13
14
  querymodelling/sql.py
14
15
  querymodelling.egg-info/PKG-INFO
15
16
  querymodelling.egg-info/SOURCES.txt
File without changes
File without changes
File without changes
File without changes