fastapi-sqla 3.1.1__py3-none-any.whl → 3.2.1__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.

Potentially problematic release.


This version of fastapi-sqla might be problematic. Click here for more details.

@@ -28,7 +28,6 @@ def db_host():
28
28
  When CI key is set in environment variables, it uses `postgres` as host name else,
29
29
  host used is `localhost`
30
30
  """
31
-
32
31
  return "postgres" if "CI" in os.environ else "localhost"
33
32
 
34
33
 
@@ -38,7 +37,6 @@ def db_user():
38
37
 
39
38
  postgres
40
39
  """
41
-
42
40
  return "postgres"
43
41
 
44
42
 
@@ -48,7 +46,6 @@ def db_url(db_host, db_user):
48
46
 
49
47
  db url example postgresql://{db_user}@{db_host}/postgres
50
48
  """
51
-
52
49
  return f"postgresql://{db_user}@{db_host}/postgres"
53
50
 
54
51
 
@@ -107,7 +104,6 @@ def sqla_reflection(sqla_modules, sqla_connection):
107
104
  @fixture
108
105
  def patch_engine_from_config(request, sqla_connection):
109
106
  """So that all DB operations are never written to db for real."""
110
-
111
107
  if "dont_patch_engines" in request.keywords:
112
108
  yield
113
109
  else:
@@ -153,7 +149,7 @@ def async_sqlalchemy_url(db_url):
153
149
  return format_async_async_sqlalchemy_url(db_url)
154
150
 
155
151
 
156
- if asyncio_support: # noqa: C901
152
+ if asyncio_support:
157
153
 
158
154
  @fixture
159
155
  def async_engine(async_sqlalchemy_url):
@@ -167,7 +163,6 @@ if asyncio_support: # noqa: C901
167
163
  @fixture
168
164
  async def patch_new_engine(request, async_sqla_connection):
169
165
  """So that all async DB operations are never written to db for real."""
170
-
171
166
  if "dont_patch_engines" in request.keywords:
172
167
  yield
173
168
  else:
@@ -1,12 +1,12 @@
1
1
  import math
2
- from collections.abc import Awaitable, Callable
3
- from typing import Annotated, Iterator, Optional, Union, cast
2
+ from collections.abc import Awaitable, Callable, Iterator
3
+ from typing import Annotated, Optional, Union, cast
4
4
 
5
5
  from fastapi import Depends, Query
6
6
  from sqlalchemy.sql import Select, func, select
7
7
 
8
8
  from fastapi_sqla.async_sqla import AsyncSessionDependency, SqlaAsyncSession
9
- from fastapi_sqla.models import Page
9
+ from fastapi_sqla.models import Meta, Page
10
10
  from fastapi_sqla.sqla import _DEFAULT_SESSION_KEY
11
11
 
12
12
  QueryCountDependency = Callable[..., Awaitable[int]]
@@ -19,7 +19,7 @@ PaginateDependency = Union[DefaultDependency, WithQueryCountDependency]
19
19
 
20
20
 
21
21
  async def default_query_count(session: SqlaAsyncSession, query: Select) -> int:
22
- result = await session.execute(select(func.count()).select_from(query.subquery())) # type: ignore # noqa
22
+ result = await session.execute(select(func.count()).select_from(query.subquery()))
23
23
  return cast(int, result.scalar())
24
24
 
25
25
 
@@ -33,20 +33,20 @@ async def paginate_query(
33
33
  scalars: bool = True,
34
34
  ) -> Page:
35
35
  total_pages = math.ceil(total_items / limit)
36
- page_number = offset / limit + 1
37
- query = query.offset(offset).limit(limit) # type: ignore
36
+ page_number = math.floor(offset / limit + 1)
37
+ query = query.offset(offset).limit(limit)
38
38
  result = await session.execute(query)
39
39
  data = iter(
40
- cast(Iterator, result.unique().scalars() if scalars else result.mappings()) # type: ignore # noqa
40
+ cast(Iterator, result.unique().scalars() if scalars else result.mappings())
41
41
  )
42
42
  return Page(
43
- data=data,
44
- meta={
45
- "offset": offset,
46
- "total_items": total_items,
47
- "total_pages": total_pages,
48
- "page_number": page_number,
49
- },
43
+ data=data, # type: ignore # Expected to be a list
44
+ meta=Meta(
45
+ offset=offset,
46
+ total_items=total_items,
47
+ total_pages=total_pages,
48
+ page_number=page_number,
49
+ ),
50
50
  )
51
51
 
52
52
 
@@ -20,7 +20,8 @@ def setup(engine: Engine):
20
20
  aws_rds_iam_enabled = lc_environ.get("fastapi_sqla_aws_rds_iam_enabled") == "true"
21
21
 
22
22
  if aws_rds_iam_enabled:
23
- assert boto3_installed, boto3_installed_err
23
+ if not boto3_installed:
24
+ raise ImportError(f"boto3 is required for RDS IAM : {boto3_installed_err}")
24
25
  # Cache the client at startup
25
26
  get_rds_client()
26
27
  event.listen(engine, "do_connect", set_connection_token)
fastapi_sqla/base.py CHANGED
@@ -30,7 +30,6 @@ def setup(app: FastAPI):
30
30
  functools.partial(sqla.add_session_to_request, key=key)
31
31
  )
32
32
  else:
33
- assert has_asyncio_support, asyncio_support_err
34
33
  app.add_event_handler(
35
34
  "startup", functools.partial(async_sqla.startup, key=key)
36
35
  )
fastapi_sqla/models.py CHANGED
@@ -3,7 +3,7 @@ from typing import Generic, TypeVar
3
3
  from pydantic import BaseModel, Field
4
4
  from pydantic import __version__ as pydantic_version
5
5
 
6
- major, _, _ = [int(v) for v in pydantic_version.split(".")]
6
+ major, _, _ = (int(v) for v in pydantic_version.split("."))
7
7
  is_pydantic2 = major == 2
8
8
  if is_pydantic2:
9
9
  GenericModel = BaseModel
@@ -1,13 +1,13 @@
1
1
  import math
2
- from collections.abc import Callable
2
+ from collections.abc import Callable, Iterator
3
3
  from functools import singledispatch
4
- from typing import Annotated, Iterator, Optional, Union, cast
4
+ from typing import Annotated, Optional, Union, cast
5
5
 
6
6
  from fastapi import Depends, Query
7
7
  from sqlalchemy.orm import Query as LegacyQuery
8
8
  from sqlalchemy.sql import Select, func, select
9
9
 
10
- from fastapi_sqla.models import Page
10
+ from fastapi_sqla.models import Meta, Page
11
11
  from fastapi_sqla.sqla import _DEFAULT_SESSION_KEY, SessionDependency, SqlaSession
12
12
 
13
13
  DbQuery = Union[LegacyQuery, Select]
@@ -52,7 +52,7 @@ def paginate_query(
52
52
  limit: int,
53
53
  scalars: bool = True,
54
54
  ) -> Page: # pragma: no cover
55
- "Dispatch on registered functions based on `query` type"
55
+ """Dispatch on registered functions based on `query` type"""
56
56
  raise NotImplementedError(f"no paginate_query registered for type {type(query)!r}")
57
57
 
58
58
 
@@ -66,15 +66,15 @@ def _paginate_legacy(
66
66
  scalars: bool = True,
67
67
  ) -> Page:
68
68
  total_pages = math.ceil(total_items / limit)
69
- page_number = offset / limit + 1
69
+ page_number = math.floor(offset / limit + 1)
70
70
  return Page(
71
- data=query.offset(offset).limit(limit).all(), # type: ignore
72
- meta={
73
- "offset": offset,
74
- "total_items": total_items,
75
- "total_pages": total_pages,
76
- "page_number": page_number,
77
- },
71
+ data=query.offset(offset).limit(limit).all(),
72
+ meta=Meta(
73
+ offset=offset,
74
+ total_items=total_items,
75
+ total_pages=total_pages,
76
+ page_number=page_number,
77
+ ),
78
78
  )
79
79
 
80
80
 
@@ -89,20 +89,20 @@ def _paginate(
89
89
  scalars: bool = True,
90
90
  ) -> Page:
91
91
  total_pages = math.ceil(total_items / limit)
92
- page_number = offset / limit + 1
93
- query = query.offset(offset).limit(limit) # type: ignore
92
+ page_number = math.floor(offset / limit + 1)
93
+ query = query.offset(offset).limit(limit)
94
94
  result = session.execute(query)
95
95
  data = iter(
96
- cast(Iterator, result.unique().scalars() if scalars else result.mappings()) # type: ignore # noqa
96
+ cast(Iterator, result.unique().scalars() if scalars else result.mappings())
97
97
  )
98
98
  return Page(
99
- data=data,
100
- meta={
101
- "offset": offset,
102
- "total_items": total_items,
103
- "total_pages": total_pages,
104
- "page_number": page_number,
105
- },
99
+ data=data, # type: ignore # Expected to be a list
100
+ meta=Meta(
101
+ offset=offset,
102
+ total_items=total_items,
103
+ total_pages=total_pages,
104
+ page_number=page_number,
105
+ ),
106
106
  )
107
107
 
108
108
 
fastapi_sqla/sqla.py CHANGED
@@ -2,7 +2,7 @@ import asyncio
2
2
  import os
3
3
  from collections.abc import Generator
4
4
  from contextlib import contextmanager
5
- from typing import Annotated, Generic, TypeVar
5
+ from typing import Annotated
6
6
 
7
7
  import structlog
8
8
  from fastapi import Depends, Request
@@ -24,7 +24,7 @@ except ImportError:
24
24
  DeclarativeBase = declarative_base() # type: ignore
25
25
 
26
26
  try:
27
- from sqlmodel import Session as SqlaSession # type: ignore # noqa
27
+ from sqlmodel import Session as SqlaSession # type: ignore
28
28
 
29
29
  except ImportError:
30
30
  pass
@@ -165,14 +165,11 @@ async def add_session_to_request(
165
165
  return response
166
166
 
167
167
 
168
- S = TypeVar("S", bound=SqlaSession)
169
-
170
-
171
- class SessionDependency(Generic[S]):
168
+ class SessionDependency:
172
169
  def __init__(self, key: str = _DEFAULT_SESSION_KEY) -> None:
173
170
  self.key = key
174
171
 
175
- def __call__(self, request: Request) -> S:
172
+ def __call__(self, request: Request) -> SqlaSession:
176
173
  """Yield the sqlalchemy session for that request.
