Skip to content

Commit 3cf67c9

Browse files
authored
Merge pull request #34 from rafsaf/release-5.0
Release 5.0
2 parents 91a3596 + c118cf6 commit 3cf67c9

File tree

15 files changed

+887
-991
lines changed

15 files changed

+887
-991
lines changed

.github/workflows/build_docker_image.yml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -19,7 +19,7 @@ jobs:
1919
- name: Set up Python
2020
uses: actions/setup-python@v2
2121
with:
22-
python-version: "3.11"
22+
python-version: "3.12"
2323

2424
- name: Generate projects from templates using cookiecutter
2525
# minimal_project folder

.github/workflows/manual_build_docker_image.yml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -17,7 +17,7 @@ jobs:
1717
- name: Set up Python
1818
uses: actions/setup-python@v2
1919
with:
20-
python-version: "3.11"
20+
python-version: "3.12"
2121

2222
- name: Generate projects from templates using cookiecutter
2323
# minimal_project folder

.github/workflows/tests.yml

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -24,7 +24,7 @@ jobs:
2424
- name: Set up Python
2525
uses: actions/setup-python@v2
2626
with:
27-
python-version: "3.11"
27+
python-version: "3.12"
2828

2929
# Below will create fresh template in path: minimal_project
3030
- name: Generate project from template using cookiecutter
@@ -61,5 +61,5 @@ jobs:
6161
TEST_DATABASE_DB: postgres
6262
run: |
6363
cd minimal_project
64-
poetry run flake8 app --count --exit-zero --statistics
64+
poetry run ruff app
6565
poetry run coverage run -m pytest

README.md

