fastapi-mongo-base 1.7.0__tar.gz → 1.7.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 (113) hide show
  1. {fastapi_mongo_base-1.7.0/src/fastapi_mongo_base.egg-info → fastapi_mongo_base-1.7.2}/PKG-INFO +1 -1
  2. {fastapi_mongo_base-1.7.0 → fastapi_mongo_base-1.7.2}/pyproject.toml +1 -1
  3. fastapi_mongo_base-1.7.2/src/fastapi_mongo_base/utils/mongo_aggregate.py +47 -0
  4. {fastapi_mongo_base-1.7.0 → fastapi_mongo_base-1.7.2/src/fastapi_mongo_base.egg-info}/PKG-INFO +1 -1
  5. {fastapi_mongo_base-1.7.0 → fastapi_mongo_base-1.7.2}/src/fastapi_mongo_base.egg-info/SOURCES.txt +2 -0
  6. fastapi_mongo_base-1.7.2/tests/test_mongo_aggregate.py +63 -0
  7. {fastapi_mongo_base-1.7.0 → fastapi_mongo_base-1.7.2}/LICENSE.txt +0 -0
  8. {fastapi_mongo_base-1.7.0 → fastapi_mongo_base-1.7.2}/MANIFEST.in +0 -0
  9. {fastapi_mongo_base-1.7.0 → fastapi_mongo_base-1.7.2}/README.md +0 -0
  10. {fastapi_mongo_base-1.7.0 → fastapi_mongo_base-1.7.2}/docs/boilerplate.md +0 -0
  11. {fastapi_mongo_base-1.7.0 → fastapi_mongo_base-1.7.2}/docs/changelog.md +0 -0
  12. {fastapi_mongo_base-1.7.0 → fastapi_mongo_base-1.7.2}/docs/contributing.md +0 -0
  13. {fastapi_mongo_base-1.7.0 → fastapi_mongo_base-1.7.2}/docs/endpoints.md +0 -0
  14. {fastapi_mongo_base-1.7.0 → fastapi_mongo_base-1.7.2}/docs/extra.css +0 -0
  15. {fastapi_mongo_base-1.7.0 → fastapi_mongo_base-1.7.2}/docs/index.md +0 -0
  16. {fastapi_mongo_base-1.7.0 → fastapi_mongo_base-1.7.2}/docs/installation.md +0 -0
  17. {fastapi_mongo_base-1.7.0 → fastapi_mongo_base-1.7.2}/docs/license.md +0 -0
  18. {fastapi_mongo_base-1.7.0 → fastapi_mongo_base-1.7.2}/docs/quickstart.md +0 -0
  19. {fastapi_mongo_base-1.7.0 → fastapi_mongo_base-1.7.2}/docs/settings.md +0 -0
  20. {fastapi_mongo_base-1.7.0 → fastapi_mongo_base-1.7.2}/docs/tutorial.md +0 -0
  21. {fastapi_mongo_base-1.7.0 → fastapi_mongo_base-1.7.2}/docs/usage.md +0 -0
  22. {fastapi_mongo_base-1.7.0 → fastapi_mongo_base-1.7.2}/mkdocs.yml +0 -0
  23. {fastapi_mongo_base-1.7.0 → fastapi_mongo_base-1.7.2}/pytest.ini +0 -0
  24. {fastapi_mongo_base-1.7.0 → fastapi_mongo_base-1.7.2}/setup.cfg +0 -0
  25. {fastapi_mongo_base-1.7.0 → fastapi_mongo_base-1.7.2}/src/fastapi_mongo_base/__init__.py +0 -0
  26. {fastapi_mongo_base-1.7.0 → fastapi_mongo_base-1.7.2}/src/fastapi_mongo_base/core/__init__.py +0 -0
  27. {fastapi_mongo_base-1.7.0 → fastapi_mongo_base-1.7.2}/src/fastapi_mongo_base/core/app_factory.py +0 -0
  28. {fastapi_mongo_base-1.7.0 → fastapi_mongo_base-1.7.2}/src/fastapi_mongo_base/core/config.py +0 -0
  29. {fastapi_mongo_base-1.7.0 → fastapi_mongo_base-1.7.2}/src/fastapi_mongo_base/core/db.py +0 -0
  30. {fastapi_mongo_base-1.7.0 → fastapi_mongo_base-1.7.2}/src/fastapi_mongo_base/core/exceptions.py +0 -0
  31. {fastapi_mongo_base-1.7.0 → fastapi_mongo_base-1.7.2}/src/fastapi_mongo_base/db/__init__.py +0 -0
  32. {fastapi_mongo_base-1.7.0 → fastapi_mongo_base-1.7.2}/src/fastapi_mongo_base/db/mongo.py +0 -0
  33. {fastapi_mongo_base-1.7.0 → fastapi_mongo_base-1.7.2}/src/fastapi_mongo_base/db/redis.py +0 -0
  34. {fastapi_mongo_base-1.7.0 → fastapi_mongo_base-1.7.2}/src/fastapi_mongo_base/db/sql.py +0 -0
  35. {fastapi_mongo_base-1.7.0 → fastapi_mongo_base-1.7.2}/src/fastapi_mongo_base/errors/__init__.py +0 -0
  36. {fastapi_mongo_base-1.7.0 → fastapi_mongo_base-1.7.2}/src/fastapi_mongo_base/errors/base.py +0 -0
  37. {fastapi_mongo_base-1.7.0 → fastapi_mongo_base-1.7.2}/src/fastapi_mongo_base/errors/exceptions.py +0 -0
  38. {fastapi_mongo_base-1.7.0 → fastapi_mongo_base-1.7.2}/src/fastapi_mongo_base/errors/handlers.py +0 -0
  39. {fastapi_mongo_base-1.7.0 → fastapi_mongo_base-1.7.2}/src/fastapi_mongo_base/errors/mongodb.py +0 -0
  40. {fastapi_mongo_base-1.7.0 → fastapi_mongo_base-1.7.2}/src/fastapi_mongo_base/errors/redis.py +0 -0
  41. {fastapi_mongo_base-1.7.0 → fastapi_mongo_base-1.7.2}/src/fastapi_mongo_base/errors/resource.py +0 -0
  42. {fastapi_mongo_base-1.7.0 → fastapi_mongo_base-1.7.2}/src/fastapi_mongo_base/errors/responses.py +0 -0
  43. {fastapi_mongo_base-1.7.0 → fastapi_mongo_base-1.7.2}/src/fastapi_mongo_base/errors/sql.py +0 -0
  44. {fastapi_mongo_base-1.7.0 → fastapi_mongo_base-1.7.2}/src/fastapi_mongo_base/errors/status.py +0 -0
  45. {fastapi_mongo_base-1.7.0 → fastapi_mongo_base-1.7.2}/src/fastapi_mongo_base/i18n/__init__.py +0 -0
  46. {fastapi_mongo_base-1.7.0 → fastapi_mongo_base-1.7.2}/src/fastapi_mongo_base/i18n/context.py +0 -0
  47. {fastapi_mongo_base-1.7.0 → fastapi_mongo_base-1.7.2}/src/fastapi_mongo_base/i18n/languages.py +0 -0
  48. {fastapi_mongo_base-1.7.0 → fastapi_mongo_base-1.7.2}/src/fastapi_mongo_base/i18n/messages.py +0 -0
  49. {fastapi_mongo_base-1.7.0 → fastapi_mongo_base-1.7.2}/src/fastapi_mongo_base/i18n/timezone.py +0 -0
  50. {fastapi_mongo_base-1.7.0 → fastapi_mongo_base-1.7.2}/src/fastapi_mongo_base/logging/__init__.py +0 -0
  51. {fastapi_mongo_base-1.7.0 → fastapi_mongo_base-1.7.2}/src/fastapi_mongo_base/logging/formatters.py +0 -0
  52. {fastapi_mongo_base-1.7.0 → fastapi_mongo_base-1.7.2}/src/fastapi_mongo_base/middlewares/__init__.py +0 -0
  53. {fastapi_mongo_base-1.7.0 → fastapi_mongo_base-1.7.2}/src/fastapi_mongo_base/middlewares/prometheus.py +0 -0
  54. {fastapi_mongo_base-1.7.0 → fastapi_mongo_base-1.7.2}/src/fastapi_mongo_base/middlewares/timer.py +0 -0
  55. {fastapi_mongo_base-1.7.0 → fastapi_mongo_base-1.7.2}/src/fastapi_mongo_base/middlewares/timezone.py +0 -0
  56. {fastapi_mongo_base-1.7.0 → fastapi_mongo_base-1.7.2}/src/fastapi_mongo_base/middlewares/trace.py +0 -0
  57. {fastapi_mongo_base-1.7.0 → fastapi_mongo_base-1.7.2}/src/fastapi_mongo_base/models.py +0 -0
  58. {fastapi_mongo_base-1.7.0 → fastapi_mongo_base-1.7.2}/src/fastapi_mongo_base/monitoring/__init__.py +0 -0
  59. {fastapi_mongo_base-1.7.0 → fastapi_mongo_base-1.7.2}/src/fastapi_mongo_base/monitoring/middleware.py +0 -0
  60. {fastapi_mongo_base-1.7.0 → fastapi_mongo_base-1.7.2}/src/fastapi_mongo_base/monitoring/mongo.py +0 -0
  61. {fastapi_mongo_base-1.7.0 → fastapi_mongo_base-1.7.2}/src/fastapi_mongo_base/monitoring/sentry.py +0 -0
  62. {fastapi_mongo_base-1.7.0 → fastapi_mongo_base-1.7.2}/src/fastapi_mongo_base/py.typed +0 -0
  63. {fastapi_mongo_base-1.7.0 → fastapi_mongo_base-1.7.2}/src/fastapi_mongo_base/routes.py +0 -0
  64. {fastapi_mongo_base-1.7.0 → fastapi_mongo_base-1.7.2}/src/fastapi_mongo_base/schemas.py +0 -0
  65. {fastapi_mongo_base-1.7.0 → fastapi_mongo_base-1.7.2}/src/fastapi_mongo_base/sql/__init__.py +0 -0
  66. {fastapi_mongo_base-1.7.0 → fastapi_mongo_base-1.7.2}/src/fastapi_mongo_base/sql/models.py +0 -0
  67. {fastapi_mongo_base-1.7.0 → fastapi_mongo_base-1.7.2}/src/fastapi_mongo_base/sql/session.py +0 -0
  68. {fastapi_mongo_base-1.7.0 → fastapi_mongo_base-1.7.2}/src/fastapi_mongo_base/tasks.py +0 -0
  69. {fastapi_mongo_base-1.7.0 → fastapi_mongo_base-1.7.2}/src/fastapi_mongo_base/utils/__init__.py +0 -0
  70. {fastapi_mongo_base-1.7.0 → fastapi_mongo_base-1.7.2}/src/fastapi_mongo_base/utils/basic.py +0 -0
  71. {fastapi_mongo_base-1.7.0 → fastapi_mongo_base-1.7.2}/src/fastapi_mongo_base/utils/bsontools.py +0 -0
  72. {fastapi_mongo_base-1.7.0 → fastapi_mongo_base-1.7.2}/src/fastapi_mongo_base/utils/delegated_create.py +0 -0
  73. {fastapi_mongo_base-1.7.0 → fastapi_mongo_base-1.7.2}/src/fastapi_mongo_base/utils/timezone.py +0 -0
  74. {fastapi_mongo_base-1.7.0 → fastapi_mongo_base-1.7.2}/src/fastapi_mongo_base/utils/trace.py +0 -0
  75. {fastapi_mongo_base-1.7.0 → fastapi_mongo_base-1.7.2}/src/fastapi_mongo_base/utils/usso/__init__.py +0 -0
  76. {fastapi_mongo_base-1.7.0 → fastapi_mongo_base-1.7.2}/src/fastapi_mongo_base/utils/usso/principals.py +0 -0
  77. {fastapi_mongo_base-1.7.0 → fastapi_mongo_base-1.7.2}/src/fastapi_mongo_base/utils/usso_routes.py +0 -0
  78. {fastapi_mongo_base-1.7.0 → fastapi_mongo_base-1.7.2}/src/fastapi_mongo_base.egg-info/dependency_links.txt +0 -0
  79. {fastapi_mongo_base-1.7.0 → fastapi_mongo_base-1.7.2}/src/fastapi_mongo_base.egg-info/requires.txt +0 -0
  80. {fastapi_mongo_base-1.7.0 → fastapi_mongo_base-1.7.2}/src/fastapi_mongo_base.egg-info/top_level.txt +0 -0
  81. {fastapi_mongo_base-1.7.0 → fastapi_mongo_base-1.7.2}/tests/__init__.py +0 -0
  82. {fastapi_mongo_base-1.7.0 → fastapi_mongo_base-1.7.2}/tests/app/__init__.py +0 -0
  83. {fastapi_mongo_base-1.7.0 → fastapi_mongo_base-1.7.2}/tests/app/logs/app.log +0 -0
  84. {fastapi_mongo_base-1.7.0 → fastapi_mongo_base-1.7.2}/tests/app/main.py +0 -0
  85. {fastapi_mongo_base-1.7.0 → fastapi_mongo_base-1.7.2}/tests/app/server.py +0 -0
  86. {fastapi_mongo_base-1.7.0 → fastapi_mongo_base-1.7.2}/tests/conftest.py +0 -0
  87. {fastapi_mongo_base-1.7.0 → fastapi_mongo_base-1.7.2}/tests/helpers/__init__.py +0 -0
  88. {fastapi_mongo_base-1.7.0 → fastapi_mongo_base-1.7.2}/tests/helpers/usso_mock.py +0 -0
  89. {fastapi_mongo_base-1.7.0 → fastapi_mongo_base-1.7.2}/tests/test_apis.py +0 -0
  90. {fastapi_mongo_base-1.7.0 → fastapi_mongo_base-1.7.2}/tests/test_app.py +0 -0
  91. {fastapi_mongo_base-1.7.0 → fastapi_mongo_base-1.7.2}/tests/test_basic_utils.py +0 -0
  92. {fastapi_mongo_base-1.7.0 → fastapi_mongo_base-1.7.2}/tests/test_bsontools.py +0 -0
  93. {fastapi_mongo_base-1.7.0 → fastapi_mongo_base-1.7.2}/tests/test_db.py +0 -0
  94. {fastapi_mongo_base-1.7.0 → fastapi_mongo_base-1.7.2}/tests/test_delegated_create.py +0 -0
  95. {fastapi_mongo_base-1.7.0 → fastapi_mongo_base-1.7.2}/tests/test_exception_shims.py +0 -0
  96. {fastapi_mongo_base-1.7.0 → fastapi_mongo_base-1.7.2}/tests/test_http_errors.py +0 -0
  97. {fastapi_mongo_base-1.7.0 → fastapi_mongo_base-1.7.2}/tests/test_i18n.py +0 -0
  98. {fastapi_mongo_base-1.7.0 → fastapi_mongo_base-1.7.2}/tests/test_i18n_timezone.py +0 -0
  99. {fastapi_mongo_base-1.7.0 → fastapi_mongo_base-1.7.2}/tests/test_middlewares.py +0 -0
  100. {fastapi_mongo_base-1.7.0 → fastapi_mongo_base-1.7.2}/tests/test_mongodb_errors.py +0 -0
  101. {fastapi_mongo_base-1.7.0 → fastapi_mongo_base-1.7.2}/tests/test_monitoring_middleware.py +0 -0
  102. {fastapi_mongo_base-1.7.0 → fastapi_mongo_base-1.7.2}/tests/test_monitoring_mongo.py +0 -0
  103. {fastapi_mongo_base-1.7.0 → fastapi_mongo_base-1.7.2}/tests/test_openapi_errors.py +0 -0
  104. {fastapi_mongo_base-1.7.0 → fastapi_mongo_base-1.7.2}/tests/test_sentry.py +0 -0
  105. {fastapi_mongo_base-1.7.0 → fastapi_mongo_base-1.7.2}/tests/test_sql_models.py +0 -0
  106. {fastapi_mongo_base-1.7.0 → fastapi_mongo_base-1.7.2}/tests/test_tasks.py +0 -0
  107. {fastapi_mongo_base-1.7.0 → fastapi_mongo_base-1.7.2}/tests/test_tenant_subject_schema.py +0 -0
  108. {fastapi_mongo_base-1.7.0 → fastapi_mongo_base-1.7.2}/tests/test_timezone.py +0 -0
  109. {fastapi_mongo_base-1.7.0 → fastapi_mongo_base-1.7.2}/tests/test_trace.py +0 -0
  110. {fastapi_mongo_base-1.7.0 → fastapi_mongo_base-1.7.2}/tests/test_usso_principals.py +0 -0
  111. {fastapi_mongo_base-1.7.0 → fastapi_mongo_base-1.7.2}/tests/test_usso_routes.py +0 -0
  112. {fastapi_mongo_base-1.7.0 → fastapi_mongo_base-1.7.2}/tests/test_usso_routes_workspace.py +0 -0
  113. {fastapi_mongo_base-1.7.0 → fastapi_mongo_base-1.7.2}/tests/test_usso_routes_workspace_entity.py +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: fastapi-mongo-base
