Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
9 changes: 6 additions & 3 deletions .github/workflows/tests.yml
Original file line number Diff line number Diff line change
Expand Up @@ -2,9 +2,12 @@ name: tests
on:
push:
branches:
- "**"
- "main"
tags-ignore:
- "*.*"
pull_request:
branches:
- "**"

jobs:
tests:
Expand All @@ -30,9 +33,9 @@ jobs:
python-version-file: "pyproject.toml"

- name: Install uv
uses: astral-sh/setup-uv@v7
uses: astral-sh/setup-uv@v10.3.2
with:
version: "0.9.2"
version: "0.13.5"
enable-cache: true

- name: Install the project
Expand Down
12 changes: 7 additions & 5 deletions .github/workflows/type_check.yml
Original file line number Diff line number Diff line change
Expand Up @@ -2,15 +2,17 @@ name: type-check
on:
push:
branches:
- "**"
- "main"
tags-ignore:
- "*.*"

pull_request:
branches:
- "**"
jobs:
type_check:
strategy:
matrix:
check: ["ruff check", "mypy --check", "ruff format --check"]
check: ["ruff check", "mypy", "ruff format --check"]

runs-on: ubuntu-latest
steps:
Expand All @@ -22,9 +24,9 @@ jobs:
python-version-file: "pyproject.toml"

- name: Install uv
uses: astral-sh/setup-uv@v7
uses: astral-sh/setup-uv@v10.3.2
with:
version: "0.9.2"
version: "0.13.5"
enable-cache: true

- name: Install the project
Expand Down
4 changes: 2 additions & 2 deletions .pre-commit-config.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -5,12 +5,12 @@ repos:
- id: check-yaml

- repo: https://github.com/astral-sh/ruff-pre-commit
rev: v0.15.0
rev: v0.17.2
hooks:
- id: ruff-format

- repo: https://github.com/astral-sh/ruff-pre-commit
rev: v0.15.0
rev: v0.17.2
hooks:
- id: ruff-check
args: [--fix]
4 changes: 2 additions & 2 deletions Dockerfile
Original file line number Diff line number Diff line change
@@ -1,11 +1,11 @@
FROM python:3.14-slim-trixie AS base
FROM python:3.15.1-slim-trixie AS base

ENV PYTHONUNBUFFERED=1
WORKDIR /build

# Create requirements.txt file
FROM base AS uv
COPY --from=ghcr.io/astral-sh/uv:0.9.2 /uv /uvx /bin/
COPY --from=ghcr.io/astral-sh/uv:0.13.5 /uv /uvx /bin/
COPY uv.lock pyproject.toml ./
RUN uv export --no-dev --no-hashes -o /requirements.txt --no-install-workspace --frozen
RUN uv export --only-group dev --no-hashes -o /requirements-dev.txt --no-install-workspace --frozen
Expand Down
18 changes: 7 additions & 11 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@