Lines changed: 12 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -1,18 +1,9 @@
1-
<a href="https://minimal-fastapi-postgres-template.rafsaf.pl/" target="_blank">
2-
<img src="https://img.shields.io/badge/live%20example-https%3A%2F%2Fminimal--fastapi--postgres--template.rafsaf.pl-blueviolet" alt="Live example">
3-
</a>
4-
<a href="https://github.com/rafsaf/minimal-fastapi-postgres-template/blob/main/LICENSE" target="_blank">
5-
<img src="https://img.shields.io/github/license/rafsaf/minimal-fastapi-postgres-template" alt="License">
6-
</a>
7-
<a href="https://docs.python.org/3/whatsnew/3.11.html" target="_blank">
8-
<img src="https://img.shields.io/badge/python-3.11-blue" alt="Python">
9-
</a>
10-
<a href="https://github.com/psf/black" target="_blank">
11-
<img src="https://img.shields.io/badge/code%20style-black-lightgrey" alt="Black">
12-
</a>
13-
<a href="https://github.com/rafsaf/minimal-fastapi-postgres-template/actions/workflows/tests.yml" target="_blank">
14-
<img src="https://github.com/rafsaf/minimal-fastapi-postgres-template/workflows/tests/badge.svg" alt="Tests">
15-
</a>
1+
[![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/)
2+
[![License](https://img.shields.io/github/license/rafsaf/minimal-fastapi-postgres-template)](https://github.com/rafsaf/minimal-fastapi-postgres-template/blob/main/LICENSE)
3+
[![Python 3.12](https://img.shields.io/badge/python-3.12-blue)](https://docs.python.org/3/whatsnew/3.12.html)
4+
[![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)
5+
[![Black](https://img.shields.io/badge/code%20style-black-lightgrey)](https://github.com/psf/black)
6+
[![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)
167

178
# Minimal async FastAPI + PostgreSQL template
189

@@ -42,9 +33,9 @@
4233
- [x] [Alembic](https://alembic.sqlalchemy.org/en/latest/) migrations
4334
- [x] Very minimal project structure yet ready for quick start building new apps
4435
- [x] Refresh token endpoint (not only access like in official template)
45-
- [x] Two databases in docker-compose.yml (second one for tests) and ready to go Dockerfile with [Uvicorn](https://www.uvicorn.org/) webserver
46-
- [x] [Poetry](https://python-poetry.org/docs/) and Python 3.11 based
47-
- [x] `pre-commit` with poetry export, autoflake, black, isort and flake8
36+
- [x] Two databases in docker-compose.yml (second one for tests) and ready to go Dockerfile with [uvicorn](https://www.uvicorn.org/) webserver
37+
- [x] [Poetry](https://python-poetry.org/docs/) and Python 3.12 based
38+
- [x] `pre-commit` with poetry export and [ruff](https://github.com/astral-sh/ruff)
4839
- [x] Rich setup for pytest async tests with few included and extensible `conftest.py`
4940

5041
<br>
@@ -69,16 +60,16 @@ cookiecutter https://github.com/rafsaf/minimal-fastapi-postgres-template
6960

7061
```bash
7162
cd project_name
72-
### Poetry install (python3.11)
63+
### Poetry install (python3.12)
7364
poetry install
7465

7566
### Optionally there is also `requirements-dev.txt` file
76-
python3.11 -m venv venv
67+
python3.12 -m venv venv
7768
source venv/bin/activate
7869
pip install -r requirements-dev.txt
7970
```
8071

81-
Note, be sure to use `python3.11` with this template with either poetry or standard venv & pip, if you need to stick to some earlier python version, you should adapt it yourself (remove new versions specific syntax for example `str | int` for python < 3.10 or `tomllib` for python < 3.11)
72+
Note, be sure to use `python3.12` with this template with either poetry or standard venv & pip, if you need to stick to some earlier python version, you should adapt it yourself (remove new versions specific syntax for example `str | int` for python < 3.10 or `tomllib` for python < 3.11)
8273

8374
### 3. Setup databases
8475

{{cookiecutter.project_name}}/.flake8

Lines changed: 0 additions & 11 deletions
This file was deleted.
Lines changed: 9 additions & 44 deletions
Original file line numberDiff line numberDiff line change
@@ -1,63 +1,28 @@
11
repos:
22
- repo: https://github.com/pre-commit/pre-commit-hooks
3-
rev: v4.4.0
3+
rev: v4.5.0
44
hooks:
55
- id: check-yaml
6-
- id: trailing-whitespace
7-
8-
- repo: https://github.com/myint/autoflake
9-
rev: "v2.0.1"
10-
hooks:
11-
- id: autoflake
12-
args:
13-
[
14-
"--recursive",
15-
"--in-place",
16-
"--remove-unused-variables",
17-
"--remove-all-unused-imports",
18-
"--ignore-init-module-imports",
19-
]
20-
21-
- repo: https://github.com/asottile/pyupgrade
22-
rev: v3.3.1
23-
hooks:
24-
- id: pyupgrade
25-
args:
26-
[
27-
"--py3-plus",
28-
"--py36-plus",
29-
"--py37-plus",
30-
"--py38-plus",
31-
"--py39-plus",
32-
"--py310-plus",
33-
"--py311-plus",
34-
]
35-
files: ".*"
366

377
- repo: https://github.com/psf/black
38-
rev: "23.1.0"
8+
rev: "23.10.1"
399
hooks:
4010
- id: black
4111

42-
- repo: https://github.com/pycqa/isort
43-
rev: "5.12.0"
44-
hooks:
45-
- id: isort
46-
47-
- repo: https://github.com/PyCQA/flake8
48-
rev: "6.0.0"
12+
- repo: https://github.com/astral-sh/ruff-pre-commit
13+
rev: v0.1.4
4914
hooks:
50-
- id: flake8
15+
- id: ruff
16+
args: [--fix]
5117

5218
- repo: https://github.com/python-poetry/poetry
53-
rev: "1.3.0"
19+
rev: "1.7.0"
5420
hooks:
5521
- id: poetry-export
5622
args: ["-o", "requirements.txt", "--without-hashes"]
5723

5824
- repo: https://github.com/python-poetry/poetry
59-
rev: "1.3.0"
25+
rev: "1.7.0"
6026
hooks:
6127
- id: poetry-export
62-
args:
63-
["-o", "requirements-dev.txt", "--without-hashes", "--with", "dev"]
28+
args: ["-o", "requirements-dev.txt", "--without-hashes", "--with=dev"]

{{cookiecutter.project_name}}/Dockerfile

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
FROM python:3.11.1-slim-bullseye
1+
FROM python:3.12.0-slim-bullseye
22

33
ENV PYTHONUNBUFFERED 1
44
WORKDIR /build

{{cookiecutter.project_name}}/app/core/config.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -21,11 +21,11 @@
2121
Note, complex types like lists are read as json-encoded strings.
2222
"""
2323

24-
import tomllib
2524
from functools import cached_property
2625
from pathlib import Path
2726
from typing import Literal
2827

28+
import tomllib
2929
from pydantic import AnyHttpUrl, EmailStr, PostgresDsn, computed_field
3030
from pydantic_settings import BaseSettings, SettingsConfigDict
3131

{{cookiecutter.project_name}}/app/tests/test_auth.py

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
from httpx import AsyncClient
1+
from httpx import AsyncClient, codes
22

33
from app.main import app
44
from app.models import User
@@ -14,7 +14,7 @@ async def test_auth_access_token(client: AsyncClient, default_user: User):
1414
},
1515
headers={"Content-Type": "application/x-www-form-urlencoded"},
1616
)
17-
assert response.status_code == 200
17+
assert response.status_code == codes.OK
1818
token = response.json()
1919
assert token["token_type"] == "Bearer"
2020
assert "access_token" in token
@@ -35,7 +35,7 @@ async def test_auth_access_token_fail_no_user(client: AsyncClient):
3535
headers={"Content-Type": "application/x-www-form-urlencoded"},
3636
)
3737

38-
assert response.status_code == 400
38+
assert response.status_code == codes.BAD_REQUEST
3939
assert response.json() == {"detail": "Incorrect email or password"}
4040

4141

@@ -53,7 +53,7 @@ async def test_auth_refresh_token(client: AsyncClient, default_user: User):
5353
new_token_response = await client.post(
5454
app.url_path_for("refresh_token"), json={"refresh_token": refresh_token}
5555
)
56-
assert new_token_response.status_code == 200
56+
assert new_token_response.status_code == codes.OK
5757
token = new_token_response.json()
5858
assert token["token_type"] == "Bearer"
5959
assert "access_token" in token

{{cookiecutter.project_name}}/app/tests/test_users.py

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
from httpx import AsyncClient
1+
from httpx import AsyncClient, codes
22
from sqlalchemy import select
33
from sqlalchemy.ext.asyncio import AsyncSession
44

@@ -15,7 +15,7 @@ async def test_read_current_user(client: AsyncClient, default_user_headers):
1515
response = await client.get(
1616
app.url_path_for("read_current_user"), headers=default_user_headers
1717
)
18-
assert response.status_code == 200
18+
assert response.status_code == codes.OK
1919
assert response.json() == {
2020
"id": default_user_id,
2121
"email": default_user_email,
@@ -28,7 +28,7 @@ async def test_delete_current_user(
2828
response = await client.delete(
2929
app.url_path_for("delete_current_user"), headers=default_user_headers
3030
)
31-
assert response.status_code == 204
31+
assert response.status_code == codes.NO_CONTENT
3232
result = await session.execute(select(User).where(User.id == default_user_id))
3333
user = result.scalars().first()
3434
assert user is None
@@ -42,7 +42,7 @@ async def test_reset_current_user_password(
4242
headers=default_user_headers,
4343
json={"password": "testxxxxxx"},
4444
)
45-
assert response.status_code == 200
45+
assert response.status_code == codes.OK
4646
result = await session.execute(select(User).where(User.id == default_user_id))
4747
user = result.scalars().first()
4848
assert user is not None
@@ -60,7 +60,7 @@ async def test_register_new_user(
6060
"password": "asdasdasd",
6161
},
6262
)
63-
assert response.status_code == 200
63+
assert response.status_code == codes.OK
6464
result = await session.execute(select(User).where(User.email == "qwe@example.com"))
6565
user = result.scalars().first()
6666
assert user is not None

{{cookiecutter.project_name}}/init.sh

100644100755
File mode changed.

0 commit comments

Comments
 (0)