3
- Version: 1.7.0
3
+ Version: 1.7.2
4
4
  Summary: A simple boilerplate application, including models and schemas and abstract router, for FastAPI with MongoDB
5
5
  Author-email: Mahdi Kiani <mahdikiany@gmail.com>
6
6
  Maintainer-email: Mahdi Kiani <mahdikiany@gmail.com>
@@ -4,7 +4,7 @@ build-backend = "setuptools.build_meta"
4
4
 
5
5
  [project]
6
6
  name = "fastapi-mongo-base"
7
- version = "1.7.0"
7
+ version = "1.7.2"
8
8
  description = "A simple boilerplate application, including models and schemas and abstract router, for FastAPI with MongoDB"
9
9
  readme = "README.md"
10
10
  requires-python = ">=3.10"
@@ -0,0 +1,47 @@
1
+ """Mongo aggregation helpers compatible with Motor and PyMongo async."""
2
+
3
+ from __future__ import annotations
4
+
5
+ import inspect
6
+ from typing import TYPE_CHECKING
7
+
8
+ if TYPE_CHECKING:
9
+ from beanie import Document
10
+
11
+
12
+ def _get_collection(model: type[Document]) -> object:
13
+ """Return the Beanie collection (Beanie 2 pymongo or Beanie 1 motor)."""
14
+ getter = getattr(model, "get_pymongo_collection", None) or getattr(
15
+ model, "get_motor_collection", None
16
+ )
17
+ if getter is None:
18
+ raise AttributeError(
19
+ f"{model.__name__} has neither get_pymongo_collection "
20
+ "nor get_motor_collection"
21
+ )
22
+ return getter()
23
+
24
+
25
+ async def aggregate_to_list(
26
+ model: type[Document],
27
+ pipeline: list[dict[str, object]],
28
+ *,
29
+ length: int | None = None,
30
+ **kwargs: object,
31
+ ) -> list[dict[str, object]]:
32
+ """
33
+ Run an aggregation pipeline and return documents as a list.
34
+
35
+ Beanie's ``aggregate().to_list()`` assumes Motor cursors; PyMongo 4.x
36
+ native async may return a coroutine from ``aggregate()`` — this helper
37
+ supports both drivers. Collection access works with Beanie 2
38
+ (``get_pymongo_collection``) and Beanie 1 (``get_motor_collection``).
39
+ """
40
+ collection = _get_collection(model)
41
+ cursor = collection.aggregate(pipeline, **kwargs)
42
+ if inspect.isawaitable(cursor):
43
+ cursor = await cursor
44
+ result = cursor.to_list(length=length)
45
+ if inspect.isawaitable(result):
46
+ return await result
47
+ return result
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: fastapi-mongo-base
3
- Version: 1.7.0
3
+ Version: 1.7.2
4
4
  Summary: A simple boilerplate application, including models and schemas and abstract router, for FastAPI with MongoDB
