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.
@@ -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
- prop = rel_attr.property
155
- return prop.uselist and rel_attr.any(expr) or rel_attr.has(expr)
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
- combined = (
166
- True
167
- if not clauses
168
- else (or_(*clauses) if q._operator == "OR" else and_(*clauses))
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(self, model: Any, relations: Sequence[str]) -> List[Load]:
261
+ def _build_relation_loaders(
262
+ self,
263
+ model: Any,
264
+ relations: Sequence[str] | None = None
265
+ ) -> List[Load]:
254
266
  """
255
- Turn ['cat','product__tags'] into
256
- [selectinload(model.cat),
257
- selectinload(model.product).selectinload('tags')]
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
- for path in relations:
261
- parts = path.split("__")
262
- loader = selectinload(getattr(model, parts[0]))
263
- for sub in parts[1:]:
264
- loader = loader.selectinload(sub)
265
- loaders.append(loader)
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):
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: rb-commons
3
- Version: 0.7.0
3
+ Version: 0.7.2
4
4
  Summary: Commons of project and simplified orm based on sqlalchemy.
5
5
  Home-page: https://github.com/RoboSell-organization/rb-commons
6
6
  Author: Abdulvoris
@@ -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=TIIoZzxlUGscNFj0diWdNNwsajF8ncFFF24mptjxGxU,18312
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.0.dist-info/METADATA,sha256=xIB-Y4RnBQGO9Y_UxBecnp_QWChADCuGmqw3SeRuARQ,6570
26
- rb_commons-0.7.0.dist-info/WHEEL,sha256=_zCd3N1l69ArxyTb8rzEoP9TpbYXkqRFSNOD5OuxnTs,91
27
- rb_commons-0.7.0.dist-info/top_level.txt,sha256=HPx_WAYo3_fbg1WCeGHsz3wPGio1ucbnrlm2lmqlJog,11
28
- rb_commons-0.7.0.dist-info/RECORD,,
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,,