Skip to content

Commit d8bac3b

Browse files
authored
Update dependencies, fix project. (#227)
1 parent 4eb58d1 commit d8bac3b

File tree

9 files changed

+523
-464
lines changed

9 files changed

+523
-464
lines changed

.github/workflows/test.yml

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -27,7 +27,7 @@ jobs:
2727
- name: Set up Python
2828
uses: actions/setup-python@v2
2929
with:
30-
python-version: '3.11'
30+
python-version: '3.12'
3131
- name: Install deps
3232
run: |
3333
pip install -U pip
@@ -40,4 +40,4 @@ jobs:
4040
git config --global user.name "fastapi_template"
4141
git config --global user.email "[email protected]"
4242
- name: Run tests
43-
run: pytest -vv
43+
run: pytest -vv -n auto

fastapi_template/input_model.py

Lines changed: 18 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,24 @@
1111
except Exception:
1212
TerminalMenu = None
1313

14+
class BuilderContext(UserDict):
15+
"""Options for project generation."""
16+
17+
def __init__(self, **kwargs: Any) -> None:
18+
self.__dict__["data"] = kwargs
19+
20+
def __getattr__(self, name: str) -> Any:
21+
try:
22+
return self.__dict__["data"][name]
23+
except KeyError:
24+
cls_name = self.__class__.__name__
25+
raise AttributeError(f"'{cls_name}' object has no attribute '{name}'")
26+
27+
def __setattr__(self, name: str, value: Any) -> None:
28+
self[name] = value
29+
30+
def dict(self) -> dict[str, Any]:
31+
return self.__dict__["data"]
1432

1533
class Database(BaseModel):
1634
name: str
@@ -43,7 +61,6 @@ def generated_name(self) -> str:
4361
return self.cli_name
4462
return self.code
4563

46-
4764
SKIP_ENTRY = MenuEntry(
4865
code="skip",
4966
user_view="skip",
@@ -239,21 +256,3 @@ def ask(self, context: "BuilderContext") -> Optional["BuilderContext"]:
239256
return context
240257

241258

242-
class BuilderContext(UserDict):
243-
"""Options for project generation."""
244-
245-
def __init__(self, **kwargs: Any) -> None:
246-
self.__dict__["data"] = kwargs
247-
248-
def __getattr__(self, name: str) -> Any:
249-
try:
250-
return self.__dict__["data"][name]
251-
except KeyError:
252-
cls_name = self.__class__.__name__
253-
raise AttributeError(f"'{cls_name}' object has no attribute '{name}'")
254-
255-
def __setattr__(self, name: str, value: Any) -> None:
256-
self[name] = value
257-
258-
def dict(self) -> dict[str, Any]:
259-
return self.__dict__["data"]

fastapi_template/template/{{cookiecutter.project_name}}/Dockerfile

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
FROM python:3.11.4-slim-bullseye as prod
1+
FROM python:3.11.4-slim-bullseye AS prod
22

33
{%- if cookiecutter.db_info.name == "mysql" %}
44
RUN apt-get update && apt-get install -y \
@@ -42,6 +42,6 @@ RUN --mount=type=cache,target=/tmp/poetry_cache poetry install --only main
4242

4343
CMD ["/usr/local/bin/python", "-m", "{{cookiecutter.project_name}}"]
4444

45-
FROM prod as dev
45+
FROM prod AS dev
4646

4747
RUN --mount=type=cache,target=/tmp/poetry_cache poetry install

fastapi_template/template/{{cookiecutter.project_name}}/pyproject.toml

Lines changed: 55 additions & 51 deletions
Original file line numberDiff line numberDiff line change
@@ -11,144 +11,148 @@ maintainers = [
1111
readme = "README.md"
1212

1313
[tool.poetry.dependencies]
14-
python = "^3.9"
15-
fastapi = "^0.111.0"
16-
uvicorn = { version = "^0.30.1", extras = ["standard"] }
14+
python = ">3.9.1,<4"
15+
fastapi = "^0.115.6"
16+
uvicorn = { version = "^0.34.0", extras = ["standard"] }
1717
{%- if cookiecutter.gunicorn == "True" %}
18-
gunicorn = "^22.0.0"
18+
gunicorn = "^23.0.0"
1919
{%- endif %}
2020
{%- if cookiecutter.add_users == "True" %}
2121
{%- if cookiecutter.orm == "sqlalchemy" %}
22-
fastapi-users = "^13.0.0"
23-
httpx-oauth = "^0.14.1"
22+
fastapi-users = "^14.0.0"
23+
httpx-oauth = "^0.16.1"
2424
fastapi-users-db-sqlalchemy = "^6.0.1"
2525
{%- endif %}
2626
{%- endif %}
27-
pydantic = "^2"
28-
pydantic-settings = "^2"
29-
yarl = "^1"
27+
{%- if cookiecutter.orm == "ormar" %}
28+
pydantic = ">=2.5.3,<2.9.0"
29+
{%- else %}
30+
pydantic = "^2.10.4"
31+
{%- endif %}
32+
pydantic-settings = "^2.7.0"
33+
yarl = "^1.18.3"
3034
ujson = "^5.10.0"
3135
{%- if cookiecutter.orm == "piccolo" %}
3236
{%- if cookiecutter.db_info.name == "postgresql" %}
33-
piccolo = {version = "^1.13.0", extras = ["postgres"]}
37+
piccolo = {version = "^1.22.0", extras = ["postgres"]}
3438
{%- elif cookiecutter.db_info.name == "sqlite" %}
35-
piccolo = {version = "^1.13.0", extras = ["sqlite"]}
39+
piccolo = {version = "^1.22.0", extras = ["sqlite"]}
3640
{%- endif %}
3741
{%- endif %}
3842
{%- if cookiecutter.orm == "sqlalchemy" %}
39-
SQLAlchemy = {version = "^2.0.31", extras = ["asyncio"]}
43+
SQLAlchemy = {version = "^2.0.36", extras = ["asyncio"]}
4044
{%- if cookiecutter.enable_migrations == "True" %}
41-
alembic = "^1.13.2"
45+
alembic = "^1.14.0"
4246
{%- endif %}
4347
{%- if cookiecutter.db_info.name == "postgresql" %}
44-
asyncpg = {version = "^0.29.0", extras = ["sa"]}
48+
asyncpg = {version = "^0.30.0", extras = ["sa"]}
4549
{%- elif cookiecutter.db_info.name == "sqlite" %}
4650
aiosqlite = "^0.20.0"
4751
{%- elif cookiecutter.db_info.name == "mysql" %}
4852
aiomysql = "^0.2.0"
49-
mysqlclient = "^2.2.4"
53+
mysqlclient = "^2.2.6"
5054
{%- endif %}
5155
{%- endif %}
5256
{%- if cookiecutter.orm == "tortoise" %}
53-
tortoise-orm = "^0.21.3"
57+
tortoise-orm = "^0.23.0"
5458
{%- if cookiecutter.enable_migrations == "True" %}
55-
aerich = "^0.7.2"
59+
aerich = "^0.8.0"
5660
{%- endif %}
5761
{%- if cookiecutter.db_info.name == "postgresql" %}
58-
asyncpg = "^0.29.0"
62+
asyncpg = "^0.30.0"
5963
{%- elif cookiecutter.db_info.name == "sqlite" %}
6064
aiosqlite = "<0.20.0"
6165
{%- elif cookiecutter.db_info.name == "mysql" %}
6266
aiomysql = "^0.2.0"
63-
mysqlclient = "^2.2.4"
64-
cryptography = "^42.0.8"
67+
mysqlclient = "^2.2.6"
68+
cryptography = "^44.0.0"
6569
{%- endif %}
6670
{%- endif %}
6771
{%- if cookiecutter.orm == "ormar" %}
68-
ormar = "^0.20.1"
72+
ormar = "^0.20.2"
6973
{%- if cookiecutter.enable_migrations == "True" %}
70-
alembic = "^1.13.2"
74+
alembic = "^1.14.0"
7175
{%- endif %}
7276
{%- if cookiecutter.db_info.name == "postgresql" %}
73-
asyncpg = "^0.29.0"
74-
psycopg2-binary = "^2.9.9"
77+
asyncpg = "^0.30.0"
78+
psycopg2-binary = "^2.9.10"
7579
{%- elif cookiecutter.db_info.name == "sqlite" %}
7680
aiosqlite = "^0.20.0"
7781
{%- elif cookiecutter.db_info.name == "mysql" %}
7882
aiomysql = "^0.2.0"
79-
mysqlclient = "^2.2.4"
83+
mysqlclient = "^2.2.6"
8084
{%- endif %}
8185
{%- endif %}
8286
{%- if cookiecutter.enable_redis == "True" %}
83-
redis = {version = "^5.0.7", extras = ["hiredis"]}
87+
redis = {version = "^5.2.1", extras = ["hiredis"]}
8488
{%- endif %}
8589
{%- if cookiecutter.self_hosted_swagger == 'True' %}
8690
aiofiles = "^24.1.0"
8791
{%- endif %}
8892
{%- if cookiecutter.orm == "psycopg" %}
89-
psycopg = { version = "^3.1.19", extras = ["binary", "pool"] }
93+
psycopg = { version = "^3.2.3", extras = ["binary", "pool"] }
9094
{%- endif %}
91-
httptools = "^0.6.1"
95+
httptools = "^0.6.4"
9296
{%- if cookiecutter.orm == "beanie" %}
93-
beanie = "^1.26.0"
97+
beanie = "^1.28.0"
9498
{%- else %}
95-
pymongo = "^4.8.0"
99+
pymongo = "^4.10.1"
96100
{%- endif %}
97101
{%- if cookiecutter.api_type == "graphql" %}
98-
strawberry-graphql = { version = "^0.235.1", extras = ["fastapi"] }
102+
strawberry-graphql = { version = "^0.256.1", extras = ["fastapi"] }
99103
{%- endif %}
100104
{%- if cookiecutter.enable_rmq == "True" %}
101-
aio-pika = "^9.4.1"
105+
aio-pika = "^9.5.4"
102106
{%- endif %}
103107
{%- if cookiecutter.prometheus_enabled == "True" %}
104-
prometheus-client = "^0.20.0"
108+
prometheus-client = "^0.21.1"
105109
prometheus-fastapi-instrumentator = "7.0.0"
106110
{%- endif %}
107111
{%- if cookiecutter.sentry_enabled == "True" %}
108-
sentry-sdk = "^2.7.1"
112+
sentry-sdk = "^2.19.2"
109113
{%- endif %}
110114
{%- if cookiecutter.otlp_enabled == "True" %}
111-
opentelemetry-api = "^1.25.0"
112-
opentelemetry-sdk = "^1.25.0"
113-
opentelemetry-exporter-otlp = "^1.25.0"
114-
opentelemetry-instrumentation = "^0.46b0"
115-
opentelemetry-instrumentation-fastapi = "^0.46b0"
115+
opentelemetry-api = "^1.29.0"
116+
opentelemetry-sdk = "^1.29.0"
117+
opentelemetry-exporter-otlp = "^1.29.0"
118+
opentelemetry-instrumentation = "^0.50b0"
119+
opentelemetry-instrumentation-fastapi = "^0.50b0"
116120
{%- if cookiecutter.enable_loguru != "True" %}
117-
opentelemetry-instrumentation-logging = "^0.46b0"
121+
opentelemetry-instrumentation-logging = "^0.50b0"
118122
{%- endif %}
119123
{%- if cookiecutter.enable_redis == "True" %}
120-
opentelemetry-instrumentation-redis = "^0.46b0"
124+
opentelemetry-instrumentation-redis = "^0.50b0"
121125
{%- endif %}
122126
{%- if cookiecutter.db_info.name == "postgresql" and cookiecutter.orm in ["ormar", "tortoise"] %}
123-
opentelemetry-instrumentation-asyncpg = "^0.46b0"
127+
opentelemetry-instrumentation-asyncpg = "^0.50b0"
124128
{%- endif %}
125129
{%- if cookiecutter.orm == "sqlalchemy" %}
126-
opentelemetry-instrumentation-sqlalchemy = "^0.46b0"
130+
opentelemetry-instrumentation-sqlalchemy = "^0.50b0"
127131
{%- endif %}
128132
{%- if cookiecutter.enable_rmq == "True" %}
129-
opentelemetry-instrumentation-aio-pika = "^0.46b0"
133+
opentelemetry-instrumentation-aio-pika = "^0.50b0"
130134
{%- endif %}
131135
{%- endif %}
132136
{%- if cookiecutter.enable_loguru == "True" %}
133-
loguru = "^0"
137+
loguru = "^0.7.3"
134138
{%- endif %}
135139
{%- if cookiecutter.enable_kafka == "True" %}
136-
aiokafka = "^0"
140+
aiokafka = "^0.12.0"
137141
{%- endif %}
138142
{%- if cookiecutter.enable_taskiq == "True" %}
139-
taskiq = "^0"
140-
taskiq-fastapi = "^0"
143+
taskiq = "^0.11.10"
144+
taskiq-fastapi = "^0.3.3"
141145

142146
{%- if cookiecutter.enable_redis == "True" %}
143-
taskiq-redis = "^1"
147+
taskiq-redis = "^1.0.2"
144148
{%- endif %}
145149

146150
{%- if cookiecutter.enable_rmq == "True" %}
147-
taskiq-aio-pika = "^0"
151+
taskiq-aio-pika = "^0.4.1"
148152
{%- endif %}
149153

150154
{%- if (cookiecutter.enable_rmq or cookiecutter.enable_rmq) != "True" %}
151-
pyzmq = "^26"
155+
pyzmq = "^26.2.0"
152156
{%- endif %}
153157

154158
{%- endif %}

fastapi_template/template/{{cookiecutter.project_name}}/tests/conftest.py

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -161,7 +161,7 @@ async def initialize_db() -> AsyncGenerator[None, None]:
161161

162162
{%- elif cookiecutter.orm == "ormar" %}
163163

164-
@pytest.fixture(autouse=True)
164+
@pytest.fixture(autouse=True, scope="function")
165165
async def initialize_db() -> AsyncGenerator[None, None]:
166166
"""
167167
Create models and databases.
@@ -186,6 +186,11 @@ async def initialize_db() -> AsyncGenerator[None, None]:
186186
yield
187187

188188
await database.disconnect()
189+
190+
engine = create_engine(str(settings.db_url))
191+
with engine.begin() as conn:
192+
meta.drop_all(conn)
193+
engine.dispose()
189194
drop_database()
190195

191196
{%- elif cookiecutter.orm == "psycopg" %}

fastapi_template/template/{{cookiecutter.project_name}}/tests/test_dummy.py

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -65,7 +65,6 @@ async def test_creation(
6565
await dao.delete_dummy_model_by_name(name=test_name)
6666
{%- endif %}
6767

68-
6968
@pytest.mark.anyio
7069
async def test_getting(
7170
fastapi_app: FastAPI,
@@ -85,6 +84,9 @@ async def test_getting(
8584
dao = DummyDAO()
8685
{%- endif %}
8786
test_name = uuid.uuid4().hex
87+
88+
assert not await dao.filter()
89+
8890
await dao.create_dummy_model(name=test_name)
8991

9092
{%- if cookiecutter.api_type == 'rest' %}

fastapi_template/template/{{cookiecutter.project_name}}/{{cookiecutter.project_name}}/db_ormar/utils.py

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -78,10 +78,11 @@ def drop_database() -> None:
7878
{%- if cookiecutter.db_info.name == "sqlite" %}
7979
def create_database() -> None:
8080
"""Create a database."""
81+
drop_database()
82+
Path(settings.db_file).touch()
8183

8284
def drop_database() -> None:
8385
"""Drop current database."""
84-
if settings.db_file.exists():
85-
Path(settings.db_file).unlink()
86+
Path(settings.db_file).unlink(missing_ok=True)
8687

8788
{%- endif %}

fastapi_template/tests/utils.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -22,7 +22,7 @@ def run_pre_commit() -> int:
2222
def run_docker_compose_command(
2323
command: Optional[str] = None,
2424
) -> subprocess.CompletedProcess:
25-
docker_command = ["docker-compose"]
25+
docker_command = ["docker", "compose"]
2626
if command:
2727
docker_command.extend(shlex.split(command))
2828
else:

0 commit comments

Comments
 (0)