-
Notifications
You must be signed in to change notification settings - Fork 11
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
feat: split the main modules into multiple modules - DIA-61984 (#106)
- Loading branch information
1 parent
512c9d8
commit e9510ac
Showing
17 changed files
with
332 additions
and
318 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,87 @@ | ||
import math | ||
from collections.abc import Awaitable, Callable | ||
from typing import Iterator, Optional, Union, cast | ||
|
||
from fastapi import Depends, Query | ||
from sqlalchemy.sql import Select, func, select | ||
|
||
from fastapi_sqla.async_sqla import AsyncSession | ||
from fastapi_sqla.models import Page | ||
|
||
QueryCountDependency = Callable[..., Awaitable[int]] | ||
PaginateSignature = Callable[[Select, Optional[bool]], Awaitable[Page]] | ||
DefaultDependency = Callable[[AsyncSession, int, int], PaginateSignature] | ||
WithQueryCountDependency = Callable[[AsyncSession, int, int, int], PaginateSignature] | ||
PaginateDependency = Union[DefaultDependency, WithQueryCountDependency] | ||
|
||
|
||
async def default_query_count(session: AsyncSession, query: Select) -> int: | ||
result = await session.execute(select(func.count()).select_from(query.subquery())) | ||
return cast(int, result.scalar()) | ||
|
||
|
||
async def paginate_query( | ||
query: Select, | ||
session: AsyncSession, | ||
total_items: int, | ||
offset: int, | ||
limit: int, | ||
*, | ||
scalars: bool = True, | ||
) -> Page: | ||
total_pages = math.ceil(total_items / limit) | ||
page_number = offset / limit + 1 | ||
query = query.offset(offset).limit(limit) | ||
result = await session.execute(query) | ||
data = iter( | ||
cast(Iterator, result.unique().scalars() if scalars else result.mappings()) | ||
) | ||
return Page( | ||
data=data, | ||
meta={ | ||
"offset": offset, | ||
"total_items": total_items, | ||
"total_pages": total_pages, | ||
"page_number": page_number, | ||
}, | ||
) | ||
|
||
|
||
def AsyncPagination( | ||
min_page_size: int = 10, | ||
max_page_size: int = 100, | ||
query_count: Union[QueryCountDependency, None] = None, | ||
) -> PaginateDependency: | ||
def default_dependency( | ||
session: AsyncSession = Depends(), | ||
offset: int = Query(0, ge=0), | ||
limit: int = Query(min_page_size, ge=1, le=max_page_size), | ||
) -> PaginateSignature: | ||
async def paginate(query: Select, scalars=True) -> Page: | ||
total_items = await default_query_count(session, query) | ||
return await paginate_query( | ||
query, session, total_items, offset, limit, scalars=scalars | ||
) | ||
|
||
return paginate | ||
|
||
def with_query_count_dependency( | ||
session: AsyncSession = Depends(), | ||
offset: int = Query(0, ge=0), | ||
limit: int = Query(min_page_size, ge=1, le=max_page_size), | ||
total_items: int = Depends(query_count), | ||
): | ||
async def paginate(query: Select, scalars=True) -> Page: | ||
return await paginate_query( | ||
query, session, total_items, offset, limit, scalars=scalars | ||
) | ||
|
||
return paginate | ||
|
||
if query_count: | ||
return with_query_count_dependency | ||
else: | ||
return default_dependency | ||
|
||
|
||
AsyncPaginate: PaginateDependency = AsyncPagination() |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,33 @@ | ||
import os | ||
|
||
from fastapi import FastAPI | ||
from sqlalchemy.engine import Engine | ||
|
||
from fastapi_sqla import sqla | ||
|
||
try: | ||
from fastapi_sqla import async_sqla | ||
|
||
has_asyncio_support = True | ||
|
||
except ImportError as err: # pragma: no cover | ||
has_asyncio_support = False | ||
asyncio_support_err = str(err) | ||
|
||
|
||
def setup(app: FastAPI): | ||
engine = sqla.new_engine() | ||
|
||
if not is_async_dialect(engine): | ||
app.add_event_handler("startup", sqla.startup) | ||
app.middleware("http")(sqla.add_session_to_request) | ||
|
||
has_async_config = "async_sqlalchemy_url" in os.environ or is_async_dialect(engine) | ||
if has_async_config: | ||
assert has_asyncio_support, asyncio_support_err | ||
app.add_event_handler("startup", async_sqla.startup) | ||
app.middleware("http")(async_sqla.add_session_to_request) | ||
|
||
|
||
def is_async_dialect(engine: Engine): | ||
return engine.dialect.is_async if hasattr(engine.dialect, "is_async") else False |
Oops, something went wrong.