177
174
 
178
175
  It is meant to be used as a FastAPI dependency::
@@ -197,5 +194,5 @@ class SessionDependency(Generic[S]):
197
194
  raise
198
195
 
199
196
 
200
- default_session_dep = SessionDependency[SqlaSession]()
197
+ default_session_dep = SessionDependency()
201
198
  Session = Annotated[SqlaSession, Depends(default_session_dep)]
@@ -1,7 +1,7 @@
1
1
  Metadata-Version: 2.1
2
2
  Name: fastapi-sqla
3
- Version: 3.1.1
4
- Summary: SQLAlchemy extension for FastAPI with support for pagination, asyncio, and pytest, ready for production.
3
+ Version: 3.2.1
4
+ Summary: SQLAlchemy extension for FastAPI with support for pagination, asyncio, SQLModel, and pytest, ready for production.
5
5
  Home-page: https://github.com/dialoguemd/fastapi-sqla
6
6
  License: MIT
7
7
  Keywords: FastAPI,SQLAlchemy,asyncio,pytest,alembic
@@ -22,6 +22,7 @@ Classifier: Programming Language :: Python :: 3
22
22
  Classifier: Programming Language :: Python :: 3.9
23
23
  Classifier: Programming Language :: Python :: 3.10
24
24
  Classifier: Programming Language :: Python :: 3.11
