fastapi-toolsets 5.1.1__tar.gz → 5.1.2__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 (44) hide show
  1. {fastapi_toolsets-5.1.1 → fastapi_toolsets-5.1.2}/PKG-INFO +1 -1
  2. {fastapi_toolsets-5.1.1 → fastapi_toolsets-5.1.2}/pyproject.toml +1 -1
  3. {fastapi_toolsets-5.1.1 → fastapi_toolsets-5.1.2}/pyproject.toml.orig +1 -1
  4. {fastapi_toolsets-5.1.1 → fastapi_toolsets-5.1.2}/src/fastapi_toolsets/__init__.py +1 -1
  5. {fastapi_toolsets-5.1.1 → fastapi_toolsets-5.1.2}/src/fastapi_toolsets/crud/factory.py +14 -40
  6. {fastapi_toolsets-5.1.1 → fastapi_toolsets-5.1.2}/LICENSE +0 -0
  7. {fastapi_toolsets-5.1.1 → fastapi_toolsets-5.1.2}/README.md +0 -0
  8. {fastapi_toolsets-5.1.1 → fastapi_toolsets-5.1.2}/src/fastapi_toolsets/_imports.py +0 -0
  9. {fastapi_toolsets-5.1.1 → fastapi_toolsets-5.1.2}/src/fastapi_toolsets/cli/__init__.py +0 -0
  10. {fastapi_toolsets-5.1.1 → fastapi_toolsets-5.1.2}/src/fastapi_toolsets/cli/app.py +0 -0
  11. {fastapi_toolsets-5.1.1 → fastapi_toolsets-5.1.2}/src/fastapi_toolsets/cli/commands/__init__.py +0 -0
  12. {fastapi_toolsets-5.1.1 → fastapi_toolsets-5.1.2}/src/fastapi_toolsets/cli/commands/fixtures.py +0 -0
  13. {fastapi_toolsets-5.1.1 → fastapi_toolsets-5.1.2}/src/fastapi_toolsets/cli/config.py +0 -0
  14. {fastapi_toolsets-5.1.1 → fastapi_toolsets-5.1.2}/src/fastapi_toolsets/cli/pyproject.py +0 -0
  15. {fastapi_toolsets-5.1.1 → fastapi_toolsets-5.1.2}/src/fastapi_toolsets/cli/utils.py +0 -0
  16. {fastapi_toolsets-5.1.1 → fastapi_toolsets-5.1.2}/src/fastapi_toolsets/crud/__init__.py +0 -0
  17. {fastapi_toolsets-5.1.1 → fastapi_toolsets-5.1.2}/src/fastapi_toolsets/crud/search.py +0 -0
  18. {fastapi_toolsets-5.1.1 → fastapi_toolsets-5.1.2}/src/fastapi_toolsets/db/__init__.py +0 -0
  19. {fastapi_toolsets-5.1.1 → fastapi_toolsets-5.1.2}/src/fastapi_toolsets/db/core.py +0 -0
  20. {fastapi_toolsets-5.1.1 → fastapi_toolsets-5.1.2}/src/fastapi_toolsets/db/locks.py +0 -0
  21. {fastapi_toolsets-5.1.1 → fastapi_toolsets-5.1.2}/src/fastapi_toolsets/db/m2m.py +0 -0
  22. {fastapi_toolsets-5.1.1 → fastapi_toolsets-5.1.2}/src/fastapi_toolsets/db/testing.py +0 -0
  23. {fastapi_toolsets-5.1.1 → fastapi_toolsets-5.1.2}/src/fastapi_toolsets/db/watch.py +0 -0
  24. {fastapi_toolsets-5.1.1 → fastapi_toolsets-5.1.2}/src/fastapi_toolsets/dependencies.py +0 -0
  25. {fastapi_toolsets-5.1.1 → fastapi_toolsets-5.1.2}/src/fastapi_toolsets/exceptions/__init__.py +0 -0
  26. {fastapi_toolsets-5.1.1 → fastapi_toolsets-5.1.2}/src/fastapi_toolsets/exceptions/exceptions.py +0 -0
  27. {fastapi_toolsets-5.1.1 → fastapi_toolsets-5.1.2}/src/fastapi_toolsets/exceptions/handler.py +0 -0
  28. {fastapi_toolsets-5.1.1 → fastapi_toolsets-5.1.2}/src/fastapi_toolsets/fixtures/__init__.py +0 -0
  29. {fastapi_toolsets-5.1.1 → fastapi_toolsets-5.1.2}/src/fastapi_toolsets/fixtures/enum.py +0 -0
  30. {fastapi_toolsets-5.1.1 → fastapi_toolsets-5.1.2}/src/fastapi_toolsets/fixtures/registry.py +0 -0
  31. {fastapi_toolsets-5.1.1 → fastapi_toolsets-5.1.2}/src/fastapi_toolsets/fixtures/utils.py +0 -0
  32. {fastapi_toolsets-5.1.1 → fastapi_toolsets-5.1.2}/src/fastapi_toolsets/logger.py +0 -0
  33. {fastapi_toolsets-5.1.1 → fastapi_toolsets-5.1.2}/src/fastapi_toolsets/metrics/__init__.py +0 -0
  34. {fastapi_toolsets-5.1.1 → fastapi_toolsets-5.1.2}/src/fastapi_toolsets/metrics/handler.py +0 -0
  35. {fastapi_toolsets-5.1.1 → fastapi_toolsets-5.1.2}/src/fastapi_toolsets/metrics/registry.py +0 -0
  36. {fastapi_toolsets-5.1.1 → fastapi_toolsets-5.1.2}/src/fastapi_toolsets/models/__init__.py +0 -0
  37. {fastapi_toolsets-5.1.1 → fastapi_toolsets-5.1.2}/src/fastapi_toolsets/models/columns.py +0 -0
  38. {fastapi_toolsets-5.1.1 → fastapi_toolsets-5.1.2}/src/fastapi_toolsets/models/watched.py +0 -0
  39. {fastapi_toolsets-5.1.1 → fastapi_toolsets-5.1.2}/src/fastapi_toolsets/py.typed +0 -0
  40. {fastapi_toolsets-5.1.1 → fastapi_toolsets-5.1.2}/src/fastapi_toolsets/pytest/__init__.py +0 -0
  41. {fastapi_toolsets-5.1.1 → fastapi_toolsets-5.1.2}/src/fastapi_toolsets/pytest/plugin.py +0 -0
  42. {fastapi_toolsets-5.1.1 → fastapi_toolsets-5.1.2}/src/fastapi_toolsets/pytest/utils.py +0 -0
  43. {fastapi_toolsets-5.1.1 → fastapi_toolsets-5.1.2}/src/fastapi_toolsets/schemas.py +0 -0
  44. {fastapi_toolsets-5.1.1 → fastapi_toolsets-5.1.2}/src/fastapi_toolsets/types.py +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: fastapi-toolsets
