statezero 0.1.0b3__py3-none-any.whl → 0.1.0b5__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.
Potentially problematic release.
This version of statezero might be problematic. Click here for more details.
- statezero/adaptors/django/orm.py +224 -174
- statezero/adaptors/django/serializers.py +45 -26
- statezero/core/ast_parser.py +315 -175
- statezero/core/hook_checks.py +86 -0
- statezero/core/interfaces.py +193 -69
- statezero/core/process_request.py +1 -1
- {statezero-0.1.0b3.dist-info → statezero-0.1.0b5.dist-info}/METADATA +1 -1
- {statezero-0.1.0b3.dist-info → statezero-0.1.0b5.dist-info}/RECORD +11 -10
- {statezero-0.1.0b3.dist-info → statezero-0.1.0b5.dist-info}/WHEEL +0 -0
- {statezero-0.1.0b3.dist-info → statezero-0.1.0b5.dist-info}/licenses/license.md +0 -0
- {statezero-0.1.0b3.dist-info → statezero-0.1.0b5.dist-info}/top_level.txt +0 -0
|
@@ -0,0 +1,86 @@
|
|
|
1
|
+
import warnings
|
|
2
|
+
from django.conf import settings
|
|
3
|
+
from typing import Any, Dict, Set, Type
|
|
4
|
+
|
|
5
|
+
def _check_pre_hook_result(
|
|
6
|
+
original_data: Dict, result_data: Any, model: Type, serializer_fields: Set[str]
|
|
7
|
+
):
|
|
8
|
+
"""Check pre-hook result and warn about common issues in DEBUG mode only."""
|
|
9
|
+
if not getattr(settings, "DEBUG", False):
|
|
10
|
+
return result_data or original_data
|
|
11
|
+
|
|
12
|
+
model_name = model.__name__
|
|
13
|
+
|
|
14
|
+
# Warning 1: Hook returned None
|
|
15
|
+
if result_data is None:
|
|
16
|
+
warnings.warn(
|
|
17
|
+
f"Pre-hook for {model_name} returned None (should return dict). HINT: If you want to skip changes, return the original data.",
|
|
18
|
+
stacklevel=5,
|
|
19
|
+
)
|
|
20
|
+
return original_data
|
|
21
|
+
|
|
22
|
+
if not isinstance(result_data, dict):
|
|
23
|
+
warnings.warn(
|
|
24
|
+
f"Pre-hook for {model_name} returned {type(result_data).__name__} (should return dict). HINT: If you want to skip changes, return the original data.",
|
|
25
|
+
stacklevel=5,
|
|
26
|
+
)
|
|
27
|
+
return original_data
|
|
28
|
+
|
|
29
|
+
# Warning 2: Added fields not in serializer
|
|
30
|
+
added_keys = set(result_data.keys()) - set(original_data.keys())
|
|
31
|
+
missing_fields = added_keys - serializer_fields
|
|
32
|
+
if missing_fields:
|
|
33
|
+
warnings.warn(
|
|
34
|
+
f"Pre-hook for {model_name} added unavailable fields {missing_fields}. HINT: Add the field to permission.editable_fields() or use post-hook.",
|
|
35
|
+
stacklevel=5,
|
|
36
|
+
)
|
|
37
|
+
|
|
38
|
+
# Warning 3: Removed fields that were in original data
|
|
39
|
+
removed_keys = set(original_data.keys()) - set(result_data.keys())
|
|
40
|
+
if removed_keys:
|
|
41
|
+
warnings.warn(
|
|
42
|
+
f"Pre-hook for {model_name} removed fields {removed_keys} that were in original data. This might be intentional, or it could be caused by a hook not returning the full input data.",
|
|
43
|
+
stacklevel=5,
|
|
44
|
+
)
|
|
45
|
+
|
|
46
|
+
return result_data
|
|
47
|
+
|
|
48
|
+
def _check_post_hook_result(original_data: Dict, result_data: Any, model: Type):
|
|
49
|
+
"""Check post-hook result and warn about common issues in DEBUG mode only."""
|
|
50
|
+
if not getattr(settings, "DEBUG", False):
|
|
51
|
+
return result_data or original_data
|
|
52
|
+
|
|
53
|
+
model_name = model.__name__
|
|
54
|
+
|
|
55
|
+
# Warning 1: Hook returned None
|
|
56
|
+
if result_data is None:
|
|
57
|
+
warnings.warn(
|
|
58
|
+
f"Post-hook for {model_name} returned None (should return dict). HINT: Return the validated_data dict.",
|
|
59
|
+
stacklevel=5,
|
|
60
|
+
)
|
|
61
|
+
return original_data
|
|
62
|
+
|
|
63
|
+
if not isinstance(result_data, dict):
|
|
64
|
+
warnings.warn(
|
|
65
|
+
f"Post-hook for {model_name} returned {type(result_data).__name__} (should return dict). HINT: Return the validated_data dict.",
|
|
66
|
+
stacklevel=5,
|
|
67
|
+
)
|
|
68
|
+
return original_data
|
|
69
|
+
|
|
70
|
+
# Warning 2: Removed validated fields (more serious than pre-hook)
|
|
71
|
+
removed_keys = set(original_data.keys()) - set(result_data.keys())
|
|
72
|
+
if removed_keys:
|
|
73
|
+
warnings.warn(
|
|
74
|
+
f"Post-hook for {model_name} removed validated fields {removed_keys}. These fields won't be saved.",
|
|
75
|
+
stacklevel=5,
|
|
76
|
+
)
|
|
77
|
+
|
|
78
|
+
# Warning 3: Added fields that weren't validated
|
|
79
|
+
added_keys = set(result_data.keys()) - set(original_data.keys())
|
|
80
|
+
if added_keys:
|
|
81
|
+
warnings.warn(
|
|
82
|
+
f"Post-hook for {model_name} added unvalidated fields {added_keys}. These bypassed serializer validation.",
|
|
83
|
+
stacklevel=5,
|
|
84
|
+
)
|
|
85
|
+
|
|
86
|
+
return result_data
|
statezero/core/interfaces.py
CHANGED
|
@@ -1,104 +1,126 @@
|
|
|
1
1
|
from __future__ import annotations
|
|
2
2
|
|
|
3
3
|
from abc import ABC, abstractmethod
|
|
4
|
-
from typing import
|
|
4
|
+
from typing import (
|
|
5
|
+
Any,
|
|
6
|
+
Callable,
|
|
7
|
+
Dict,
|
|
8
|
+
List,
|
|
9
|
+
Optional,
|
|
10
|
+
Set,
|
|
11
|
+
Tuple,
|
|
12
|
+
Type,
|
|
13
|
+
Union,
|
|
14
|
+
Literal,
|
|
15
|
+
Protocol,
|
|
16
|
+
)
|
|
5
17
|
|
|
6
18
|
from statezero.core.classes import ModelSchemaMetadata, SchemaFieldMetadata
|
|
7
|
-
from statezero.core.types import (
|
|
19
|
+
from statezero.core.types import (
|
|
20
|
+
ActionType,
|
|
21
|
+
ORMField,
|
|
22
|
+
ORMModel,
|
|
23
|
+
ORMQuerySet,
|
|
24
|
+
RequestType,
|
|
25
|
+
)
|
|
26
|
+
|
|
8
27
|
|
|
9
28
|
class AbstractORMProvider(ABC):
|
|
10
29
|
"""
|
|
11
30
|
A merged ORM engine interface that combines both query building (filtering,
|
|
12
31
|
ordering, aggregation, etc.) and ORM provider responsibilities (queryset assembly,
|
|
13
32
|
event signal registration, model graph construction, etc.).
|
|
33
|
+
|
|
34
|
+
UPDATED: All query manipulation methods now take queryset parameters and return
|
|
35
|
+
new querysets instead of mutating internal state.
|
|
14
36
|
"""
|
|
15
37
|
|
|
16
|
-
# === Query Engine Methods ===
|
|
38
|
+
# === Query Engine Methods (UPDATED: Now stateless) ===
|
|
17
39
|
|
|
18
40
|
@abstractmethod
|
|
19
|
-
def get_fields(self) -> Set[str]:
|
|
41
|
+
def get_fields(self, model: ORMModel) -> Set[str]:
|
|
20
42
|
"""
|
|
21
43
|
Get all of the model fields - doesn't apply permissions check.
|
|
22
44
|
"""
|
|
23
45
|
pass
|
|
24
46
|
|
|
25
47
|
@abstractmethod
|
|
26
|
-
def filter_node(self, node: Dict[str, Any]) ->
|
|
48
|
+
def filter_node(self, queryset: ORMQuerySet, node: Dict[str, Any]) -> ORMQuerySet:
|
|
27
49
|
"""
|
|
28
|
-
Apply filter/and/or/not logic to the
|
|
50
|
+
Apply filter/and/or/not logic to the queryset and return new queryset.
|
|
29
51
|
"""
|
|
30
52
|
pass
|
|
31
53
|
|
|
32
54
|
@abstractmethod
|
|
33
|
-
def search_node(
|
|
55
|
+
def search_node(
|
|
56
|
+
self, queryset: ORMQuerySet, search_query: str, search_fields: Set[str]
|
|
57
|
+
) -> ORMQuerySet:
|
|
34
58
|
"""
|
|
35
|
-
Apply search to the
|
|
59
|
+
Apply search to the queryset and return new queryset.
|
|
36
60
|
"""
|
|
37
61
|
pass
|
|
38
62
|
|
|
39
63
|
@abstractmethod
|
|
40
|
-
def
|
|
41
|
-
"""Create a new record."""
|
|
42
|
-
pass
|
|
43
|
-
|
|
44
|
-
@abstractmethod
|
|
45
|
-
def update(self, node: Dict[str, Any]) -> int:
|
|
64
|
+
def exclude_node(self, queryset: ORMQuerySet, node: Dict[str, Any]) -> ORMQuerySet:
|
|
46
65
|
"""
|
|
47
|
-
|
|
48
|
-
Returns the number of rows updated.
|
|
66
|
+
Apply exclude logic to the queryset and return new queryset.
|
|
49
67
|
"""
|
|
50
68
|
pass
|
|
51
69
|
|
|
52
70
|
@abstractmethod
|
|
53
|
-
def
|
|
71
|
+
def order_by(self, queryset: ORMQuerySet, order_list: List[str]) -> ORMQuerySet:
|
|
54
72
|
"""
|
|
55
|
-
|
|
56
|
-
Returns the number of rows deleted.
|
|
73
|
+
Order the queryset based on a list of fields and return new queryset.
|
|
57
74
|
"""
|
|
58
75
|
pass
|
|
59
76
|
|
|
60
77
|
@abstractmethod
|
|
61
|
-
def
|
|
78
|
+
def select_related(
|
|
79
|
+
self, queryset: ORMQuerySet, related_fields: List[str]
|
|
80
|
+
) -> ORMQuerySet:
|
|
62
81
|
"""
|
|
63
|
-
|
|
82
|
+
Optimize the queryset by eager loading the given related fields and return new queryset.
|
|
64
83
|
"""
|
|
65
84
|
pass
|
|
66
85
|
|
|
67
86
|
@abstractmethod
|
|
68
|
-
def
|
|
87
|
+
def prefetch_related(
|
|
88
|
+
self, queryset: ORMQuerySet, related_fields: List[str]
|
|
89
|
+
) -> ORMQuerySet:
|
|
69
90
|
"""
|
|
70
|
-
|
|
71
|
-
Returns a tuple of (instance, created_flag).
|
|
91
|
+
Optimize the queryset by prefetching the given related fields and return new queryset.
|
|
72
92
|
"""
|
|
73
93
|
pass
|
|
74
94
|
|
|
75
95
|
@abstractmethod
|
|
76
|
-
def
|
|
96
|
+
def select_fields(self, queryset: ORMQuerySet, fields: List[str]) -> ORMQuerySet:
|
|
77
97
|
"""
|
|
78
|
-
|
|
79
|
-
Returns a tuple of (instance, created_flag).
|
|
98
|
+
Select only specific fields from the queryset and return new queryset.
|
|
80
99
|
"""
|
|
81
100
|
pass
|
|
82
101
|
|
|
83
102
|
@abstractmethod
|
|
84
|
-
def
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
103
|
+
def fetch_list(
|
|
104
|
+
self,
|
|
105
|
+
queryset: ORMQuerySet,
|
|
106
|
+
offset: Optional[int] = None,
|
|
107
|
+
limit: Optional[int] = None,
|
|
108
|
+
req: Optional[RequestType] = None,
|
|
109
|
+
permissions: Optional[List[Type]] = None,
|
|
110
|
+
) -> ORMQuerySet:
|
|
111
|
+
"""
|
|
112
|
+
Return a sliced queryset based on pagination with permission checks.
|
|
113
|
+
"""
|
|
91
114
|
pass
|
|
92
115
|
|
|
93
|
-
|
|
94
|
-
def exists(self) -> bool:
|
|
95
|
-
"""Return True if the current query has any results; otherwise False."""
|
|
96
|
-
pass
|
|
116
|
+
# === Aggregate Methods (UPDATED: Take queryset parameter) ===
|
|
97
117
|
|
|
98
118
|
@abstractmethod
|
|
99
|
-
def aggregate(
|
|
119
|
+
def aggregate(
|
|
120
|
+
self, queryset: ORMQuerySet, agg_list: List[Dict[str, Any]]
|
|
121
|
+
) -> Dict[str, Any]:
|
|
100
122
|
"""
|
|
101
|
-
Aggregate the
|
|
123
|
+
Aggregate the queryset based on the provided functions.
|
|
102
124
|
Example:
|
|
103
125
|
[
|
|
104
126
|
{'function': 'count', 'field': 'id', 'alias': 'id_count'},
|
|
@@ -108,60 +130,155 @@ class AbstractORMProvider(ABC):
|
|
|
108
130
|
pass
|
|
109
131
|
|
|
110
132
|
@abstractmethod
|
|
111
|
-
def count(self, field: str) -> int:
|
|
133
|
+
def count(self, queryset: ORMQuerySet, field: str) -> int:
|
|
112
134
|
"""Count the number of records for the given field."""
|
|
113
135
|
pass
|
|
114
136
|
|
|
115
137
|
@abstractmethod
|
|
116
|
-
def sum(self, field: str) -> Any:
|
|
138
|
+
def sum(self, queryset: ORMQuerySet, field: str) -> Any:
|
|
117
139
|
"""Sum the values of the given field."""
|
|
118
140
|
pass
|
|
119
141
|
|
|
120
142
|
@abstractmethod
|
|
121
|
-
def avg(self, field: str) -> Any:
|
|
143
|
+
def avg(self, queryset: ORMQuerySet, field: str) -> Any:
|
|
122
144
|
"""Calculate the average of the given field."""
|
|
123
145
|
pass
|
|
124
146
|
|
|
125
147
|
@abstractmethod
|
|
126
|
-
def min(self, field: str) -> Any:
|
|
148
|
+
def min(self, queryset: ORMQuerySet, field: str) -> Any:
|
|
127
149
|
"""Find the minimum value for the given field."""
|
|
128
150
|
pass
|
|
129
151
|
|
|
130
152
|
@abstractmethod
|
|
131
|
-
def max(self, field: str) -> Any:
|
|
153
|
+
def max(self, queryset: ORMQuerySet, field: str) -> Any:
|
|
132
154
|
"""Find the maximum value for the given field."""
|
|
133
155
|
pass
|
|
134
156
|
|
|
135
157
|
@abstractmethod
|
|
136
|
-
def
|
|
158
|
+
def first(self, queryset: ORMQuerySet) -> Any:
|
|
159
|
+
"""Return the first record from the queryset."""
|
|
160
|
+
pass
|
|
161
|
+
|
|
162
|
+
@abstractmethod
|
|
163
|
+
def last(self, queryset: ORMQuerySet) -> Any:
|
|
164
|
+
"""Return the last record from the queryset."""
|
|
165
|
+
pass
|
|
166
|
+
|
|
167
|
+
@abstractmethod
|
|
168
|
+
def exists(self, queryset: ORMQuerySet) -> bool:
|
|
169
|
+
"""Return True if the queryset has any results; otherwise False."""
|
|
170
|
+
pass
|
|
171
|
+
|
|
172
|
+
# === CRUD Methods (UPDATED: Take model or queryset parameters explicitly) ===
|
|
173
|
+
|
|
174
|
+
@abstractmethod
|
|
175
|
+
def create(
|
|
176
|
+
self, model: Type[ORMModel], data: Dict[str, Any], *args, **kwargs
|
|
177
|
+
) -> Any:
|
|
178
|
+
"""Create a new record using the model class."""
|
|
179
|
+
pass
|
|
180
|
+
|
|
181
|
+
@abstractmethod
|
|
182
|
+
def update(
|
|
183
|
+
self,
|
|
184
|
+
queryset: ORMQuerySet,
|
|
185
|
+
node: Dict[str, Any],
|
|
186
|
+
req: RequestType,
|
|
187
|
+
permissions: List[Type],
|
|
188
|
+
readable_fields: Optional[Set[str]] = None,
|
|
189
|
+
) -> Tuple[int, List[Any]]:
|
|
137
190
|
"""
|
|
138
|
-
|
|
139
|
-
|
|
191
|
+
Update records in the queryset.
|
|
192
|
+
Returns tuple of (number of rows updated, updated instances).
|
|
140
193
|
"""
|
|
141
194
|
pass
|
|
142
195
|
|
|
143
196
|
@abstractmethod
|
|
144
|
-
def
|
|
197
|
+
def delete(
|
|
198
|
+
self,
|
|
199
|
+
queryset: ORMQuerySet,
|
|
200
|
+
node: Dict[str, Any],
|
|
201
|
+
req: RequestType,
|
|
202
|
+
permissions: List[Type],
|
|
203
|
+
) -> Tuple[int, Any]:
|
|
145
204
|
"""
|
|
146
|
-
|
|
205
|
+
Delete records in the queryset.
|
|
206
|
+
Returns tuple of (number of rows deleted, deleted instance data).
|
|
147
207
|
"""
|
|
148
208
|
pass
|
|
149
209
|
|
|
150
210
|
@abstractmethod
|
|
151
|
-
def
|
|
211
|
+
def get(
|
|
212
|
+
self,
|
|
213
|
+
queryset: ORMQuerySet,
|
|
214
|
+
node: Dict[str, Any],
|
|
215
|
+
req: RequestType,
|
|
216
|
+
permissions: List[Type],
|
|
217
|
+
) -> Any:
|
|
152
218
|
"""
|
|
153
|
-
|
|
219
|
+
Retrieve a single record from the queryset.
|
|
220
|
+
Raises an error if multiple or none are found.
|
|
154
221
|
"""
|
|
155
222
|
pass
|
|
156
223
|
|
|
157
224
|
@abstractmethod
|
|
158
|
-
def
|
|
225
|
+
def get_or_create(
|
|
226
|
+
self,
|
|
227
|
+
queryset: ORMQuerySet,
|
|
228
|
+
node: Dict[str, Any],
|
|
229
|
+
serializer: Any,
|
|
230
|
+
req: RequestType,
|
|
231
|
+
permissions: List[Type],
|
|
232
|
+
create_fields_map: Dict[str, Set[str]],
|
|
233
|
+
) -> Tuple[Any, bool]:
|
|
159
234
|
"""
|
|
160
|
-
|
|
235
|
+
Retrieve a record if it exists, otherwise create it.
|
|
236
|
+
Returns a tuple of (instance, created_flag).
|
|
161
237
|
"""
|
|
162
238
|
pass
|
|
163
239
|
|
|
164
|
-
|
|
240
|
+
@abstractmethod
|
|
241
|
+
def update_or_create(
|
|
242
|
+
self,
|
|
243
|
+
queryset: ORMQuerySet,
|
|
244
|
+
node: Dict[str, Any],
|
|
245
|
+
req: RequestType,
|
|
246
|
+
serializer: Any,
|
|
247
|
+
permissions: List[Type],
|
|
248
|
+
update_fields_map: Dict[str, Set[str]],
|
|
249
|
+
create_fields_map: Dict[str, Set[str]],
|
|
250
|
+
) -> Tuple[Any, bool]:
|
|
251
|
+
"""
|
|
252
|
+
Update a record if it exists or create it if it doesn't.
|
|
253
|
+
Returns a tuple of (instance, created_flag).
|
|
254
|
+
"""
|
|
255
|
+
pass
|
|
256
|
+
|
|
257
|
+
@abstractmethod
|
|
258
|
+
def update_instance(
|
|
259
|
+
self,
|
|
260
|
+
model: Type[ORMModel],
|
|
261
|
+
ast: Dict[str, Any],
|
|
262
|
+
req: RequestType,
|
|
263
|
+
permissions: List[Type],
|
|
264
|
+
serializer: Any,
|
|
265
|
+
fields_map: Dict[str, Set[str]],
|
|
266
|
+
) -> Any:
|
|
267
|
+
"""Update a single model instance by filter."""
|
|
268
|
+
pass
|
|
269
|
+
|
|
270
|
+
@abstractmethod
|
|
271
|
+
def delete_instance(
|
|
272
|
+
self,
|
|
273
|
+
model: Type[ORMModel],
|
|
274
|
+
ast: Dict[str, Any],
|
|
275
|
+
req: RequestType,
|
|
276
|
+
permissions: List[Type],
|
|
277
|
+
) -> int:
|
|
278
|
+
"""Delete a single model instance by filter."""
|
|
279
|
+
pass
|
|
280
|
+
|
|
281
|
+
# === ORM Provider Methods (Unchanged - these are utility methods) ===
|
|
165
282
|
|
|
166
283
|
@abstractmethod
|
|
167
284
|
def get_queryset(
|
|
@@ -205,29 +322,32 @@ class AbstractORMProvider(ABC):
|
|
|
205
322
|
pass
|
|
206
323
|
|
|
207
324
|
@abstractmethod
|
|
208
|
-
def get_user(self, request: RequestType):
|
|
325
|
+
def get_user(self, request: RequestType): # returns User
|
|
209
326
|
"""
|
|
210
327
|
Get the request user.
|
|
211
328
|
"""
|
|
212
329
|
pass
|
|
213
330
|
|
|
214
331
|
@abstractmethod
|
|
215
|
-
def build_model_graph(self, model: ORMModel) ->
|
|
332
|
+
def build_model_graph(self, model: ORMModel) -> Any: # type:ignore
|
|
216
333
|
"""
|
|
217
334
|
Construct a graph representation of model relationships.
|
|
218
335
|
"""
|
|
219
336
|
pass
|
|
220
337
|
|
|
221
338
|
|
|
339
|
+
# === Other Abstract Classes (Unchanged) ===
|
|
340
|
+
|
|
341
|
+
|
|
222
342
|
class AbstractCustomQueryset(ABC):
|
|
223
343
|
@abstractmethod
|
|
224
344
|
def get_queryset(self, request: Optional[RequestType] = None) -> Any:
|
|
225
345
|
"""
|
|
226
346
|
Return a custom queryset (e.g. a custom SQLAlchemy Query or Django QuerySet).
|
|
227
|
-
|
|
347
|
+
|
|
228
348
|
Args:
|
|
229
349
|
request: The current request object, which may contain user information
|
|
230
|
-
|
|
350
|
+
|
|
231
351
|
Returns:
|
|
232
352
|
A custom queryset
|
|
233
353
|
"""
|
|
@@ -302,7 +422,7 @@ class AbstractEventEmitter(ABC):
|
|
|
302
422
|
) -> None:
|
|
303
423
|
"""
|
|
304
424
|
Emit an event to the specified namespace with the given event type and data.
|
|
305
|
-
|
|
425
|
+
|
|
306
426
|
Parameters:
|
|
307
427
|
-----------
|
|
308
428
|
namespace: str
|
|
@@ -406,24 +526,31 @@ class AbstractPermission(ABC):
|
|
|
406
526
|
"""
|
|
407
527
|
pass
|
|
408
528
|
|
|
529
|
+
|
|
409
530
|
class AbstractSearchProvider(ABC):
|
|
410
531
|
"""Base class for search providers in StateZero."""
|
|
411
|
-
|
|
532
|
+
|
|
412
533
|
@abstractmethod
|
|
413
|
-
def search(
|
|
534
|
+
def search(
|
|
535
|
+
self,
|
|
536
|
+
queryset: ORMQuerySet,
|
|
537
|
+
query: str,
|
|
538
|
+
search_fields: Union[Set[str], Literal["__all__"]],
|
|
539
|
+
) -> ORMQuerySet:
|
|
414
540
|
"""
|
|
415
541
|
Apply search filtering to a queryset.
|
|
416
|
-
|
|
542
|
+
|
|
417
543
|
Args:
|
|
418
544
|
queryset: Django queryset
|
|
419
545
|
query: The search query string
|
|
420
546
|
search_fields: Set of field names to search in
|
|
421
|
-
|
|
547
|
+
|
|
422
548
|
Returns:
|
|
423
549
|
Filtered queryset with search applied
|
|
424
550
|
"""
|
|
425
551
|
pass
|
|
426
552
|
|
|
553
|
+
|
|
427
554
|
class AbstractQueryOptimizer(ABC):
|
|
428
555
|
"""
|
|
429
556
|
Abstract Base Class for query optimizers.
|
|
@@ -436,7 +563,7 @@ class AbstractQueryOptimizer(ABC):
|
|
|
436
563
|
self,
|
|
437
564
|
depth: Optional[int] = None,
|
|
438
565
|
fields_per_model: Optional[Dict[str, Set[str]]] = None,
|
|
439
|
-
get_model_name_func: Optional[Callable[[Type[ORMModel]], str]] = None
|
|
566
|
+
get_model_name_func: Optional[Callable[[Type[ORMModel]], str]] = None,
|
|
440
567
|
):
|
|
441
568
|
"""
|
|
442
569
|
Initializes the optimizer with common configuration potentially
|
|
@@ -462,10 +589,7 @@ class AbstractQueryOptimizer(ABC):
|
|
|
462
589
|
|
|
463
590
|
@abstractmethod
|
|
464
591
|
def optimize(
|
|
465
|
-
self,
|
|
466
|
-
queryset: Any,
|
|
467
|
-
fields: Optional[List[str]] = None,
|
|
468
|
-
**kwargs: Any
|
|
592
|
+
self, queryset: Any, fields: Optional[List[str]] = None, **kwargs: Any
|
|
469
593
|
) -> Any:
|
|
470
594
|
"""
|
|
471
595
|
Optimizes the given query object.
|
|
@@ -170,13 +170,13 @@ class RequestProcessor:
|
|
|
170
170
|
)
|
|
171
171
|
|
|
172
172
|
# Create and use the AST parser directly, instead of delegating to ORM provider
|
|
173
|
-
self.orm_provider.set_queryset(base_queryset)
|
|
174
173
|
parser = ASTParser(
|
|
175
174
|
engine=self.orm_provider,
|
|
176
175
|
serializer=self.data_serializer,
|
|
177
176
|
model=model,
|
|
178
177
|
config=self.config,
|
|
179
178
|
registry=self.registry,
|
|
179
|
+
base_queryset=base_queryset, # Pass the queryset here
|
|
180
180
|
serializer_options=serializer_options or {},
|
|
181
181
|
request=req,
|
|
182
182
|
)
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: statezero
|
|
3
|
-
Version: 0.1.
|
|
3
|
+
Version: 0.1.0b5
|
|
4
4
|
Summary: Connect your Python backend to a modern JavaScript SPA frontend with 90% less complexity.
|
|
5
5
|
Author-email: Robert <robert.herring@statezero.dev>
|
|
6
6
|
Project-URL: homepage, https://www.statezero.dev
|
|
@@ -9,11 +9,11 @@ statezero/adaptors/django/exception_handler.py,sha256=cQF1Fm5IjH91ydB54TK9sqXiAO
|
|
|
9
9
|
statezero/adaptors/django/f_handler.py,sha256=yvITFj9UAnz8-r-aLEcWoz48tBhZ08-VMq9Fsm2uiN8,12305
|
|
10
10
|
statezero/adaptors/django/helpers.py,sha256=0Dyq5vboDuTUaH-KpS3oVDjastA9yv6xI6XpBuvRM3I,5974
|
|
11
11
|
statezero/adaptors/django/middleware.py,sha256=YVr8fkqCk51xJQM-ovtrUiB9Kt9H81cLd9xv4cM9YlM,410
|
|
12
|
-
statezero/adaptors/django/orm.py,sha256
|
|
12
|
+
statezero/adaptors/django/orm.py,sha256=-9tWH9hW2Ta5AipXysoWy-em7R-ybHKmPLtBX89nYQc,37118
|
|
13
13
|
statezero/adaptors/django/permissions.py,sha256=fU2c4bKK0zX2uuVB0UazZHTI-5OkiI5-BtPNcPEWmW0,9525
|
|
14
14
|
statezero/adaptors/django/query_optimizer.py,sha256=-GNqL7Xn8WP8OsLEAAxXpIszSyEwm-l6WjgdkEFzxUM,38541
|
|
15
15
|
statezero/adaptors/django/schemas.py,sha256=shq8ed9qHCnbCfYVsRxVE7V3R3GhGIKeRRj7dI3r1IU,12728
|
|
16
|
-
statezero/adaptors/django/serializers.py,sha256=
|
|
16
|
+
statezero/adaptors/django/serializers.py,sha256=YFFDu6bzoWkSEOVH5Wmc4yJ8SaOkUA6HbXXYt6djlfc,23296
|
|
17
17
|
statezero/adaptors/django/urls.py,sha256=G4LAUVG1WtPCyB_POQ3wa_VKqKCSI6p3fHZGy6GV99g,636
|
|
18
18
|
statezero/adaptors/django/views.py,sha256=ZoTocBkqv8sdxaq5bMOZpsj1zko5FDcSYP1C9m8s9Hw,13723
|
|
19
19
|
statezero/adaptors/django/extensions/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
@@ -27,7 +27,7 @@ statezero/adaptors/django/search_providers/__init__.py,sha256=47DEQpj8HBSa-_TImW
|
|
|
27
27
|
statezero/adaptors/django/search_providers/basic_search.py,sha256=5_GJ1r_B6JdIYXL6yYEYn5mik88EolSH5aZvygc_UF0,977
|
|
28
28
|
statezero/adaptors/django/search_providers/postgres_search.py,sha256=IMoHxzfi-Y3hAxPND4Xc6GatrPs1eXAqpmcfwt5Zr14,2459
|
|
29
29
|
statezero/core/__init__.py,sha256=Z6RTutAAElLMEjBFphVVmpySPdJBA55j-Uo0BtR7c5E,1040
|
|
30
|
-
statezero/core/ast_parser.py,sha256=
|
|
30
|
+
statezero/core/ast_parser.py,sha256=ezEHqVB1Afqw_GSyUs4Dh0W94xFM4aaNEaxyYMk-rr4,38756
|
|
31
31
|
statezero/core/ast_validator.py,sha256=YZAflPyba0kXWBNhd1Z_XeEk-_zUzM6MkY9zSlX1PMs,11582
|
|
32
32
|
statezero/core/classes.py,sha256=-rJ8szqGGzsFxE3TvbtYHFHFP9Kg2WP24aYi74Io338,4923
|
|
33
33
|
statezero/core/config.py,sha256=oOjcudQO0XgEZ60kwkzpcOoTi0QZARS8XWbp9gzgasg,11489
|
|
@@ -35,11 +35,12 @@ statezero/core/context_storage.py,sha256=DVx525ZMRorj41kg5K0N6pPdGkQ5_XEJcBucpH5
|
|
|
35
35
|
statezero/core/event_bus.py,sha256=2IFLBHSkLzpm1AX0MfSXSmF2X-lXK-gOoODZCtB2Jdw,6284
|
|
36
36
|
statezero/core/event_emitters.py,sha256=qjMbeUmdn4bG7WiVfqTmNdaflEea5amnTEpOn5X0J44,2046
|
|
37
37
|
statezero/core/exceptions.py,sha256=_krMHWW9qBbMXvvqFdWf85a3Kayn7XbJczfC3x3gmBI,3330
|
|
38
|
-
statezero/core/
|
|
39
|
-
statezero/core/
|
|
38
|
+
statezero/core/hook_checks.py,sha256=uqtvwRx1qGsF7Vc49elAWdOjMzhuv3RADKY1wiLvhK4,3425
|
|
39
|
+
statezero/core/interfaces.py,sha256=VCekst5esL9Yh739tW8PSedRS_s50qhEzlnJ8pwaxtU,19064
|
|
40
|
+
statezero/core/process_request.py,sha256=dwIeBEVOE8zA-oE1h65XNOGiVqFbbXA7SzTAguLNgZk,8060
|
|
40
41
|
statezero/core/types.py,sha256=K9x9AU5J6yd2AWvqRz27CeAY6UYfuQoQ7xTEwTijrmM,1982
|
|
41
|
-
statezero-0.1.
|
|
42
|
-
statezero-0.1.
|
|
43
|
-
statezero-0.1.
|
|
44
|
-
statezero-0.1.
|
|
45
|
-
statezero-0.1.
|
|
42
|
+
statezero-0.1.0b5.dist-info/licenses/license.md,sha256=0uKjybTt9K_YbEmYgf25JN292qjjJ-BPofvIZ3wdtX4,7411
|
|
43
|
+
statezero-0.1.0b5.dist-info/METADATA,sha256=cHmsrjlDYnl5F-H5HSHcgqpP13UMLfZr9M8gqoC7UZc,7152
|
|
44
|
+
statezero-0.1.0b5.dist-info/WHEEL,sha256=_zCd3N1l69ArxyTb8rzEoP9TpbYXkqRFSNOD5OuxnTs,91
|
|
45
|
+
statezero-0.1.0b5.dist-info/top_level.txt,sha256=UAuZYPKczradU1kcMQxsGjUzEW0qdgsqzhXyscrcLpw,10
|
|
46
|
+
statezero-0.1.0b5.dist-info/RECORD,,
|
|
File without changes
|
|
File without changes
|
|
File without changes
|