Skip to content

Commit c08ba26

Browse files
committed
merge from faastapi-minimum
2 parents de273ca + 61b67d0 commit c08ba26

17 files changed

Lines changed: 1386 additions & 2536 deletions

Makefile

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -20,8 +20,8 @@ test:
2020
--keep-project-on-failure -o /tmp .
2121

2222
cd /tmp/$(TARGET_NAME); \
23-
poetry run make lint && \
24-
poetry run make test && \
25-
poetry run make audit && \
26-
poetry run make smoke_test && \
23+
uv run make lint && \
24+
uv run make test && \
25+
uv run make audit && \
26+
uv run make smoke_test && \
2727
echo '\nSuccess!'

README.rst

Lines changed: 11 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -16,8 +16,8 @@ Features
1616

1717
* FastAPI_ web framework
1818
* Asynchronous database support based on `Encode Databases`_ and `SQLAlchemy Core`_
19-
* Python 3.12+ (configurable)
20-
* Poetry_ based dependency management
19+
* Python 3.14+ (configurable)
20+
* uv_ based dependency management
2121
* Development tasks registered in a ``Makefile`` for easy access and management
2222
* Custom Mercurial/Git hooks for ``pre-commit`` and ``pre-push`` events
2323
* Linting based on ruff_, mypy_ and others
@@ -36,17 +36,21 @@ Instructions
3636
============
3737

3838
To instantiate the template into a new project, you'll need cookiecutter_ (>=2.4.0).
39-
The best way to use it just once is through pipx_:
39+
The best way to use it just once is through uvx_:
4040

4141
.. code:: console
4242
43+
<<<<<<< working copy
4344
$ pipx run cookiecutter gh:andredias/perfect_python_project -c fastapi-complete
45+
=======
46+
$ uvx run cookiecutter gh:andredias/perfect_python_project -c fastapi-minimum
47+
>>>>>>> merge rev
4448

45-
If you prefer, use can install it throught `pip` instead:
49+
If you prefer, use can install it throught ``uv tool`` instead:
4650

4751
.. code:: console
4852
49-
$ pip install --user cookiecutter
53+
$ uv tool install cookiecutter
5054
5155
Next, run the following command:
5256

@@ -85,9 +89,9 @@ That's it!
8589
.. _HTTPX: https://www.python-httpx.org/
8690
.. _Loguru: https://github.com/Delgan/loguru
8791
.. _mypy: http://mypy-lang.org/
88-
.. _pipx: https://pypa.github.io/pipx/
89-
.. _Poetry: https://python-poetry.org/
9092
.. _pytest: https://pytest.org
9193
.. _python-dotenv: https://pypi.org/project/python-dotenv/
9294
.. _ruff: https://pypi.org/project/ruff/
9395
.. _SQLAlchemy Core: https://docs.sqlalchemy.org/en/latest/core/
96+
.. _uv: https://docs.astral.sh/uv/
97+
.. _uvx: https://docs.astral.sh/uv/guides/tools/