[![Live example](https://img.shields.io/badge/live%20example-https%3A%2F%2Fminimal--fastapi--postgres--template.rafsaf.pl-blueviolet)](https://minimal-fastapi-postgres-template.rafsaf.pl/)
[![License](https://img.shields.io/github/license/rafsaf/minimal-fastapi-postgres-template)](https://github.com/rafsaf/minimal-fastapi-postgres-template/blob/main/LICENSE)
[![Python 3.14](https://img.shields.io/badge/python-3.14-blue)](https://docs.python.org/3/whatsnew/3.14.html)
[![Python 3.15](https://img.shields.io/badge/python-3.15-blue)](https://docs.python.org/3/whatsnew/3.15.html)
[![Ruff](https://img.shields.io/endpoint?url=https://raw.githubusercontent.com/astral-sh/ruff/main/assets/badge/v2.json)](https://github.com/astral-sh/ruff)
[![Tests](https://github.com/rafsaf/minimal-fastapi-postgres-template/actions/workflows/tests.yml/badge.svg)](https://github.com/rafsaf/minimal-fastapi-postgres-template/actions/workflows/tests.yml)

Expand Down Expand Up @@ -72,7 +72,7 @@ uv sync

```

Uv should automatically install Python version currently required by template (>=3.14) or use existing Python installation if you already have it.
Uv should automatically install Python version currently required by template (>=3.15) or use existing Python installation if you already have it.

### 3. Run app

Expand Down Expand Up @@ -100,6 +100,8 @@ You should then use `git init` (if needed) to initialize git repository and acce

[pre-commit](https://pre-commit.com/) is de facto standard now for pre push activities like isort or black or its nowadays replacement ruff.

It's best to install it using `apt`, `brew` or equivalent on your system.

Refer to `.pre-commit-config.yaml` file to see my current opinionated choices.

```bash
Expand Down Expand Up @@ -168,7 +170,6 @@ class Pet(Base):
sa.ForeignKey("auth_user.user_id", ondelete="CASCADE"),
)
pet_name: Mapped[str] = mapped_column(sa.String(50), nullable=False)

```

Note, we are using super powerful SQLAlchemy feature here - `Mapped` and `mapped_column` were first introduced in SQLAlchemy 2.0, if this syntax is new for you, read carefully [what's new](https://docs.sqlalchemy.org/en/20/changelog/whatsnew_20.html) part of documentation.
Expand All @@ -180,12 +181,11 @@ Without this step, alembic won't be able to follow changes in new `models.py` fi
```python
# alembic/env.py

(...)
(...)
# import other models here
import app.pets.models # noqa

(...)

```

### 4. Create and apply alembic migration
Expand Down Expand Up @@ -230,7 +230,6 @@ class PetResponse(BaseModel):
user_id: str

model_config = ConfigDict(from_attributes=True)

```

### 6. Create endpoints
Expand Down Expand Up @@ -285,7 +284,6 @@ async def get_all_my_pets(
)

return list(pets.all())

```

Now we need to add newly created router to `main.py` app.
Expand All @@ -300,7 +298,6 @@ from app.pets.views import router as pets_router
(...)

app.include_router(pets_router, prefix="/pets", tags=["pets"])

```

### 7. Add Pet model to tests factories
Expand All @@ -315,9 +312,9 @@ from app.pets.models import Pet

(...)


class PetFactory(SQLAlchemyFactory[Pet]):
pet_name = Use(Faker().first_name)

```

### 8. Create new test file
Expand Down Expand Up @@ -384,7 +381,6 @@ async def test_get_all_my_pets(
"id": pet2.id,
},
]

```

## Design choices
Expand Down Expand Up @@ -418,7 +414,7 @@ Docs page is simply `/` (by default in FastAPI it is `/docs`). You can change it
```python
app = FastAPI(
title="minimal fastapi postgres template",
version="7.0.0",
version="8.0.0",
description="https://github.com/rafsaf/minimal-fastapi-postgres-template",
openapi_url="/openapi.json",
docs_url="/",
Expand Down
2 changes: 1 addition & 1 deletion app/main.py
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@

app = FastAPI(
title="minimal fastapi postgres template",
version="7.0.0",
version="8.0.0",
description="https://github.com/rafsaf/minimal-fastapi-postgres-template",
openapi_url="/openapi.json",
docs_url="/",
Expand Down
43 changes: 21 additions & 22 deletions pyproject.toml
Original file line number Diff line number Diff line change
@@ -1,37 +1,36 @@
[project]
authors = [{ name = "admin", email = "admin@example.com" }]
dependencies = [
"alembic>=1.18.3",
"asyncpg>=0.31.0",
"alembic>=1.20.1",
"asyncpg>=0.32.0",
"bcrypt>=5.0.0",
"fastapi>=0.128.0",
"prometheus-client>=0.24.1",
"pydantic-settings>=2.12.0",
"pydantic[email]>=2.12.5",
"pyjwt>=2.11.0",
"python-multipart>=0.0.22",
"sqlalchemy[asyncio]>=2.0.46",
"fastapi>=0.162.0",
"prometheus-client>=0.26.0",
"pydantic-settings>=2.16.1",
"pydantic[email]>=2.14.1",
"pyjwt>=2.15.1",
"python-multipart>=0.0.32",
"sqlalchemy[asyncio]>=2.1.6",
]
description = "FastAPI project generated using minimal-fastapi-postgres-template."
name = "app"
requires-python = ">=3.14,<3.15"
requires-python = ">=3.15,<3.16"
version = "0.1.0-alpha"

[dependency-groups]
dev = [
"coverage>=7.13.2",
"coverage>=7.17.0",
"freezegun>=1.5.5",
"greenlet>=3.3.1",
"greenlet>=3.5.6",
"httpx>=0.28.1",
"mypy>=1.19.1",
"polyfactory>=3.2.0",
"pre-commit>=4.5.1",
"pytest-asyncio>=1.3.0",
"pytest-cov>=7.0.0",
"mypy>=2.4.0",
"polyfactory>=3.5.0",
"pytest-asyncio>=1.4.1",
"pytest-cov>=7.1.0",
"pytest-xdist>=3.8.0",
"pytest>=9.0.2",
"ruff>=0.14.14",
"uvicorn[standard]>=0.40.0",
"pytest>=9.1.1",
"ruff>=0.17.2",
"uvicorn>=0.54.0",
]

[tool.uv]
Expand All @@ -56,11 +55,11 @@ source = ["app"]
[tool.mypy]
exclude = [".venv", "alembic"]
files = "app/**"
python_version = "3.14"
python_version = "3.15"
strict = true

[tool.ruff]
target-version = "py314"
target-version = "py315"

[tool.ruff.lint]
# pycodestyle, pyflakes, isort, pylint, pyupgrade
Expand Down
Loading
Loading