rb-commons 0.7.0__py3-none-any.whl → 0.7.2__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.
- rb_commons/orm/managers.py +65 -18
- {rb_commons-0.7.0.dist-info → rb_commons-0.7.2.dist-info}/METADATA +1 -1
- {rb_commons-0.7.0.dist-info → rb_commons-0.7.2.dist-info}/RECORD +5 -5
- {rb_commons-0.7.0.dist-info → rb_commons-0.7.2.dist-info}/WHEEL +0 -0
- {rb_commons-0.7.0.dist-info → rb_commons-0.7.2.dist-info}/top_level.txt +0 -0
rb_commons/orm/managers.py
CHANGED
@@ -1,8 +1,9 @@
|
|
1
1
|
from __future__ import annotations
|
2
2
|
|
3
|
+
import re
|
3
4
|
import uuid
|
4
5
|
from typing import TypeVar, Type, Generic, Optional, List, Dict, Literal, Union, Sequence, Any, Iterable
|
5
|
-
from sqlalchemy import select, delete, update, and_, func, desc, inspect, or_, asc
|
6
|
+
from sqlalchemy import select, delete, update, and_, func, desc, inspect, or_, asc, true
|
6
7
|
from sqlalchemy.exc import IntegrityError, SQLAlchemyError
|
7
8
|
from sqlalchemy.ext.asyncio import AsyncSession
|
8
9
|
from sqlalchemy.orm import declarative_base, selectinload, RelationshipProperty, Load
|
@@ -150,9 +151,13 @@ class BaseManager(Generic[ModelType]):
|
|
150
151
|
def _parse_lookup(self, lookup: str, value: Any):
|
151
152
|
parts, operator, rel_attr, col_attr = self._parse_lookup_meta(lookup)
|
152
153
|
expr = self._build_comparison(col_attr, operator, value)
|
154
|
+
|
153
155
|
if rel_attr:
|
154
|
-
|
155
|
-
|
156
|
+
if rel_attr.property.uselist:
|
157
|
+
return rel_attr.any(expr)
|
158
|
+
else:
|
159
|
+
return rel_attr.has(expr)
|
160
|
+
|
156
161
|
return expr
|
157
162
|
|
158
163
|
def _q_to_expr(self, q: Union[Q, QJSON]):
|
@@ -162,11 +167,14 @@ class BaseManager(Generic[ModelType]):
|
|
162
167
|
clauses: List[Any] = [self._parse_lookup(k, v) for k, v in q.lookups.items()]
|
163
168
|
for child in q.children:
|
164
169
|
clauses.append(self._q_to_expr(child))
|
165
|
-
|
166
|
-
|
167
|
-
|
168
|
-
|
169
|
-
|
170
|
+
|
171
|
+
if not clauses:
|
172
|
+
combined = true()
|
173
|
+
elif q._operator == "OR":
|
174
|
+
combined = or_(*clauses)
|
175
|
+
else:
|
176
|
+
combined = and_(*clauses)
|
177
|
+
|
170
178
|
return ~combined if q.negated else combined
|
171
179
|
|
172
180
|
def _parse_qjson(self, qjson: QJSON):
|
@@ -250,19 +258,58 @@ class BaseManager(Generic[ModelType]):
|
|
250
258
|
self._limit = value
|
251
259
|
return self
|
252
260
|
|
253
|
-
def _build_relation_loaders(
|
261
|
+
def _build_relation_loaders(
|
262
|
+
self,
|
263
|
+
model: Any,
|
264
|
+
relations: Sequence[str] | None = None
|
265
|
+
) -> List[Load]:
|
254
266
|
"""
|
255
|
-
|
256
|
-
|
257
|
-
|
267
|
+
Given e.g. ["media", "properties.property", "properties__property"],
|
268
|
+
returns [
|
269
|
+
selectinload(Product.media),
|
270
|
+
selectinload(Product.properties).selectinload(Property.property)
|
271
|
+
].
|
272
|
+
|
273
|
+
If `relations` is None or empty, recurse *all* relationships once (cycle-safe).
|
258
274
|
"""
|
259
275
|
loaders: List[Load] = []
|
260
|
-
|
261
|
-
|
262
|
-
|
263
|
-
|
264
|
-
|
265
|
-
|
276
|
+
|
277
|
+
if relations:
|
278
|
+
for path in relations:
|
279
|
+
parts = re.split(r"\.|\_\_", path)
|
280
|
+
current_model = model
|
281
|
+
loader: Load | None = None
|
282
|
+
|
283
|
+
for part in parts:
|
284
|
+
attr = getattr(current_model, part, None)
|
285
|
+
if attr is None or not hasattr(attr, "property"):
|
286
|
+
raise ValueError(f"Invalid relationship path: {path!r}")
|
287
|
+
loader = selectinload(attr) if loader is None else loader.selectinload(attr)
|
288
|
+
current_model = attr.property.mapper.class_
|
289
|
+
|
290
|
+
loaders.append(loader)
|
291
|
+
|
292
|
+
return loaders
|
293
|
+
|
294
|
+
visited = set()
|
295
|
+
|
296
|
+
def recurse(curr_model: Any, curr_loader: Load | None = None):
|
297
|
+
mapper = inspect(curr_model)
|
298
|
+
if mapper in visited:
|
299
|
+
return
|
300
|
+
visited.add(mapper)
|
301
|
+
|
302
|
+
for rel in mapper.relationships:
|
303
|
+
attr = getattr(curr_model, rel.key)
|
304
|
+
loader = (
|
305
|
+
selectinload(attr)
|
306
|
+
if curr_loader is None
|
307
|
+
else curr_loader.selectinload(attr)
|
308
|
+
)
|
309
|
+
loaders.append(loader)
|
310
|
+
recurse(rel.mapper.class_, loader)
|
311
|
+
|
312
|
+
recurse(model)
|
266
313
|
return loaders
|
267
314
|
|
268
315
|
async def _execute_query(self, stmt):
|
@@ -13,7 +13,7 @@ rb_commons/http/consul.py,sha256=Ioq72VD1jGwoC96set7n2SgxN40olzI-myA2lwKkYi4,186
|
|
13
13
|
rb_commons/http/exceptions.py,sha256=EGRMr1cRgiJ9Q2tkfANbf0c6-zzXf1CD6J3cmCaT_FA,1885
|
14
14
|
rb_commons/orm/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
15
15
|
rb_commons/orm/exceptions.py,sha256=1aMctiEwrPjyehoXVX1l6ML5ZOhmDkmBISzlTD5ey1Y,509
|
16
|
-
rb_commons/orm/managers.py,sha256=
|
16
|
+
rb_commons/orm/managers.py,sha256=f9F84tljRzrWOlJQeFQl7c_ZEnxBTROTS2MuclcCshA,19700
|
17
17
|
rb_commons/orm/services.py,sha256=71eRcJ4TxZvzNz-hLXo12X4U7PGK54ZfbLAb27AjZi8,1589
|
18
18
|
rb_commons/permissions/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
19
19
|
rb_commons/permissions/role_permissions.py,sha256=4dV89z6ggzLqCCiFYlMp7kQVJRESu6MHpkT5ZNjLo6A,1096
|
@@ -22,7 +22,7 @@ rb_commons/schemes/jwt.py,sha256=ZKLJ5D3fcEmEKySjzbxEgUcza4K-oPoHr14_Z0r9Yic,249
|
|
22
22
|
rb_commons/schemes/pagination.py,sha256=8VZW1wZGJIPR9jEBUgppZUoB4uqP8ORudHkMwvEJSxg,1866
|
23
23
|
rb_commons/utils/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
24
24
|
rb_commons/utils/media.py,sha256=J2Zi0J28DhcVQVzt-myNNVuzj9Msaetul53VjZtdDdc,820
|
25
|
-
rb_commons-0.7.
|
26
|
-
rb_commons-0.7.
|
27
|
-
rb_commons-0.7.
|
28
|
-
rb_commons-0.7.
|
25
|
+
rb_commons-0.7.2.dist-info/METADATA,sha256=Pn9mMU6eTTncfarrpeySkfFEfd-imHZHEVzgbm62mOM,6570
|
26
|
+
rb_commons-0.7.2.dist-info/WHEEL,sha256=_zCd3N1l69ArxyTb8rzEoP9TpbYXkqRFSNOD5OuxnTs,91
|
27
|
+
rb_commons-0.7.2.dist-info/top_level.txt,sha256=HPx_WAYo3_fbg1WCeGHsz3wPGio1ucbnrlm2lmqlJog,11
|
28
|
+
rb_commons-0.7.2.dist-info/RECORD,,
|
File without changes
|
File without changes
|