cookiecutter.json

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,9 @@
11
{
22
"author": "",
33
"email": "",
4-
"project_name": "Perfect Python Project",
4+
"project_name": "Perfect_FastAPI_Project",
55
"project_slug": "{{ cookiecutter.project_name.lower().replace(' ', '_').replace('-', '_') }}",
6-
"python_version": "3.12",
6+
"python_version": "3.14",
77
"line_length": 100,
88
"version_control": [
99
"hg",

hooks/post_gen_project.sh

Lines changed: 4 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -4,10 +4,8 @@ set -xuo pipefail
44

55
cp sample.env .env
66
rm alembic/versions/empty.txt # empty.txt was used to keep the alembic folder in version control
7-
poetry env use {{cookiecutter.python_version}}
8-
poetry lock --no-update
9-
poetry install
10-
poetry run make format
7+
uv sync --no-install-project
8+
uv run make format
119

1210
commit_message="Initial project structure based on https://github.com/andredias/perfect_python_project/tree/fastapi-complete"
1311

@@ -27,12 +25,12 @@ make install_hooks
2725
# initial migration for alembic
2826
docker compose up -d db
2927
sleep 5
30-
poetry run alembic revision --autogenerate -m "Initial migration"
28+
uv run alembic revision --autogenerate -m "Initial migration"
3129
docker compose down
3230

3331
# use a separated commit for the initial migration
3432
# so it can be easily reverted if needed
35-
poetry run make format
33+
uv run make format
3634
if [ "{{cookiecutter.version_control}}" == "hg" ]; then
3735
hg commit -Am 'Initial alembic migration'
3836
else

{{cookiecutter.project_slug}}/.dockerignore

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,9 @@
22
!alembic*
33
!entrypoint.sh
44
!migrate_database.py
5+
!entrypoint.sh
56
!pyproject.toml
6-
!poetry.lock
7+
!README.rst
8+
!uv.lock
79
!{{cookiecutter.project_slug}}/
810
**/__pycache__

{{cookiecutter.project_slug}}/.github/workflows/continuous_integration.yml

Lines changed: 20 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -8,38 +8,37 @@ jobs:
88
runs-on: ubuntu-latest
99
steps:
1010

11-
- name: Set up python
12-
uses: actions/setup-python@v4
13-
with:
14-
python-version: '{{cookiecutter.python_version}}'
15-
1611
- name: Check out repository
17-
uses: actions/checkout@v3
12+
uses: actions/checkout@v5
1813

19-
- name: Install Poetry
20-
uses: snok/install-poetry@v1
14+
- name: Set up python
15+
uses: actions/setup-python@v6
2116
with:
22-
virtualenvs-in-project: true
17+
python-version-file: "pyproject.toml"
2318

24-
- name: Load cached venv
25-
id: cached-poetry-dependencies
26-
uses: actions/cache@v3
19+
- name: Install uv
20+
uses: astral-sh/setup-uv@v6
2721
with:
28-
path: .venv
29-
key: venv-{{ "${{ hashFiles('**/poetry.lock') }}" }}
22+
version: "0.9.8"
23+
enable-cache: true
3024

3125
- name: Install dependencies
32-
if: steps.cached-poetry-dependencies.outputs.cache-hit != 'true'
33-
run: poetry install --no-interaction
26+
run: uv sync --locked --no-install-project
27+
28+
- name: Testing
29+
run: uv run --locked make test
3430

3531
- name: Linting
36-
run: poetry run make lint
32+
run: uv run --locked make lint
3733

3834
- name: Auditing
39-
run: poetry run make audit
35+
run: uv run make audit
4036

41-
- name: Test
42-
run: poetry run make test
37+
- name: Building
38+
run: docker compose build
4339

4440
- name: Smoke Test
45-
run: poetry run make smoke_test
41+
run: uv run make smoke_test
42+
43+
- name: Minimize uv cache
44+
run: uv cache prune --ci
Lines changed: 60 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -1,33 +1,77 @@
1-
FROM python:{{cookiecutter.python_version}}-slim as builder
1+
# syntax=docker/dockerfile:1
2+
3+
FROM python:3.14-slim AS builder
4+
LABEL maintainer="André Felipe Dias <andref.dias@gmail.com>"
5+
6+
RUN DEBIAN_FRONTEND=noninteractive apt-get update && \
7+
apt-get install -y --no-install-recommends build-essential libffi-dev libxml2-dev \
8+
libxslt-dev curl libpq-dev && \
9+
apt-get clean && \
10+
rm -rf /var/lib/apt/lists/*
11+
12+
# ref: https://github.com/astral-sh/uv-docker-example/blob/main/multistage.Dockerfile
13+
14+
COPY --from=ghcr.io/astral-sh/uv:0.9.8 /uv /uvx /bin/
15+
16+
ENV UV_COMPILE_BYTECODE=1 UV_LINK_MODE=copy UV_PYTHON_DOWNLOADS=0
17+
18+
WORKDIR /app
19+
20+
COPY pyproject.toml uv.lock ./
21+
RUN uv sync --locked --no-install-project --no-dev
22+
23+
# ---------------------------------------------------------
24+
25+
FROM python:3.14-slim AS final
26+
27+
RUN DEBIAN_FRONTEND=noninteractive apt-get update && \
28+
apt-get install -y --no-install-recommends libpq-dev && \
29+
apt-get clean && \
30+
rm -rf /var/lib/apt/lists/*
31+
32+
WORKDIR /app
33+
COPY --from=builder --chown=nobody:nogroup /app/.venv ./.venv
34+
ENV PATH=/app/.venv/bin:${PATH}
35+
36+
COPY --chown=nobody:nogroup --exclude=pyproject.toml --exclude=uv.lock . ./
37+
38+
USER nobody
39+
40+
EXPOSE 5000
41+
42+
CMD ["./entrypoint.sh"]
43+
44+
# ---------------------------------------------------------
45+
46+
FROM python:{{cookiecutter.python_version}}-slim AS builder
247
LABEL maintainer="{{cookiecutter.author}} <{{cookiecutter.email}}>"
348

449
RUN DEBIAN_FRONTEND=noninteractive apt-get update && \
5-
apt-get install -y --no-install-recommends build-essential libpq-dev curl && \
50+
apt-get install -y --no-install-recommends build-essential libffi-dev libxml2-dev \
51+
libxslt-dev curl libpq-dev && \
652
apt-get clean && \
753
rm -rf /var/lib/apt/lists/*
854

9-
ENV PYTHONDONTWRITEBYTECODE=1
10-
ENV PYTHONUNBUFFERED=1
11-
RUN python -m venv /venv
55+
COPY --from=ghcr.io/astral-sh/uv:0.9.8 /uv /uvx /bin/
1256

13-
ENV POETRY_VERSION=1.8.2
14-
ENV POETRY_HOME=/opt/poetry
15-
SHELL ["/bin/bash", "-o", "pipefail", "-c"]
16-
RUN curl -sSL https://install.python-poetry.org | python -
57+
ENV UV_COMPILE_BYTECODE=1 UV_LINK_MODE=copy UV_PYTHON_DOWNLOADS=0
1758

1859
WORKDIR /app
19-
COPY pyproject.toml poetry.lock ./
20-
RUN . /venv/bin/activate; \
21-
$POETRY_HOME/bin/poetry install --only main --no-interaction
2260

61+
COPY pyproject.toml uv.lock ./
62+
RUN uv sync --locked --no-install-project --no-dev
2363

24-
FROM python:{{cookiecutter.python_version}}-slim as final
64+
# ---------------------------------------------------------
2565

26-
COPY --from=builder /venv /venv
27-
ENV PATH=/venv/bin:${PATH}
66+
FROM python:{{cookiecutter.python_version}}-slim AS final
2867

2968
WORKDIR /app
69+
COPY --from=builder --chown=nobody:nogroup /app/.venv ./.venv
70+
ENV PATH=/app/.venv/bin:${PATH}
71+
72+
COPY --chown=nobody:nogroup --exclude=pyproject.toml --exclude=uv.lock . ./
73+
3074
USER nobody
31-
COPY --chown=nobody:nogroup {{cookiecutter.project_slug}}/ ./{{cookiecutter.project_slug}}
75+
EXPOSE 5000
3276

3377
CMD ["./entrypoint.sh"]

{{cookiecutter.project_slug}}/Makefile

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -44,4 +44,7 @@ install_hooks:
4444

4545

4646
check_env:
47-
@ if [ ! -f ".env" ]; then echo '.env not found'; exit 1; fi
47+
@ if [ ! -f ".env" ]; then \
48+
cp sample.env .env; \
49+
echo '.env created from sample.env'; \
50+
fi

{{cookiecutter.project_slug}}/docker-compose.dev.yml

Lines changed: 0 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -1,15 +1,5 @@
11
services:
22
app:
3-
command:
4-
[
5-
"hypercorn",
6-
"--worker-class={{ cookiecutter.worker_class }}",
7-
"--bind=0.0.0.0:5000",
8-
"--error-logfile=-",
9-
"--reload",
10-
"--root-path=/api",
11-
"{{cookiecutter.project_slug}}.main:app"
12-
]
133
volumes:
144
- ./{{cookiecutter.project_slug}}/:/app/{{cookiecutter.project_slug}}/
155
environment:

{{cookiecutter.project_slug}}/docker-compose.yml

Lines changed: 0 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -43,15 +43,6 @@ services:
4343
environment:
4444
DB_HOST: db
4545
ENV: ${ENV:-production}
46-
command:
47-
[
48-
"hypercorn",
49-
"--worker-class={{cookiecutter.worker_class}}",
50-
"--bind=0.0.0.0:5000",
51-
"--error-logfile=-",
52-
"--root-path=/api",
53-
"{{cookiecutter.project_slug}}.main:app"
54-
]
5546

5647
volumes:
5748
caddy_data:

0 commit comments

Comments
 (0)