25
+ Classifier: Programming Language :: Python :: 3.12
25
26
  Classifier: Programming Language :: Python :: 3 :: Only
26
27
  Classifier: Programming Language :: SQL
27
28
  Classifier: Topic :: Internet
@@ -40,20 +41,18 @@ Requires-Dist: Faker (>=14.2.0,<15.0.0) ; extra == "tests"
40
41
  Requires-Dist: alembic (>=1.4.3,<2.0.0) ; extra == "tests"
41
42
  Requires-Dist: asgi_lifespan (>=1.0.1,<2.0.0) ; extra == "tests"
42
43
  Requires-Dist: asyncpg (>=0.28.0,<0.29.0) ; extra == "asyncpg"
43
- Requires-Dist: black (>=22.8.0,<23.0.0) ; extra == "tests"
44
44
  Requires-Dist: boto3 (>=1.24.74,<2.0.0) ; extra == "aws-rds-iam"
45
45
  Requires-Dist: fastapi (>=0.95.1)
46
- Requires-Dist: greenlet (>=1.1.3,<2.0.0) ; extra == "tests"
46
+ Requires-Dist: greenlet (>=3.0.3,<4.0.0) ; extra == "tests"
47
47
  Requires-Dist: httpx (>=0.23.0,<0.24.0) ; extra == "tests"
