fastapi-sqla 3.2.1__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.2.1 → fastapi_sqla-3.3.0}/PKG-INFO +29 -5
- {fastapi_sqla-3.2.1 → fastapi_sqla-3.3.0}/README.md +27 -4
- {fastapi_sqla-3.2.1 → fastapi_sqla-3.3.0}/fastapi_sqla/__init__.py +3 -1
- {fastapi_sqla-3.2.1 → fastapi_sqla-3.3.0}/fastapi_sqla/base.py +28 -0
- {fastapi_sqla-3.2.1 → fastapi_sqla-3.3.0}/pyproject.toml +68 -69
- {fastapi_sqla-3.2.1 → fastapi_sqla-3.3.0}/LICENSE +0 -0
- {fastapi_sqla-3.2.1 → fastapi_sqla-3.3.0}/fastapi_sqla/_pytest_plugin.py +0 -0
- {fastapi_sqla-3.2.1 → fastapi_sqla-3.3.0}/fastapi_sqla/async_pagination.py +0 -0
- {fastapi_sqla-3.2.1 → fastapi_sqla-3.3.0}/fastapi_sqla/async_sqla.py +0 -0
- {fastapi_sqla-3.2.1 → fastapi_sqla-3.3.0}/fastapi_sqla/aws_aurora_support.py +0 -0
- {fastapi_sqla-3.2.1 → fastapi_sqla-3.3.0}/fastapi_sqla/aws_rds_iam_support.py +0 -0
- {fastapi_sqla-3.2.1 → fastapi_sqla-3.3.0}/fastapi_sqla/models.py +0 -0
- {fastapi_sqla-3.2.1 → fastapi_sqla-3.3.0}/fastapi_sqla/pagination.py +0 -0
- {fastapi_sqla-3.2.1 → fastapi_sqla-3.3.0}/fastapi_sqla/py.typed +0 -0
- {fastapi_sqla-3.2.1 → fastapi_sqla-3.3.0}/fastapi_sqla/sqla.py +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
|
|
@@ -42,6 +42,7 @@ Requires-Dist: alembic (>=1.4.3,<2.0.0) ; extra == "tests"
|
|
|
42
42
|
Requires-Dist: asgi_lifespan (>=1.0.1,<2.0.0) ; extra == "tests"
|
|
43
43
|
Requires-Dist: asyncpg (>=0.28.0,<0.29.0) ; extra == "asyncpg"
|
|
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
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"
|
|
@@ -89,15 +90,22 @@ unique `email`:
|
|
|
89
90
|
|
|
90
91
|
```python
|
|
91
92
|
# main.py
|
|
93
|
+
from contextlib import asynccontextmanager
|
|
92
94
|
from fastapi import FastAPI, HTTPException
|
|
93
|
-
from fastapi_sqla import Base, Item, Page, Paginate, Session,
|
|
95
|
+
from fastapi_sqla import Base, Item, Page, Paginate, Session, setup_middlewares, startup
|
|
94
96
|
from pydantic import BaseModel, EmailStr
|
|
95
97
|
from sqlalchemy import select
|
|
96
98
|
from sqlalchemy.exc import IntegrityError
|
|
97
99
|
|
|
98
|
-
app = FastAPI()
|
|
99
100
|
|
|
100
|
-
|
|
101
|
+
@asynccontextmanager
|
|
102
|
+
async def lifespan(app: FastAPI):
|
|
103
|
+
await startup()
|
|
104
|
+
yield
|
|
105
|
+
|
|
106
|
+
|
|
107
|
+
app = FastAPI(lifespan=lifespan)
|
|
108
|
+
setup_middlewares(app)
|
|
101
109
|
|
|
102
110
|
|
|
103
111
|
class User(Base):
|
|
@@ -202,7 +210,23 @@ And define the environment variable `sqlalchemy_url` with `postgres+asyncpg` sch
|
|
|
202
210
|
export sqlalchemy_url=postgresql+asyncpg://postgres@localhost
|
|
203
211
|
```
|
|
204
212
|
|
|
205
|
-
## 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):
|
|
206
230
|
|
|
207
231
|
```python
|
|
208
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
|
|
|
@@ -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}
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
[tool.poetry]
|
|
2
2
|
name = "fastapi-sqla"
|
|
3
|
-
version = "3.
|
|
3
|
+
version = "3.3.0"
|
|
4
4
|
description = "SQLAlchemy extension for FastAPI with support for pagination, asyncio, SQLModel, and pytest, ready for production."
|
|
5
5
|
authors = [
|
|
6
6
|
"Hadrien David <hadrien.david@dialogue.co>",
|
|
@@ -43,22 +43,23 @@ fastapi = ">=0.95.1"
|
|
|
43
43
|
pydantic = ">=1"
|
|
44
44
|
sqlalchemy = ">=1.3"
|
|
45
45
|
structlog = ">=20"
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
pytest
|
|
56
|
-
pytest-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
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 }
|
|
62
63
|
sqlmodel = { version = "^0.0.14", optional = true }
|
|
63
64
|
|
|
64
65
|
[tool.poetry.extras]
|
|
@@ -102,58 +103,58 @@ target-version = "py39"
|
|
|
102
103
|
|
|
103
104
|
[tool.ruff.lint]
|
|
104
105
|
select = [
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
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
|
|
121
122
|
]
|
|
122
123
|
|
|
123
124
|
# Ignore some pydocstyle rules that Google convention enables
|
|
124
125
|
ignore = [
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
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
|
|
149
150
|
]
|
|
150
151
|
|
|
151
152
|
[tool.ruff.lint.extend-per-file-ignores]
|
|
152
153
|
"tests/*" = [
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
|
|
154
|
+
"S101", # Enable assert
|
|
155
|
+
"S105", # Disable passwords check
|
|
156
|
+
"S106", # Disable passwords check
|
|
157
|
+
"S608", # Allow SQL string construction
|
|
157
158
|
]
|
|
158
159
|
|
|
159
160
|
[tool.ruff.lint.pydocstyle]
|
|
@@ -172,19 +173,14 @@ addopts = """
|
|
|
172
173
|
"""
|
|
173
174
|
|
|
174
175
|
# https://nedbatchelder.com/blog/201810/why_warnings_is_mysterious.html
|
|
175
|
-
filterwarnings = [
|
|
176
|
-
"error:.*removed in version 2.0.*:",
|
|
177
|
-
]
|
|
176
|
+
filterwarnings = ["error:.*removed in version 2.0.*:"]
|
|
178
177
|
|
|
179
178
|
[tool.pytest-watch.run]
|
|
180
179
|
ext = ".py, .yaml, .cfg"
|
|
181
180
|
|
|
182
181
|
[tool.coverage.run]
|
|
183
182
|
branch = true
|
|
184
|
-
omit = [
|
|
185
|
-
"tests/*",
|
|
186
|
-
".venv/*"
|
|
187
|
-
]
|
|
183
|
+
omit = ["tests/*", ".venv/*"]
|
|
188
184
|
concurrency = ["thread", "greenlet"]
|
|
189
185
|
|
|
190
186
|
[tool.coverage.report]
|
|
@@ -216,5 +212,8 @@ commands = pytest -vv --cov={envsitepackagesdir}/fastapi_sqla --cov-report xml -
|
|
|
216
212
|
|
|
217
213
|
[tool.mypy]
|
|
218
214
|
exclude = ["tests"]
|
|
215
|
+
plugins = ["sqlalchemy.ext.mypy.plugin"]
|
|
216
|
+
|
|
217
|
+
[[tool.mypy.overrides]]
|
|
218
|
+
module = ["asyncpg", "boto3", "deprecated"]
|
|
219
219
|
ignore_missing_imports = true
|
|
220
|
-
plugins = "sqlalchemy.ext.mypy.plugin"
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|