Skip to content

Commit ec3f947

Browse files
authored
18 update dependencies (#19)
* use uv instead of poetry. update pyproject.toml * update args in pre-commit * Switch to uv in Dockerfile * update frontend deps. udpate esling config * fix errors due to mui v7 and react-router v7 * add hydratefallback component * fix some typing issues and remove with provider when using fastapi_sso * update docker config * update github test workflow to use uv * bump version to 1.3.0
1 parent d49a741 commit ec3f947

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

41 files changed

+5436
-3493
lines changed

.github/workflows/test.yml

Lines changed: 17 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,7 @@ on:
1313
- main
1414

1515
env: # environment variables (available in any part of the action)
16-
NODE_VERSION: 21
16+
NODE_VERSION: 22
1717
PYTHON_VERSION: 3.12
1818
MONGODB_VERSION: 8.0
1919

@@ -53,10 +53,19 @@ jobs:
5353
- name: Check out Git repository
5454
uses: actions/checkout@v4
5555

56-
- name: Run black
57-
uses: psf/black@stable
56+
- name: Install uv
57+
uses: astral-sh/setup-uv@v5
5858
with:
59-
options: "--config backend/pyproject.toml"
59+
enable-cache: true
60+
61+
- name: Run black
62+
run: uv run --group dev black --check --config ./pyproject.toml .
63+
64+
- name: Run mypy
65+
run: uv run --group dev mypy --config-file=pyproject.toml
66+
67+
- name: Run ruff
68+
run: uv run --group dev ruff check
6069

6170
test-backend:
6271
name: Run backend unit tests
@@ -70,28 +79,18 @@ jobs:
7079
- name: Git checkout
7180
uses: actions/checkout@v4
7281

73-
- name: Install poetry
74-
run: pipx install poetry
75-
76-
- name: Set up Python
77-
uses: actions/setup-python@v5
82+
- name: Install uv
83+
uses: astral-sh/setup-uv@v5
7884
with:
79-
python-version: ${{ env.PYTHON_VERSION }}
80-
cache: "poetry"
85+
enable-cache: true
8186

8287
- name: Start MongoDB
8388
uses: supercharge/[email protected]
8489
with:
8590
mongodb-version: ${{ env.MONGODB_VERSION }}
8691

87-
# Install dependencies. `--no-root` means "install all dependencies but not the project
88-
# itself", which is what you want to avoid caching _your_ code. The `if` statement
89-
# ensures this only runs on a cache miss.
90-
- name: Install dependencies
91-
run: poetry install --no-interaction --no-root --with dev
92-
9392
- name: Test with pytest
94-
run: poetry run pytest --cov=app tests --cov-report html
93+
run: uv run --group dev pytest --cov=app tests --cov-report html
9594

9695
# upload-artifact action does not take into account working-directory default
9796
# see https://github.com/actions/upload-artifact/issues/232

.gitignore

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1 +1,4 @@
11
.vscode
2+
.mypy_cache
3+
.pytest_cache
4+
.ruff_cache

.pre-commit-config.yaml

Lines changed: 12 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -2,39 +2,36 @@ default_language_version:
22
python: python3.12
33

44
repos:
5+
# general checks (see here: https://pre-commit.com/hooks.html
56
- repo: https://github.com/pre-commit/pre-commit-hooks
67
rev: v4.6.0
78
hooks:
8-
- id: check-added-large-files
9-
- id: check-toml
109
- id: check-yaml
1110
args: [--allow-multiple-documents]
1211
- id: end-of-file-fixer
1312
- id: trailing-whitespace
1413

14+
# black - formatting
1515
- repo: https://github.com/psf/black
16-
rev: 24.8.0
16+
rev: 25.1.0
1717
hooks:
1818
- id: black
1919
name: black
20-
args:
21-
- "--config"
22-
- "./backend/pyproject.toml"
20+
args: [--config=./backend/pyproject.toml]
2321

22+
# ruff - linting
2423
- repo: https://github.com/astral-sh/ruff-pre-commit
25-
rev: v0.6.9
24+
rev: "v0.11.10"
2625
hooks:
27-
# Run the linter.
2826
- id: ruff
29-
# Run the formatter.
30-
- id: ruff-format
27+
name: ruff
28+
args: [--config=./backend/pyproject.toml]
3129

30+
# mypy - lint-like type checking
3231
- repo: https://github.com/pre-commit/mirrors-mypy
33-
rev: v1.11.2
32+
rev: v1.15.0
3433
hooks:
3534
- id: mypy
3635
name: mypy
37-
args:
38-
- "--config"
39-
- "./backend/pyproject.toml"
40-
- "--ignore-missing-imports"
36+
additional_dependencies: [types-requests==2.32.0.20250515]
37+
args: [--config-file=./backend/pyproject.toml, --ignore-missing-imports]

README.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@
33
![Tests](https://github.com/jonasrenault/fastapi-react-mongodb-docker/actions/workflows/test.yml/badge.svg)
44
![Build](https://github.com/jonasrenault/fastapi-react-mongodb-docker/actions/workflows/build.yml/badge.svg)
55
[![License](https://img.shields.io/badge/License-MIT-yellow)](LICENSE)
6-
![python_version](https://img.shields.io/badge/Python-%3E=3.10-blue)
6+
![python_version](https://img.shields.io/badge/Python-%3E=3.12-blue)
77

88
This is a template application for a FARM stack. FARM stands for FastAPI, React, MongoDB.
99

backend/Dockerfile

Lines changed: 29 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -1,19 +1,40 @@
1-
FROM python:3.12-slim
1+
FROM python:3.12-slim-bookworm
22

33
ENV PYTHONUNBUFFERED=true
44

55
WORKDIR /app
66

7-
### install poetry
8-
RUN pip install poetry && poetry config virtualenvs.in-project true
7+
# Install uv
8+
# Ref: https://docs.astral.sh/uv/guides/integration/docker/#installing-uv
9+
COPY --from=ghcr.io/astral-sh/uv:0.5.11 /uv /uvx /bin/
910

10-
### install dependencies and project
11+
# Place executables in the environment at the front of the path
12+
# Ref: https://docs.astral.sh/uv/guides/integration/docker/#using-the-environment
13+
ENV PATH="/app/.venv/bin:$PATH"
14+
15+
# Compile bytecode
16+
# Ref: https://docs.astral.sh/uv/guides/integration/docker/#compiling-bytecode
17+
ENV UV_COMPILE_BYTECODE=1
18+
19+
# uv Cache
20+
# Ref: https://docs.astral.sh/uv/guides/integration/docker/#caching
21+
ENV UV_LINK_MODE=copy
22+
23+
# Install dependencies
24+
# Ref: https://docs.astral.sh/uv/guides/integration/docker/#intermediate-layers
25+
RUN --mount=type=cache,target=/root/.cache/uv \
26+
--mount=type=bind,source=uv.lock,target=uv.lock \
27+
--mount=type=bind,source=pyproject.toml,target=pyproject.toml \
28+
uv sync --frozen --no-install-project
29+
30+
# Copy the project into the image
1131
ADD pyproject.toml README.md ./
1232
ADD app /app/app
13-
RUN poetry install --no-interaction --no-ansi
1433

15-
### add executables to path
16-
ENV PATH="/app/.venv/bin:$PATH"
34+
# Sync the project
35+
# Ref: https://docs.astral.sh/uv/guides/integration/docker/#intermediate-layers
36+
RUN --mount=type=cache,target=/root/.cache/uv \
37+
uv sync
1738

18-
### default cmd: run fastapi with 4 workers
39+
# default cmd: run fastapi with 4 workers
1940
CMD ["fastapi", "run", "--workers", "4", "app/main.py"]

backend/README.md

Lines changed: 5 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -4,26 +4,22 @@ This directory contains the backend API app. It is built with [FastAPI](https://
44

55
## Requirements
66

7-
* [Poetry](https://python-poetry.org/) for Python package and environment management.
7+
* [uv](https://docs.astral.sh/uv/) for Python package and environment management.
88
* A [MongoDB](https://www.mongodb.com/) database for persistence.
99

1010
## Install
1111

12-
The project uses poetry to manage dependencies and run the backend application. You can use an other tool to manage your virtual environment, such as `pip` or [uv](https://docs.astral.sh/uv/), but you'll need to extract the dependencies from the [pyproject.toml](./pyproject.toml) file.
13-
14-
If using poetry, for convenience, run `poetry config virtualenvs.in-project true` before installing depencies. This will install the dependencies in the project directory and make it easier to manage in vscode.
15-
16-
You can then install the dependencies with `poetry install --with dev`.
12+
The project uses [uv](https://docs.astral.sh/uv/) to manage dependencies and run the backend application. You can install the project and its dependencies with `uv sync`.
1713

1814
## Running the server
1915

2016
To start a development server, run
2117

2218
```console
23-
poetry run fastapi dev app/main.py
19+
uv run fastapi dev app/main.py
2420
```
2521

26-
from the `backend` directory (remove the `poetry run` prefix if using another dependency management tool).
22+
from the `backend` directory (remove the `uv run` prefix if using another dependency management tool).
2723

2824
This will start a server running on `http://127.0.0.1:8000`. The API will be available on the API's base prefix, which by default is `/api/v1`.
2925

@@ -36,7 +32,7 @@ Navigate to `http://localhost:8000/redoc` to access the API's alternative doc bu
3632
Run
3733

3834
```console
39-
poetry run pytest
35+
uv run pytest
4036
```
4137

4238
to run the unit tests for the backend app.

backend/app/auth/auth.py

Lines changed: 7 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -75,12 +75,14 @@ def verify_password(password: str, hashed_pass: str) -> bool:
7575
return password_context.verify(password, hashed_pass)
7676

7777

78-
async def authenticate_user(email: str, password: str):
78+
async def authenticate_user(email: str, password: str) -> models.User | None:
7979
user = await models.User.find_one({"email": email})
8080
if not user:
81-
return False
82-
if not verify_password(password, user.hashed_password):
83-
return False
81+
return None
82+
if user.hashed_password is None or not verify_password(
83+
password, user.hashed_password
84+
):
85+
return None
8486
return user
8587

8688

@@ -112,7 +114,7 @@ async def _get_current_user(token):
112114
)
113115
try:
114116
payload = jwt.decode(token, settings.SECRET_KEY, algorithms=[ALGORITHM])
115-
userid: UUID = payload.get("sub")
117+
userid: UUID | None = payload.get("sub")
116118
if userid is None:
117119
raise credentials_exception
118120
token_data = schemas.TokenPayload(uuid=userid)

backend/app/routers/login.py

Lines changed: 3 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -35,7 +35,7 @@ async def login_access_token(form_data: OAuth2PasswordRequestForm = Depends()) -
3535
OAuth2 compatible token login, get an access token for future requests
3636
"""
3737
user = await authenticate_user(form_data.username, form_data.password)
38-
if not user:
38+
if user is None:
3939
raise HTTPException(status_code=400, detail="Incorrect email or password")
4040
elif not user.is_active:
4141
raise HTTPException(status_code=400, detail="Inactive user")
@@ -79,8 +79,7 @@ async def google_login(google_sso: GoogleSSO = Depends(get_google_sso)):
7979
"""
8080
Generate login url and redirect
8181
"""
82-
with google_sso:
83-
return await google_sso.get_login_redirect()
82+
return await google_sso.get_login_redirect()
8483

8584

8685
@router.get("/google/callback")
@@ -97,8 +96,7 @@ async def google_callback(
9796
)
9897

9998
# Get user details from Google
100-
with google_sso:
101-
google_user = await google_sso.verify_and_process(request)
99+
google_user = await google_sso.verify_and_process(request)
102100

103101
if google_user is None:
104102
raise HTTPException(

0 commit comments

Comments
 (0)