48
- Requires-Dist: isort (>=5.5.3,<6.0.0) ; extra == "tests"
49
- Requires-Dist: mypy[tests] (>=0.991,<0.992) ; extra == "tests"
48
+ Requires-Dist: mypy[tests] (>=1.0.0,<2.0.0) ; extra == "tests"
50
49
  Requires-Dist: pdbpp (>=0.10.2,<0.11.0) ; extra == "tests"
51
50
  Requires-Dist: psycopg2 (>=2.8.6,<3.0.0) ; extra == "tests"
52
51
  Requires-Dist: pydantic (>=1)
53
- Requires-Dist: pylama (>=8.4.1,<9.0.0) ; extra == "tests"
54
52
  Requires-Dist: pytest (>=7.2.1,<8.0.0) ; extra == "tests"
55
53
  Requires-Dist: pytest-asyncio (>=0.19.0,<0.20.0) ; extra == "tests"
56
54
  Requires-Dist: pytest-cov (>=2.10.1,<3.0.0) ; extra == "tests"
55
+ Requires-Dist: ruff (>=0.4.5,<0.5.0) ; extra == "tests"
57
56
  Requires-Dist: sqlalchemy (>=1.3)
58
57
  Requires-Dist: sqlmodel (>=0.0.14,<0.0.15) ; extra == "sqlmodel"
59
58
  Requires-Dist: structlog (>=20)
@@ -0,0 +1,16 @@
1
+ fastapi_sqla/__init__.py,sha256=G9bKR6L9EnLgzelE_BLnHgc1cOm0Yu0wMzwLAdyA8iE,1153
2
+ fastapi_sqla/_pytest_plugin.py,sha256=IQUlj-O874Sfuth254LBrEBGCrwH3rNHST9OMZl2pIk,5411
3
+ fastapi_sqla/async_pagination.py,sha256=3DHGUjvrpkbWMIc_BEX4GvM-_PTcn62K9z48ucTJlH0,3164
4
+ fastapi_sqla/async_sqla.py,sha256=7SXRH3DMsQvpjCQdvCBEjQhDZ4-cPAg175MlgNVBnCg,5888
5
+ fastapi_sqla/aws_aurora_support.py,sha256=4dxLKOqDccgLwFqlz81L6f4HzrOXMZkY7Zuf4t_310U,838
6
+ fastapi_sqla/aws_rds_iam_support.py,sha256=Uw-XaiwShMMWYKCvlSqXoxvtKMblCAvbCZ1m6BYVpJk,1257
7
+ fastapi_sqla/base.py,sha256=ssgt-EU7KrRg3IfvXoEZdCsDE4uQVhOVTFuamMmw-Kk,1546
8
+ fastapi_sqla/models.py,sha256=-B1xwINpTc9rEQd3KYHEC1s5s7jdVQkJ6Gy6xpmT13c,1108
9
+ fastapi_sqla/pagination.py,sha256=1gfIGcmt1OFspbRgtJ8AZOZdFd14DGRc4FkDgyh5bJ8,4517
10
+ fastapi_sqla/py.typed,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
11
+ fastapi_sqla/sqla.py,sha256=irHuZaun027o9WJrdcZPavCN2vXNHupCWYhU5Dx-AqE,6348
12
+ fastapi_sqla-3.2.1.dist-info/LICENSE,sha256=8G0-nWLqi3xRYRrtRlTE8n1mkYJcnCRoZGUhv6ZE29c,1064
13
+ fastapi_sqla-3.2.1.dist-info/METADATA,sha256=48-YxU0G8S7GR5zDMrLLgRY5LyMA7v0ku29SiEnqihA,20848
14
+ fastapi_sqla-3.2.1.dist-info/WHEEL,sha256=sP946D7jFCHeNz5Iq4fL4Lu-PrWrFsgfLXbbkciIZwg,88
15
+ fastapi_sqla-3.2.1.dist-info/entry_points.txt,sha256=haa0EueKcRo8-AlJTpHBMn08wMBiULNGA53nkvaDWj0,53
16
+ fastapi_sqla-3.2.1.dist-info/RECORD,,
@@ -1,4 +1,4 @@
1
1
  Wheel-Version: 1.0