3
- Version: 5.1.1
3
+ Version: 5.1.2
4
4
  Summary: Production-ready utilities for FastAPI applications
5
5
  Keywords: fastapi,sqlalchemy,postgresql
6
6
  Author: d3vyce
@@ -1,6 +1,6 @@
1
1
  [project]
2
2
  name = "fastapi-toolsets"
3
- version = "5.1.1"
3
+ version = "5.1.2"
4
4
  description = "Production-ready utilities for FastAPI applications"
5
5
  readme = "README.md"
6
6
  license = "MIT"
@@ -1,6 +1,6 @@
1
1
  [project]
2
2
  name = "fastapi-toolsets"
3
- version = "5.1.1"
3
+ version = "5.1.2"
4
4
  description = "Production-ready utilities for FastAPI applications"
5
5
  readme = "README.md"
6
6
  license = "MIT"
@@ -24,4 +24,4 @@ Example usage:
24
24
  return Response(data={"user": user.username}, message="Success")
25
25
  """
26
26
 
27
- __version__ = "5.1.1"
27
+ __version__ = "5.1.2"
@@ -270,32 +270,17 @@ class AsyncCrud(Generic[ModelType]):
270
270
  return cls.default_load_options
271
271
 
272
272
  @classmethod
273
- def _capture_pk_values(
274
- cls: type[Self], instance: DeclarativeBase
275
- ) -> dict[str, Any]:
276
- """Capture PK values off instance — call before commit expires attributes."""
277
- return {
278
- cast(str, col.key): getattr(instance, cast(str, col.key))
279
- for col in cls.model.__mapper__.primary_key
280
- }
281
-
282
- @classmethod
283
- async def _reload_with_options_by_pk(
284
- cls: type[Self], session: AsyncSession, pk_values: dict[str, Any]
273
+ async def _reload_with_options(
274
+ cls: type[Self], session: AsyncSession, instance: DeclarativeBase
285
275
  ) -> ModelType:
286
- """Re-query by previously captured PK values, with default_load_options applied."""
287
- # Only called when cls.default_load_options is set (see call sites).
276
+ """Re-query instance by PK with default_load_options applied."""
277
+ mapper = cls.model.__mapper__
288
278
  pk_filters = [
289
- getattr(cls.model, key) == value for key, value in pk_values.items()
279
+ getattr(cls.model, cast(str, col.key))
280
+ == getattr(instance, cast(str, col.key))
281
+ for col in mapper.primary_key
290
282
  ]
291
- q = select(cls.model).where(and_(*pk_filters))
292
- q = q.execution_options(populate_existing=True)
293
- q = q.options(*cast(Sequence[ExecutableOption], cls.default_load_options))
294
- result = await session.execute(q)
295
- item = result.unique().scalar_one_or_none()
296
- if item is None: # pragma: no cover — row was just flushed in this transaction
297
- raise NotFoundError()
298
- return cast(ModelType, item)
283
+ return await cls.get(session, filters=pk_filters)
299
284
 
300
285
  @classmethod
301
286
  async def _resolve_m2m(
@@ -849,14 +834,9 @@ class AsyncCrud(Generic[ModelType]):
849
834
  setattr(db_model, rel_attr, related_instances)
850
835
 
851
836
  session.add(db_model)
852
- pk_values: dict[str, Any] | None = None
853
- if cls.default_load_options:
854
- await session.flush()
855
- pk_values = cls._capture_pk_values(db_model)
856
- if pk_values is not None:
857
- db_model = await cls._reload_with_options_by_pk(session, pk_values)
858
- else:
859
- await session.refresh(db_model)
837
+ await session.refresh(db_model)
838
+ if cls.default_load_options:
839
+ db_model = await cls._reload_with_options(session, db_model)
860
840
  result = cast(ModelType, db_model)
861
841
  if schema:
862
842
  return Response(data=schema.model_validate(result))
@@ -1233,15 +1213,9 @@ class AsyncCrud(Generic[ModelType]):
1233
1213
  m2m_resolved = await cls._resolve_m2m(session, obj, only_set=True)
1234
1214
  for rel_attr, related_instances in m2m_resolved.items():
1235
1215
  setattr(db_model, rel_attr, related_instances)
1236
-
1237
- pk_values: dict[str, Any] | None = None
1238
- if cls.default_load_options:
1239
- await session.flush()
1240
- pk_values = cls._capture_pk_values(db_model)
1241
- if pk_values is not None:
1242
- db_model = await cls._reload_with_options_by_pk(session, pk_values)
1243
- else:
1244
- await session.refresh(db_model)
1216
+ await session.refresh(db_model)
1217
+ if cls.default_load_options:
1218
+ db_model = await cls._reload_with_options(session, db_model)
1245
1219
  if schema:
1246
1220
  return Response(data=schema.model_validate(db_model))
1247
1221
  return db_model