fastapi-sqla 3.1.2__tar.gz → 3.3.0__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.
- {fastapi_sqla-3.1.2 → fastapi_sqla-3.3.0}/PKG-INFO +32 -9
- {fastapi_sqla-3.1.2 → fastapi_sqla-3.3.0}/README.md +27 -4
- {fastapi_sqla-3.1.2 → fastapi_sqla-3.3.0}/fastapi_sqla/__init__.py +3 -1
- {fastapi_sqla-3.1.2 → fastapi_sqla-3.3.0}/fastapi_sqla/_pytest_plugin.py +1 -6
- {fastapi_sqla-3.1.2 → fastapi_sqla-3.3.0}/fastapi_sqla/async_pagination.py +2 -2
- {fastapi_sqla-3.1.2 → fastapi_sqla-3.3.0}/fastapi_sqla/aws_rds_iam_support.py +2 -1
- {fastapi_sqla-3.1.2 → fastapi_sqla-3.3.0}/fastapi_sqla/base.py +28 -1
- {fastapi_sqla-3.1.2 → fastapi_sqla-3.3.0}/fastapi_sqla/models.py +1 -1
- {fastapi_sqla-3.1.2 → fastapi_sqla-3.3.0}/fastapi_sqla/pagination.py +3 -3
- {fastapi_sqla-3.1.2 → fastapi_sqla-3.3.0}/fastapi_sqla/sqla.py +1 -1
- fastapi_sqla-3.3.0/pyproject.toml +219 -0
- fastapi_sqla-3.1.2/pyproject.toml +0 -132
- {fastapi_sqla-3.1.2 → fastapi_sqla-3.3.0}/LICENSE +0 -0
- {fastapi_sqla-3.1.2 → fastapi_sqla-3.3.0}/fastapi_sqla/async_sqla.py +0 -0
- {fastapi_sqla-3.1.2 → fastapi_sqla-3.3.0}/fastapi_sqla/aws_aurora_support.py +0 -0
- {fastapi_sqla-3.1.2 → fastapi_sqla-3.3.0}/fastapi_sqla/py.typed +0 -0
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.1
|
|
2
2
|
Name: fastapi-sqla
|
|
3
|
-
Version: 3.
|
|
3
|
+
Version: 3.3.0
|
|
4
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
|
|
@@ -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,19 @@ 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
|
+
Requires-Dist: deprecated (>=1.2)
|
|
45
46
|
Requires-Dist: fastapi (>=0.95.1)
|
|
46
|
-
Requires-Dist: greenlet (>=
|
|
47
|
+
Requires-Dist: greenlet (>=3.0.3,<4.0.0) ; extra == "tests"
|
|
47
48
|
Requires-Dist: httpx (>=0.23.0,<0.24.0) ; extra == "tests"
|
|
48
|
-
Requires-Dist: isort (>=5.5.3,<6.0.0) ; extra == "tests"
|
|
49
49
|
Requires-Dist: mypy[tests] (>=1.0.0,<2.0.0) ; extra == "tests"
|
|
50
50
|
Requires-Dist: pdbpp (>=0.10.2,<0.11.0) ; extra == "tests"
|
|
51
51
|
Requires-Dist: psycopg2 (>=2.8.6,<3.0.0) ; extra == "tests"
|
|
52
52
|
Requires-Dist: pydantic (>=1)
|
|
53
|
-
Requires-Dist: pylama (>=8.4.1,<9.0.0) ; extra == "tests"
|
|
54
53
|
Requires-Dist: pytest (>=7.2.1,<8.0.0) ; extra == "tests"
|
|
55
54
|
Requires-Dist: pytest-asyncio (>=0.19.0,<0.20.0) ; extra == "tests"
|
|
56
55
|
Requires-Dist: pytest-cov (>=2.10.1,<3.0.0) ; extra == "tests"
|
|
56
|
+
Requires-Dist: ruff (>=0.4.5,<0.5.0) ; extra == "tests"
|
|
57
57
|
Requires-Dist: sqlalchemy (>=1.3)
|
|
58
58
|
Requires-Dist: sqlmodel (>=0.0.14,<0.0.15) ; extra == "sqlmodel"
|
|
59
59
|
Requires-Dist: structlog (>=20)
|
|
@@ -90,15 +90,22 @@ unique `email`:
|
|
|
90
90
|
|
|
91
91
|
```python
|
|
92
92
|
# main.py
|
|
93
|
+
from contextlib import asynccontextmanager
|
|
93
94
|
from fastapi import FastAPI, HTTPException
|
|
94
|
-
from fastapi_sqla import Base, Item, Page, Paginate, Session,
|
|
95
|
+
from fastapi_sqla import Base, Item, Page, Paginate, Session, setup_middlewares, startup
|
|
95
96
|
from pydantic import BaseModel, EmailStr
|
|
96
97
|
from sqlalchemy import select
|
|
97
98
|
from sqlalchemy.exc import IntegrityError
|
|
98
99
|
|
|
99
|
-
app = FastAPI()
|
|
100
100
|
|
|
101
|
-
|
|
101
|
+
@asynccontextmanager
|
|
102
|
+
async def lifespan(app: FastAPI):
|
|
103
|
+
await startup()
|
|
104
|
+
yield
|
|
105
|
+
|
|
106
|
+
|
|
107
|
+
app = FastAPI(lifespan=lifespan)
|
|
108
|
+
setup_middlewares(app)
|
|
102
109
|
|
|
103
110
|
|
|
104
111
|
class User(Base):
|
|
@@ -203,7 +210,23 @@ And define the environment variable `sqlalchemy_url` with `postgres+asyncpg` sch
|
|
|
203
210
|
export sqlalchemy_url=postgresql+asyncpg://postgres@localhost
|
|
204
211
|
```
|
|
205
212
|
|
|
206
|
-
## Setup the app:
|
|
213
|
+
## Setup the app AsyncContextManager (recommended):
|
|
214
|
+
|
|
215
|
+
```python
|
|
216
|
+
import fastapi_sqla
|
|
217
|
+
from fastapi import FastAPI
|
|
218
|
+
|
|
219
|
+
@asynccontextmanager
|
|
220
|
+
async def lifespan(app: FastAPI):
|
|
221
|
+
await fastapi_sqla.startup()
|
|
222
|
+
yield
|
|
223
|
+
|
|
224
|
+
|
|
225
|
+
app = FastAPI(lifespan=lifespan)
|
|
226
|
+
fastapi_sqla.setup_middlewares(app)
|
|
227
|
+
```
|
|
228
|
+
|
|
229
|
+
## Setup the app using startup/shutdown events (deprecated):
|
|
207
230
|
|
|
208
231
|
```python
|
|
209
232
|
import fastapi_sqla
|
|
@@ -27,15 +27,22 @@ unique `email`:
|
|
|
27
27
|
|
|
28
28
|
```python
|
|
29
29
|
# main.py
|
|
30
|
+
from contextlib import asynccontextmanager
|
|
30
31
|
from fastapi import FastAPI, HTTPException
|
|
31
|
-
from fastapi_sqla import Base, Item, Page, Paginate, Session,
|
|
32
|
+
from fastapi_sqla import Base, Item, Page, Paginate, Session, setup_middlewares, startup
|
|
32
33
|
from pydantic import BaseModel, EmailStr
|
|
33
34
|
from sqlalchemy import select
|
|
34
35
|
from sqlalchemy.exc import IntegrityError
|
|
35
36
|
|
|
36
|
-
app = FastAPI()
|
|
37
37
|
|
|
38
|
-
|
|
38
|
+
@asynccontextmanager
|
|
39
|
+
async def lifespan(app: FastAPI):
|
|
40
|
+
await startup()
|
|
41
|
+
yield
|
|
42
|
+
|
|
43
|
+
|
|
44
|
+
app = FastAPI(lifespan=lifespan)
|
|
45
|
+
setup_middlewares(app)
|
|
39
46
|
|
|
40
47
|
|
|
41
48
|
class User(Base):
|
|
@@ -140,7 +147,23 @@ And define the environment variable `sqlalchemy_url` with `postgres+asyncpg` sch
|
|
|
140
147
|
export sqlalchemy_url=postgresql+asyncpg://postgres@localhost
|
|
141
148
|
```
|
|
142
149
|
|
|
143
|
-
## Setup the app:
|
|
150
|
+
## Setup the app AsyncContextManager (recommended):
|
|
151
|
+
|
|
152
|
+
```python
|
|
153
|
+
import fastapi_sqla
|
|
154
|
+
from fastapi import FastAPI
|
|
155
|
+
|
|
156
|
+
@asynccontextmanager
|
|
157
|
+
async def lifespan(app: FastAPI):
|
|
158
|
+
await fastapi_sqla.startup()
|
|
159
|
+
yield
|
|
160
|
+
|
|
161
|
+
|
|
162
|
+
app = FastAPI(lifespan=lifespan)
|
|
163
|
+
fastapi_sqla.setup_middlewares(app)
|
|
164
|
+
```
|
|
165
|
+
|
|
166
|
+
## Setup the app using startup/shutdown events (deprecated):
|
|
144
167
|
|
|
145
168
|
```python
|
|
146
169
|
import fastapi_sqla
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
from fastapi_sqla.base import setup
|
|
1
|
+
from fastapi_sqla.base import setup, setup_middlewares, startup
|
|
2
2
|
from fastapi_sqla.models import Collection, Item, Page
|
|
3
3
|
from fastapi_sqla.pagination import Paginate, PaginateSignature, Pagination
|
|
4
4
|
from fastapi_sqla.sqla import (
|
|
@@ -22,6 +22,8 @@ __all__ = [
|
|
|
22
22
|
"SqlaSession",
|
|
23
23
|
"open_session",
|
|
24
24
|
"setup",
|
|
25
|
+
"setup_middlewares",
|
|
26
|
+
"startup",
|
|
25
27
|
]
|
|
26
28
|
|
|
27
29
|
|
|
@@ -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:
|
|
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,6 +1,6 @@
|
|
|
1
1
|
import math
|
|
2
|
-
from collections.abc import Awaitable, Callable
|
|
3
|
-
from typing import Annotated,
|
|
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
|
|
@@ -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
|
-
|
|
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)
|
|
@@ -2,6 +2,7 @@ import functools
|
|
|
2
2
|
import os
|
|
3
3
|
import re
|
|
4
4
|
|
|
5
|
+
from deprecated import deprecated
|
|
5
6
|
from fastapi import FastAPI
|
|
6
7
|
from sqlalchemy.engine import Engine
|
|
7
8
|
|
|
@@ -20,6 +21,33 @@ except ImportError as err: # pragma: no cover
|
|
|
20
21
|
_ENGINE_KEYS_REGEX = re.compile(r"fastapi_sqla__(?!_)(.+)(?<!_)__(?!_).+")
|
|
21
22
|
|
|
22
23
|
|
|
24
|
+
async def startup():
|
|
25
|
+
engine_keys = _get_engine_keys()
|
|
26
|
+
engines = {key: sqla.new_engine(key) for key in engine_keys}
|
|
27
|
+
for key, engine in engines.items():
|
|
28
|
+
if not _is_async_dialect(engine):
|
|
29
|
+
sqla.startup(key=key)
|
|
30
|
+
else:
|
|
31
|
+
await async_sqla.startup(key=key)
|
|
32
|
+
|
|
33
|
+
|
|
34
|
+
def setup_middlewares(app: FastAPI):
|
|
35
|
+
engine_keys = _get_engine_keys()
|
|
36
|
+
engines = {key: sqla.new_engine(key) for key in engine_keys}
|
|
37
|
+
for key, engine in engines.items():
|
|
38
|
+
if not _is_async_dialect(engine):
|
|
39
|
+
app.middleware("http")(
|
|
40
|
+
functools.partial(sqla.add_session_to_request, key=key)
|
|
41
|
+
)
|
|
42
|
+
else:
|
|
43
|
+
app.middleware("http")(
|
|
44
|
+
functools.partial(async_sqla.add_session_to_request, key=key)
|
|
45
|
+
)
|
|
46
|
+
|
|
47
|
+
|
|
48
|
+
@deprecated(
|
|
49
|
+
reason="FastAPI events are deprecated. This function will be remove in the upcoming major release." # noqa: E501
|
|
50
|
+
)
|
|
23
51
|
def setup(app: FastAPI):
|
|
24
52
|
engine_keys = _get_engine_keys()
|
|
25
53
|
engines = {key: sqla.new_engine(key) for key in engine_keys}
|
|
@@ -30,7 +58,6 @@ def setup(app: FastAPI):
|
|
|
30
58
|
functools.partial(sqla.add_session_to_request, key=key)
|
|
31
59
|
)
|
|
32
60
|
else:
|
|
33
|
-
assert has_asyncio_support, asyncio_support_err
|
|
34
61
|
app.add_event_handler(
|
|
35
62
|
"startup", functools.partial(async_sqla.startup, key=key)
|
|
36
63
|
)
|
|
@@ -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, _, _ =
|
|
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,7 +1,7 @@
|
|
|
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,
|
|
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
|
|
@@ -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
|
|
|
@@ -0,0 +1,219 @@
|
|
|
1
|
+
[tool.poetry]
|
|
2
|
+
name = "fastapi-sqla"
|
|
3
|
+
version = "3.3.0"
|
|
4
|
+
description = "SQLAlchemy extension for FastAPI with support for pagination, asyncio, SQLModel, and pytest, ready for production."
|
|
5
|
+
authors = [
|
|
6
|
+
"Hadrien David <hadrien.david@dialogue.co>",
|
|
7
|
+
"Victor Repkow <victor.repkow@dialogue.co>",
|
|
8
|
+
]
|
|
9
|
+
license = "MIT"
|
|
10
|
+
readme = "README.md"
|
|
11
|
+
repository = "https://github.com/dialoguemd/fastapi-sqla"
|
|
12
|
+
keywords = ["FastAPI", "SQLAlchemy", "asyncio", "pytest", "alembic"]
|
|
13
|
+
classifiers = [
|
|
14
|
+
"Development Status :: 5 - Production/Stable",
|
|
15
|
+
"Environment :: Web Environment",
|
|
16
|
+
"Framework :: AsyncIO",
|
|
17
|
+
"Framework :: FastAPI",
|
|
18
|
+
"Intended Audience :: Developers",
|
|
19
|
+
"Intended Audience :: Information Technology",
|
|
20
|
+
"Intended Audience :: System Administrators",
|
|
21
|
+
"License :: OSI Approved :: MIT License",
|
|
22
|
+
"Operating System :: OS Independent",
|
|
23
|
+
"Programming Language :: Python :: 3 :: Only",
|
|
24
|
+
"Programming Language :: Python :: 3",
|
|
25
|
+
"Programming Language :: Python :: 3.11",
|
|
26
|
+
"Programming Language :: Python :: 3.10",
|
|
27
|
+
"Programming Language :: Python :: 3.9",
|
|
28
|
+
"Programming Language :: Python",
|
|
29
|
+
"Programming Language :: SQL",
|
|
30
|
+
"Topic :: Internet :: WWW/HTTP :: HTTP Servers",
|
|
31
|
+
"Topic :: Internet :: WWW/HTTP",
|
|
32
|
+
"Topic :: Internet",
|
|
33
|
+
"Topic :: Software Development :: Libraries :: Application Frameworks",
|
|
34
|
+
"Topic :: Software Development :: Libraries :: Python Modules",
|
|
35
|
+
"Topic :: Software Development :: Libraries",
|
|
36
|
+
"Topic :: Software Development",
|
|
37
|
+
"Typing :: Typed",
|
|
38
|
+
]
|
|
39
|
+
|
|
40
|
+
[tool.poetry.dependencies]
|
|
41
|
+
python = "^3.9"
|
|
42
|
+
fastapi = ">=0.95.1"
|
|
43
|
+
pydantic = ">=1"
|
|
44
|
+
sqlalchemy = ">=1.3"
|
|
45
|
+
structlog = ">=20"
|
|
46
|
+
deprecated = ">=1.2"
|
|
47
|
+
|
|
48
|
+
alembic = { version = "^1.4.3", optional = true }
|
|
49
|
+
asgi_lifespan = { version = "^1.0.1", optional = true }
|
|
50
|
+
asyncpg = { version = "^0.28.0", optional = true }
|
|
51
|
+
Faker = { version = "^14.2.0", optional = true }
|
|
52
|
+
httpx = { version = "^0.23.0", optional = true }
|
|
53
|
+
pdbpp = { version = "^0.10.2", optional = true }
|
|
54
|
+
psycopg2 = { version = "^2.8.6", optional = true }
|
|
55
|
+
pytest = { version = "^7.2.1", optional = true }
|
|
56
|
+
pytest-asyncio = { version = "^0.19.0", optional = true }
|
|
57
|
+
pytest-cov = { version = "^2.10.1", optional = true }
|
|
58
|
+
ruff = { version = "^0.4.5", optional = true }
|
|
59
|
+
tox = { version = "^3.26.0", optional = true }
|
|
60
|
+
boto3 = { version = "^1.24.74", optional = true }
|
|
61
|
+
greenlet = { version = "^3.0.3", optional = true }
|
|
62
|
+
mypy = { version = "^1.0.0", extras = ["tests"], optional = true }
|
|
63
|
+
sqlmodel = { version = "^0.0.14", optional = true }
|
|
64
|
+
|
|
65
|
+
[tool.poetry.extras]
|
|
66
|
+
# Test dependencies as extras so they can be set as extras in tox config
|
|
67
|
+
# More info on https://github.com/python-poetry/poetry/issues/1941
|
|
68
|
+
tests = [
|
|
69
|
+
"alembic",
|
|
70
|
+
"asgi_lifespan",
|
|
71
|
+
"coverage",
|
|
72
|
+
"Faker",
|
|
73
|
+
"greenlet",
|
|
74
|
+
"httpx",
|
|
75
|
+
"mypy",
|
|
76
|
+
"pdbpp",
|
|
77
|
+
"psycopg2",
|
|
78
|
+
"pytest",
|
|
79
|
+
"pytest-asyncio",
|
|
80
|
+
"pytest-cov",
|
|
81
|
+
"pytest-watch",
|
|
82
|
+
"ruff",
|
|
83
|
+
"tox",
|
|
84
|
+
]
|
|
85
|
+
asyncpg = ["asyncpg"]
|
|
86
|
+
aws_rds_iam = ["boto3"]
|
|
87
|
+
sqlmodel = ["sqlmodel"]
|
|
88
|
+
|
|
89
|
+
[build-system]
|
|
90
|
+
requires = ["poetry>=1.3.0"]
|
|
91
|
+
build-backend = "poetry.masonry.api"
|
|
92
|
+
|
|
93
|
+
[tool.semantic_release]
|
|
94
|
+
version_toml = ["pyproject.toml:tool.poetry.version"]
|
|
95
|
+
upload_to_pypi = false
|
|
96
|
+
commit_message = "{version}\n\nVersion generated by python-semantic-release [ci skip]"
|
|
97
|
+
|
|
98
|
+
[tool.poetry.plugins."pytest11"]
|
|
99
|
+
fastapi-sqla = "fastapi_sqla._pytest_plugin"
|
|
100
|
+
|
|
101
|
+
[tool.ruff]
|
|
102
|
+
target-version = "py39"
|
|
103
|
+
|
|
104
|
+
[tool.ruff.lint]
|
|
105
|
+
select = [
|
|
106
|
+
"E", # pycodestyle
|
|
107
|
+
"W", # pycodestyle warnings
|
|
108
|
+
"F", # pyflakes
|
|
109
|
+
"I", # isort
|
|
110
|
+
"N", # pep8-naming
|
|
111
|
+
"D", # pydocstyle
|
|
112
|
+
"UP", # pyupgrade
|
|
113
|
+
"ASYNC", # flake8-async
|
|
114
|
+
"S", # flake8-bandit
|
|
115
|
+
"B", # flake8-bugbear
|
|
116
|
+
"C4", # flake8-comprehensions
|
|
117
|
+
"SIM", # flake8-simplify
|
|
118
|
+
"TD", # flake8-todos
|
|
119
|
+
"ERA", # eradicate
|
|
120
|
+
"PL", # pylint
|
|
121
|
+
"RUF", # ruff
|
|
122
|
+
]
|
|
123
|
+
|
|
124
|
+
# Ignore some pydocstyle rules that Google convention enables
|
|
125
|
+
ignore = [
|
|
126
|
+
"D100",
|
|
127
|
+
"D101",
|
|
128
|
+
"D102",
|
|
129
|
+
"D103",
|
|
130
|
+
"D104",
|
|
131
|
+
"D105",
|
|
132
|
+
"D106",
|
|
133
|
+
"D107",
|
|
134
|
+
"D212",
|
|
135
|
+
"D415",
|
|
136
|
+
"B008", # Enable using functions in default function args. Easier to work with FastAPI dependencies that way
|
|
137
|
+
"C408", # Enable using dict/list/tuple
|
|
138
|
+
"PLR0911", # Disable max number of return
|
|
139
|
+
"PLR0912", # Disable max number of branches
|
|
140
|
+
"PLR0913", # Disable max number of args
|
|
141
|
+
"PLR0915", # Disable max number of statements
|
|
142
|
+
"PLR2004", # Enable magic values
|
|
143
|
+
"SIM105", # Allow using try - except - pass
|
|
144
|
+
"TD001", # Enable FIXMEs
|
|
145
|
+
"TD002", # Enable TODOs without author
|
|
146
|
+
"TD003", # Enable TODOs without issue link
|
|
147
|
+
"N802", # FastAPI dependency conventions is title cased
|
|
148
|
+
"N803", # Same as N802
|
|
149
|
+
"N806", # Same as N802
|
|
150
|
+
]
|
|
151
|
+
|
|
152
|
+
[tool.ruff.lint.extend-per-file-ignores]
|
|
153
|
+
"tests/*" = [
|
|
154
|
+
"S101", # Enable assert
|
|
155
|
+
"S105", # Disable passwords check
|
|
156
|
+
"S106", # Disable passwords check
|
|
157
|
+
"S608", # Allow SQL string construction
|
|
158
|
+
]
|
|
159
|
+
|
|
160
|
+
[tool.ruff.lint.pydocstyle]
|
|
161
|
+
convention = "google"
|
|
162
|
+
|
|
163
|
+
[tool.pytest.ini_options]
|
|
164
|
+
asyncio_mode = "auto"
|
|
165
|
+
testpaths = "tests"
|
|
166
|
+
norecursedirs = ".git,.venv"
|
|
167
|
+
xfail_strict = "true"
|
|
168
|
+
addopts = """
|
|
169
|
+
-p no:fastapi-sqla
|
|
170
|
+
--cov-config pyproject.toml
|
|
171
|
+
--cov-report term
|
|
172
|
+
--cov-report term-missing
|
|
173
|
+
"""
|
|
174
|
+
|
|
175
|
+
# https://nedbatchelder.com/blog/201810/why_warnings_is_mysterious.html
|
|
176
|
+
filterwarnings = ["error:.*removed in version 2.0.*:"]
|
|
177
|
+
|
|
178
|
+
[tool.pytest-watch.run]
|
|
179
|
+
ext = ".py, .yaml, .cfg"
|
|
180
|
+
|
|
181
|
+
[tool.coverage.run]
|
|
182
|
+
branch = true
|
|
183
|
+
omit = ["tests/*", ".venv/*"]
|
|
184
|
+
concurrency = ["thread", "greenlet"]
|
|
185
|
+
|
|
186
|
+
[tool.coverage.report]
|
|
187
|
+
skip_covered = true
|
|
188
|
+
|
|
189
|
+
[tool.tox]
|
|
190
|
+
legacy_tox_ini = """
|
|
191
|
+
[tox]
|
|
192
|
+
envlist = sqlalchemy{ 1.3, 1.4, 2.0, 2.0-sqlmodel }-{ asyncpg, noasyncpg }-{aws_rds_iam, noaws_rds_iam }-pydantic{ 1, 2 }
|
|
193
|
+
|
|
194
|
+
[testenv]
|
|
195
|
+
passenv = CI
|
|
196
|
+
deps =
|
|
197
|
+
sqlalchemy1.3: sqlalchemy<1.4
|
|
198
|
+
sqlalchemy1.4: sqlalchemy>=1.4,<2
|
|
199
|
+
sqlalchemy2.0: sqlalchemy>=2
|
|
200
|
+
sqlalchemy2.0-sqlmodel: sqlalchemy>=2
|
|
201
|
+
sqlalchemy2.0-sqlmodel: sqlmodel
|
|
202
|
+
asyncpg: asyncpg
|
|
203
|
+
aws_rds_iam: boto3
|
|
204
|
+
pydantic1: pydantic<2
|
|
205
|
+
pydantic2: pydantic>=2
|
|
206
|
+
|
|
207
|
+
extras =
|
|
208
|
+
tests
|
|
209
|
+
|
|
210
|
+
commands = pytest -vv --cov={envsitepackagesdir}/fastapi_sqla --cov-report xml --cov-report html --junitxml=test-reports/pytest/junit.xml
|
|
211
|
+
"""
|
|
212
|
+
|
|
213
|
+
[tool.mypy]
|
|
214
|
+
exclude = ["tests"]
|
|
215
|
+
plugins = ["sqlalchemy.ext.mypy.plugin"]
|
|
216
|
+
|
|
217
|
+
[[tool.mypy.overrides]]
|
|
218
|
+
module = ["asyncpg", "boto3", "deprecated"]
|
|
219
|
+
ignore_missing_imports = true
|
|
@@ -1,132 +0,0 @@
|
|
|
1
|
-
[tool]
|
|
2
|
-
[tool.poetry]
|
|
3
|
-
name = "fastapi-sqla"
|
|
4
|
-
version = "3.1.2"
|
|
5
|
-
description = "SQLAlchemy extension for FastAPI with support for pagination, asyncio, SQLModel, and pytest, ready for production."
|
|
6
|
-
authors = ["Hadrien David <hadrien.david@dialogue.co>", "Victor Repkow <victor.repkow@dialogue.co>"]
|
|
7
|
-
license = "MIT"
|
|
8
|
-
readme = "README.md"
|
|
9
|
-
repository = "https://github.com/dialoguemd/fastapi-sqla"
|
|
10
|
-
keywords = ["FastAPI", "SQLAlchemy", "asyncio", "pytest", "alembic"]
|
|
11
|
-
classifiers = ["Development Status :: 5 - Production/Stable", "Environment :: Web Environment", "Framework :: AsyncIO", "Framework :: FastAPI", "Intended Audience :: Developers", "Intended Audience :: Information Technology", "Intended Audience :: System Administrators", "License :: OSI Approved :: MIT License", "Operating System :: OS Independent", "Programming Language :: Python :: 3 :: Only", "Programming Language :: Python :: 3", "Programming Language :: Python :: 3.11", "Programming Language :: Python :: 3.10", "Programming Language :: Python :: 3.9", "Programming Language :: Python", "Programming Language :: SQL", "Topic :: Internet :: WWW/HTTP :: HTTP Servers", "Topic :: Internet :: WWW/HTTP", "Topic :: Internet", "Topic :: Software Development :: Libraries :: Application Frameworks", "Topic :: Software Development :: Libraries :: Python Modules", "Topic :: Software Development :: Libraries", "Topic :: Software Development", "Typing :: Typed"]
|
|
12
|
-
[tool.poetry.dependencies]
|
|
13
|
-
python = "^3.9"
|
|
14
|
-
fastapi = ">=0.95.1"
|
|
15
|
-
pydantic = ">=1"
|
|
16
|
-
sqlalchemy = ">=1.3"
|
|
17
|
-
structlog = ">=20"
|
|
18
|
-
[tool.poetry.dependencies.alembic]
|
|
19
|
-
version = "^1.4.3"
|
|
20
|
-
optional = true
|
|
21
|
-
[tool.poetry.dependencies.asgi_lifespan]
|
|
22
|
-
version = "^1.0.1"
|
|
23
|
-
optional = true
|
|
24
|
-
[tool.poetry.dependencies.asyncpg]
|
|
25
|
-
version = "^0.28.0"
|
|
26
|
-
optional = true
|
|
27
|
-
[tool.poetry.dependencies.black]
|
|
28
|
-
version = "^22.8.0"
|
|
29
|
-
optional = true
|
|
30
|
-
[tool.poetry.dependencies.Faker]
|
|
31
|
-
version = "^14.2.0"
|
|
32
|
-
optional = true
|
|
33
|
-
[tool.poetry.dependencies.httpx]
|
|
34
|
-
version = "^0.23.0"
|
|
35
|
-
optional = true
|
|
36
|
-
[tool.poetry.dependencies.isort]
|
|
37
|
-
version = "^5.5.3"
|
|
38
|
-
optional = true
|
|
39
|
-
[tool.poetry.dependencies.pdbpp]
|
|
40
|
-
version = "^0.10.2"
|
|
41
|
-
optional = true
|
|
42
|
-
[tool.poetry.dependencies.psycopg2]
|
|
43
|
-
version = "^2.8.6"
|
|
44
|
-
optional = true
|
|
45
|
-
[tool.poetry.dependencies.pylama]
|
|
46
|
-
version = "^8.4.1"
|
|
47
|
-
optional = true
|
|
48
|
-
[tool.poetry.dependencies.pytest]
|
|
49
|
-
version = "^7.2.1"
|
|
50
|
-
optional = true
|
|
51
|
-
[tool.poetry.dependencies.pytest-asyncio]
|
|
52
|
-
version = "^0.19.0"
|
|
53
|
-
optional = true
|
|
54
|
-
[tool.poetry.dependencies.pytest-cov]
|
|
55
|
-
version = "^2.10.1"
|
|
56
|
-
optional = true
|
|
57
|
-
[tool.poetry.dependencies.tox]
|
|
58
|
-
version = "^3.26.0"
|
|
59
|
-
optional = true
|
|
60
|
-
[tool.poetry.dependencies.boto3]
|
|
61
|
-
version = "^1.24.74"
|
|
62
|
-
optional = true
|
|
63
|
-
[tool.poetry.dependencies.greenlet]
|
|
64
|
-
version = "^1.1.3"
|
|
65
|
-
optional = true
|
|
66
|
-
[tool.poetry.dependencies.mypy]
|
|
67
|
-
version = "^1.0.0"
|
|
68
|
-
extras = ["tests"]
|
|
69
|
-
optional = true
|
|
70
|
-
[tool.poetry.dependencies.sqlmodel]
|
|
71
|
-
version = "^0.0.14"
|
|
72
|
-
optional = true
|
|
73
|
-
[tool.poetry.extras]
|
|
74
|
-
tests = ["alembic", "asgi_lifespan", "black", "coverage", "Faker", "greenlet", "httpx", "isort", "mypy", "pdbpp", "psycopg2", "pylama", "pytest", "pytest-asyncio", "pytest-cov", "pytest-watch", "tox"]
|
|
75
|
-
asyncpg = ["asyncpg"]
|
|
76
|
-
aws_rds_iam = ["boto3"]
|
|
77
|
-
sqlmodel = ["sqlmodel"]
|
|
78
|
-
[tool.poetry.plugins]
|
|
79
|
-
[tool.poetry.plugins.pytest11]
|
|
80
|
-
fastapi-sqla = "fastapi_sqla._pytest_plugin"
|
|
81
|
-
|
|
82
|
-
[[tool.poetry.source]]
|
|
83
|
-
name = "dialogue-private"
|
|
84
|
-
url = "https://dialogue-527641002329.d.codeartifact.us-east-1.amazonaws.com/pypi/distribution-readonly/simple/"
|
|
85
|
-
default = true
|
|
86
|
-
[tool.semantic_release]
|
|
87
|
-
version_variable = "pyproject.toml:version"
|
|
88
|
-
upload_to_pypi = false
|
|
89
|
-
commit_message = "Version generated by python-semantic-release [ci skip]"
|
|
90
|
-
[tool.pylama]
|
|
91
|
-
paths = "fastapi_sqla tests"
|
|
92
|
-
linters = "pycodestyle,mccabe,pyflakes"
|
|
93
|
-
[tool.pylama.linter]
|
|
94
|
-
[tool.pylama.linter.pycodestyle]
|
|
95
|
-
max_line_length = 88
|
|
96
|
-
[tool.isort]
|
|
97
|
-
profile = "black"
|
|
98
|
-
lines_between_sections = 1
|
|
99
|
-
multi_line_output = 3
|
|
100
|
-
include_trailing_comma = "True"
|
|
101
|
-
line_length = 88
|
|
102
|
-
[tool.pytest]
|
|
103
|
-
[tool.pytest.ini_options]
|
|
104
|
-
asyncio_mode = "auto"
|
|
105
|
-
testpaths = "tests"
|
|
106
|
-
norecursedirs = ".git,.venv"
|
|
107
|
-
xfail_strict = "true"
|
|
108
|
-
addopts = " -p no:fastapi-sqla\n --cov-config pyproject.toml\n --cov-report term\n --cov-report term-missing\n"
|
|
109
|
-
filterwarnings = ["error:.*removed in version 2.0.*:"]
|
|
110
|
-
[tool.pytest-watch]
|
|
111
|
-
[tool.pytest-watch.run]
|
|
112
|
-
ext = ".py, .yaml, .cfg"
|
|
113
|
-
[tool.coverage]
|
|
114
|
-
[tool.coverage.run]
|
|
115
|
-
branch = true
|
|
116
|
-
omit = ["tests/*", ".venv/*"]
|
|
117
|
-
concurrency = ["thread", "greenlet"]
|
|
118
|
-
[tool.coverage.report]
|
|
119
|
-
skip_covered = true
|
|
120
|
-
[tool.tox]
|
|
121
|
-
legacy_tox_ini = "[tox]\nenvlist = sqlalchemy{ 1.3, 1.4, 2.0, 2.0-sqlmodel }-{ asyncpg, noasyncpg }-{aws_rds_iam, noaws_rds_iam }-pydantic{ 1, 2 }\n\n[testenv]\npassenv = CI\ndeps =\n sqlalchemy1.3: sqlalchemy<1.4\n sqlalchemy1.4: sqlalchemy>=1.4,<2\n sqlalchemy2.0: sqlalchemy>=2\n sqlalchemy2.0-sqlmodel: sqlalchemy>=2\n sqlalchemy2.0-sqlmodel: sqlmodel\n asyncpg: asyncpg\n aws_rds_iam: boto3\n pydantic1: pydantic<2\n pydantic2: pydantic>=2\n\nextras =\n tests\n\ncommands = pytest -vv --cov={envsitepackagesdir}/fastapi_sqla --cov-report xml --cov-report html --junitxml=test-reports/pytest/junit.xml\n"
|
|
122
|
-
[tool.black]
|
|
123
|
-
exclude = ".mypy_cache|.pytest_cache|.vscode|.eggs|venv"
|
|
124
|
-
--skip-magic-trailing-comma = true
|
|
125
|
-
[tool.mypy]
|
|
126
|
-
exclude = ["tests"]
|
|
127
|
-
ignore_missing_imports = true
|
|
128
|
-
plugins = "sqlalchemy.ext.mypy.plugin"
|
|
129
|
-
|
|
130
|
-
[build-system]
|
|
131
|
-
requires = ["poetry>=1.3.0"]
|
|
132
|
-
build-backend = "poetry.masonry.api"
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|