2
- Generator: poetry-core 1.6.1
2
+ Generator: poetry-core 1.9.0
3
3
  Root-Is-Purelib: true
4
4
  Tag: py3-none-any
@@ -1,16 +0,0 @@
1
- fastapi_sqla/__init__.py,sha256=G9bKR6L9EnLgzelE_BLnHgc1cOm0Yu0wMzwLAdyA8iE,1153
2
- fastapi_sqla/_pytest_plugin.py,sha256=bjPzOuwk32Zo4hoOa_bGjTGhtHGPImh3RyiORqz-J84,5430
3
- fastapi_sqla/async_pagination.py,sha256=r5APFbE-xpqQPF1aTG19ILOwYDhuIlHql3UF3mYZMt4,3176
4
- fastapi_sqla/async_sqla.py,sha256=7SXRH3DMsQvpjCQdvCBEjQhDZ4-cPAg175MlgNVBnCg,5888
5
- fastapi_sqla/aws_aurora_support.py,sha256=4dxLKOqDccgLwFqlz81L6f4HzrOXMZkY7Zuf4t_310U,838
6
- fastapi_sqla/aws_rds_iam_support.py,sha256=YSJNhrxmhGN-GVk9PLMTmQSWTKZBvuorKkhc_XaoL44,1189
7
- fastapi_sqla/base.py,sha256=0X7Gbt49rBHPiSFmNy5S2PT0dA4UBNnwrAesYSkaHBc,1606
8
- fastapi_sqla/models.py,sha256=fesW7BqkwOA4iC345dbybzcV8Kz4-kLwREo38oqy_7A,1108
9
- fastapi_sqla/pagination.py,sha256=uhsNRf9w2GzJQkF8eUUQZMAudPDi7tN5OCb00kz3Dn4,4515
10
- fastapi_sqla/py.typed,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
11
- fastapi_sqla/sqla.py,sha256=zAkzY07bHEnOrmP7_dwO4Gdar18qm1ZbhB1RD3AZGrA,6427
12
- fastapi_sqla-3.1.1.dist-info/LICENSE,sha256=8G0-nWLqi3xRYRrtRlTE8n1mkYJcnCRoZGUhv6ZE29c,1064
13
- fastapi_sqla-3.1.1.dist-info/METADATA,sha256=caalhTVa91W2oBq_rXUhu5xahUzINgBpq39GRlsbvxc,20905
14
- fastapi_sqla-3.1.1.dist-info/WHEEL,sha256=Zb28QaM1gQi8f4VCBhsUklF61CTlNYfs9YAZn-TOGFk,88
15
- fastapi_sqla-3.1.1.dist-info/entry_points.txt,sha256=haa0EueKcRo8-AlJTpHBMn08wMBiULNGA53nkvaDWj0,53
16
- fastapi_sqla-3.1.1.dist-info/RECORD,,