Skip to content

Commit 0847913

Browse files
authored
Add async pymongo integration (#1544)
1 parent b1617c0 commit 0847913

File tree

2 files changed

+66
-14
lines changed

2 files changed

+66
-14
lines changed

fastapi_pagination/ext/pymongo.py

Lines changed: 43 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,17 +1,22 @@
11
from __future__ import annotations
22

3-
__all__ = ["paginate"]
3+
__all__ = [
4+
"apaginate",
5+
"paginate",
6+
]
7+
48

59
from collections.abc import Mapping, Sequence
610
from typing import Any, Optional, TypeVar
711

12+
from pymongo.asynchronous.collection import AsyncCollection
813
from pymongo.collection import Collection
914

1015
from fastapi_pagination.bases import AbstractParams
1116
from fastapi_pagination.config import Config
12-
from fastapi_pagination.flow import flow_expr, run_sync_flow
17+
from fastapi_pagination.flow import flow_expr, run_async_flow, run_sync_flow
1318
from fastapi_pagination.flows import generic_flow
14-
from fastapi_pagination.types import AdditionalData, SyncItemsTransformer
19+
from fastapi_pagination.types import AdditionalData, ItemsTransformer, SyncItemsTransformer
1520

1621
T = TypeVar("T", bound=Mapping[str, Any])
1722

@@ -49,3 +54,38 @@ def paginate(
4954
config=config,
5055
)
5156
)
57+
58+
59+
async def apaginate(
60+
collection: AsyncCollection[T],
61+
query_filter: Optional[dict[Any, Any]] = None,
62+
filter_fields: Optional[dict[Any, Any]] = None,
63+
params: Optional[AbstractParams] = None,
64+
sort: Optional[Sequence[Any]] = None,
65+
*,
66+
transformer: Optional[ItemsTransformer] = None,
67+
additional_data: Optional[AdditionalData] = None,
68+
config: Optional[Config] = None,
69+
**kwargs: Any,
70+
) -> Any:
71+
query_filter = query_filter or {}
72+
73+
return await run_async_flow(
74+
generic_flow(
75+
total_flow=flow_expr(lambda: collection.count_documents(query_filter)),
76+
limit_offset_flow=flow_expr(
77+
lambda raw_params: collection.find(
78+
query_filter,
79+
filter_fields,
80+
skip=raw_params.offset,
81+
limit=raw_params.limit,
82+
sort=sort,
83+
**kwargs,
84+
).to_list()
85+
),
86+
params=params,
87+
transformer=transformer,
88+
additional_data=additional_data,
89+
config=config,
90+
)
91+
)

tests/ext/test_pymongo.py

Lines changed: 23 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,10 @@
11
import pytest
2-
from pymongo import MongoClient
2+
from pymongo import AsyncMongoClient, MongoClient
3+
from pytest_asyncio import fixture as async_fixture
34

4-
from fastapi_pagination.ext.pymongo import paginate
5-
from tests.base import BasePaginationTestSuite
5+
from fastapi_pagination.ext.pymongo import apaginate, paginate
6+
from tests.base import BasePaginationTestSuite, async_sync_testsuite
7+
from tests.utils import maybe_async
68

79
from .utils import mongodb_test
810

@@ -12,18 +14,28 @@ def database_url(mongodb_url) -> str:
1214
return mongodb_url
1315

1416

15-
@pytest.fixture(scope="session")
16-
def db_client(database_url):
17-
with MongoClient(database_url) as client:
18-
yield client
19-
20-
2117
@mongodb_test
18+
@async_sync_testsuite
2219
class TestPymongo(BasePaginationTestSuite):
20+
@async_fixture(scope="session")
21+
async def db_client(self, database_url, is_async_db):
22+
if is_async_db:
23+
async with AsyncMongoClient(database_url) as client:
24+
yield client
25+
else:
26+
with MongoClient(database_url) as client:
27+
yield client
28+
2329
@pytest.fixture(scope="session")
24-
def app(self, builder, db_client):
30+
def paginate_func(self, is_async_db):
31+
return apaginate if is_async_db else paginate
32+
33+
@pytest.fixture(scope="session")
34+
def app(self, builder, db_client, paginate_func):
35+
builder = builder.new()
36+
2537
@builder.both.default
2638
async def route():
27-
return paginate(db_client.test.users)
39+
return await maybe_async(paginate_func(db_client.test.users))
2840

2941
return builder.build()

0 commit comments

Comments
 (0)