5
5
  Author-email: Mahdi Kiani <mahdikiany@gmail.com>
6
6
  Maintainer-email: Mahdi Kiani <mahdikiany@gmail.com>
@@ -69,6 +69,7 @@ src/fastapi_mongo_base/utils/__init__.py
69
69
  src/fastapi_mongo_base/utils/basic.py
70
70
  src/fastapi_mongo_base/utils/bsontools.py
71
71
  src/fastapi_mongo_base/utils/delegated_create.py
72
+ src/fastapi_mongo_base/utils/mongo_aggregate.py
72
73
  src/fastapi_mongo_base/utils/timezone.py
73
74
  src/fastapi_mongo_base/utils/trace.py
74
75
  src/fastapi_mongo_base/utils/usso_routes.py
@@ -87,6 +88,7 @@ tests/test_http_errors.py
87
88
  tests/test_i18n.py
88
89
  tests/test_i18n_timezone.py
89
90
  tests/test_middlewares.py
91
+ tests/test_mongo_aggregate.py
90
92
  tests/test_mongodb_errors.py
91
93
  tests/test_monitoring_middleware.py
92
94
  tests/test_monitoring_mongo.py
@@ -0,0 +1,63 @@
1
+ """Tests for Motor/PyMongo-compatible aggregation helper."""
2
+
3
+ from __future__ import annotations
4
+
5
+ from typing import Any
6
+ from unittest.mock import AsyncMock, MagicMock
7
+
8
+ import pytest
9
+
10
+ from src.fastapi_mongo_base.utils.mongo_aggregate import aggregate_to_list
11
+
12
+
13
+ @pytest.mark.asyncio
14
+ async def test_aggregate_to_list_beanie2_pymongo_collection() -> None:
15
+ """Beanie 2: use get_pymongo_collection; aggregate/to_list may be sync."""
16
+ docs = [{"_id": 1}]
17
+ cursor = MagicMock()
18
+ cursor.to_list.return_value = docs
19
+ collection = MagicMock()
20
+ collection.aggregate.return_value = cursor
21
+ model = MagicMock(spec=["get_pymongo_collection"])
22
+ model.get_pymongo_collection.return_value = collection
23
+ model.__name__ = "Doc"
24
+
25
+ result = await aggregate_to_list(model, [{"$match": {}}], length=10)
26
+
27
+ assert result == docs
28
+ model.get_pymongo_collection.assert_called_once_with()
29
+ collection.aggregate.assert_called_once_with([{"$match": {}}])
30
+ cursor.to_list.assert_called_once_with(length=10)
31
+
32
+
33
+ @pytest.mark.asyncio
34
+ async def test_aggregate_to_list_beanie1_motor_fallback() -> None:
35
+ """Beanie 1: fall back to get_motor_collection."""
36
+ docs = [{"_id": 2}]
37
+ cursor = MagicMock()
38
+ cursor.to_list = AsyncMock(return_value=docs)
39
+ collection = MagicMock()
40
+ collection.aggregate = AsyncMock(return_value=cursor)
41
+ model = MagicMock(spec=["get_motor_collection"])
42
+ model.get_motor_collection.return_value = collection
43
+ model.__name__ = "Doc"
44
+
45
+ pipeline: list[dict[str, Any]] = [{"$group": {"_id": None}}]
46
+ result = await aggregate_to_list(
47
+ model, pipeline, length=None, allowDiskUse=True
48
+ )
49
+
50
+ assert result == docs
51
+ model.get_motor_collection.assert_called_once_with()
52
+ collection.aggregate.assert_awaited_once_with(pipeline, allowDiskUse=True)
53
+ cursor.to_list.assert_awaited_once_with(length=None)
54
+
55
+
56
+ @pytest.mark.asyncio
57
+ async def test_aggregate_to_list_missing_collection_getter() -> None:
58
+ """Raise when the model exposes neither collection getter."""
59
+ model = MagicMock(spec=[])
60
+ model.__name__ = "Broken"
61
+
62
+ with pytest.raises(AttributeError, match="get_pymongo_collection"):
63
+ await aggregate_to_list(model, [])