From 587f53627768ffd2caad5b3265368bf6954fa428 Mon Sep 17 00:00:00 2001 From: Laurent Sorber Date: Thu, 16 Jan 2025 13:28:42 +0000 Subject: [PATCH 1/7] feat: upgrade to Poetry v2.0 --- .../.github/workflows/test.yml | 5 -- .../Dockerfile | 4 +- .../pyproject.toml | 71 +++++++++++-------- 3 files changed, 43 insertions(+), 37 deletions(-) diff --git a/{{ cookiecutter.__project_name_kebab_case }}/.github/workflows/test.yml b/{{ cookiecutter.__project_name_kebab_case }}/.github/workflows/test.yml index b436a01..a67e33a 100644 --- a/{{ cookiecutter.__project_name_kebab_case }}/.github/workflows/test.yml +++ b/{{ cookiecutter.__project_name_kebab_case }}/.github/workflows/test.yml @@ -40,8 +40,3 @@ jobs: - name: Test {{ cookiecutter.project_type }} run: devcontainer exec --workspace-folder . poe test - - - name: Upload coverage - uses: codecov/codecov-action@v5 - with: - files: reports/coverage.xml diff --git a/{{ cookiecutter.__project_name_kebab_case }}/Dockerfile b/{{ cookiecutter.__project_name_kebab_case }}/Dockerfile index 88aa063..2b9b181 100644 --- a/{{ cookiecutter.__project_name_kebab_case }}/Dockerfile +++ b/{{ cookiecutter.__project_name_kebab_case }}/Dockerfile @@ -37,7 +37,7 @@ FROM base AS poetry USER root # Install Poetry in separate venv so it doesn't pollute the main venv. -ENV POETRY_VERSION 1.8.0 +ENV POETRY_VERSION 2.0.1 ENV POETRY_VIRTUAL_ENV /opt/poetry-env RUN --mount=type=cache,target=/root/.cache/pip/ \ python -m venv $POETRY_VIRTUAL_ENV && \ @@ -92,7 +92,7 @@ RUN mkdir -p /opt/build/poetry/ && cp poetry.lock /opt/build/poetry/ && \ mkdir -p /opt/build/git/ && cp .git/hooks/commit-msg .git/hooks/pre-commit /opt/build/git/ # Configure the non-root user's shell. -ENV ANTIDOTE_VERSION 1.8.6 +ENV ANTIDOTE_VERSION 1.9.7 RUN git clone --branch v$ANTIDOTE_VERSION --depth=1 https://github.com/mattmc3/antidote.git ~/.antidote/ && \ echo 'zsh-users/zsh-syntax-highlighting' >> ~/.zsh_plugins.txt && \ echo 'zsh-users/zsh-autosuggestions' >> ~/.zsh_plugins.txt && \ diff --git a/{{ cookiecutter.__project_name_kebab_case }}/pyproject.toml b/{{ cookiecutter.__project_name_kebab_case }}/pyproject.toml index 372a2e2..eeb9adf 100644 --- a/{{ cookiecutter.__project_name_kebab_case }}/pyproject.toml +++ b/{{ cookiecutter.__project_name_kebab_case }}/pyproject.toml @@ -2,45 +2,47 @@ requires = ["poetry-core>=1.0.0"] build-backend = "poetry.core.masonry.api" -[tool.poetry] # https://python-poetry.org/docs/pyproject/ +[project] # https://packaging.python.org/en/latest/specifications/pyproject-toml/ name = "{{ cookiecutter.__project_name_kebab_case }}" version = "0.0.0" description = "{{ cookiecutter.project_description }}" -authors = ["{{ cookiecutter.author_name }} <{{ cookiecutter.author_email }}>"] readme = "README.md" -repository = "{{ cookiecutter.project_url }}" -{%- if cookiecutter.with_conventional_commits|int %} +license-files = ["LICENSE*"] +authors = ["{{ cookiecutter.author_name }} <{{ cookiecutter.author_email }}>"] +requires-python = ">={{ cookiecutter.python_version }},<4.0" -[tool.commitizen] # https://commitizen-tools.github.io/commitizen/config/ -bump_message = "bump(release): v$current_version → v$new_version" -tag_format = "v$version" -update_changelog_on_bump = true -version_provider = "poetry" +[project.urls] # https://packaging.python.org/en/latest/specifications/well-known-project-urls/#well-known-labels +homepage = "{{ cookiecutter.project_url }}" +source = "{{ cookiecutter.project_url }}" +{%- if cookiecutter.with_conventional_commits|int %} +changelog = "{{ cookiecutter.project_url }}/{% if cookiecutter.continuous_integration == "GitLab" %}-/{% endif %}blob/main/CHANGELOG.md" {%- endif %} +releasenotes = "{{ cookiecutter.project_url }}/{% if cookiecutter.continuous_integration == "GitLab" %}-/{% endif %}releases" +documentation = "{{ cookiecutter.project_url }}" +issues = "{{ cookiecutter.project_url }}/{% if cookiecutter.continuous_integration == "GitLab" %}-/{% endif %}issues" +dependencies = [ + {%- if cookiecutter.with_fastapi_api|int %} + "coloredlogs (>=15.0.1)", + "fastapi[all] (>=0.110.1)", + "gunicorn (>=21.2.0)", + {%- endif %} + {%- if cookiecutter.project_type == "app" %} + "poethepoet (>=0.25.0)", + {%- endif %} + {%- if cookiecutter.with_typer_cli|int %} + "typer[all] (>=0.12.0)", + {%- endif %} + {%- if cookiecutter.with_fastapi_api|int %} + "uvicorn[standard] (>=0.29.0)", + {%- endif %} +] {%- if cookiecutter.with_typer_cli|int %} -[tool.poetry.scripts] # https://python-poetry.org/docs/pyproject/#scripts +[project.scripts] # https://python-poetry.org/docs/pyproject/#scripts {{ cookiecutter.__project_name_kebab_case }} = "{{ cookiecutter.__project_name_snake_case }}.cli:app" {%- endif %} -[tool.poetry.dependencies] # https://python-poetry.org/docs/dependency-specification/ -{%- if cookiecutter.with_fastapi_api|int %} -coloredlogs = ">=15.0.1" -fastapi = { extras = ["all"], version = ">=0.110.1" } -gunicorn = ">=21.2.0" -{%- endif %} -{%- if cookiecutter.project_type == "app" %} -poethepoet = ">=0.25.0" -{%- endif %} -python = ">={{ cookiecutter.python_version }},<4.0" -{%- if cookiecutter.with_typer_cli|int %} -typer = { extras = ["all"], version = ">=0.12.0" } -{%- endif %} -{%- if cookiecutter.with_fastapi_api|int %} -uvicorn = { extras = ["standard"], version = ">=0.29.0" } -{%- endif %} - -[tool.poetry.group.test.dependencies] # https://python-poetry.org/docs/master/managing-dependencies/ +[tool.poetry.group.test.dependencies] # https://python-poetry.org/docs/managing-dependencies#dependency-groups {%- if cookiecutter.with_conventional_commits|int %} commitizen = ">=3.21.3" {%- endif %} @@ -60,7 +62,7 @@ shellcheck-py = ">=0.10.0.1" typeguard = ">=4.2.1" {%- endif %} -[tool.poetry.group.dev.dependencies] # https://python-poetry.org/docs/master/managing-dependencies/ +[tool.poetry.group.dev.dependencies] # https://python-poetry.org/docs/managing-dependencies#dependency-groups cruft = ">=2.15.0" ipykernel = ">=6.29.4" ipython = ">=8.18.0" @@ -77,6 +79,14 @@ name = "{{ cookiecutter.private_package_repository_name|slugify }}" url = "{{ cookiecutter.private_package_repository_url }}" priority = "explicit" {%- endif %} +{%- if cookiecutter.with_conventional_commits|int %} + +[tool.commitizen] # https://commitizen-tools.github.io/commitizen/config/ +bump_message = "bump(release): v$current_version → v$new_version" +tag_format = "v$version" +update_changelog_on_bump = true +version_provider = "poetry" +{%- endif %} [tool.coverage.report] # https://coverage.readthedocs.io/en/latest/config.html#report {%- if cookiecutter.development_environment == "strict" %} @@ -128,7 +138,8 @@ filterwarnings = ["error", "ignore::DeprecationWarning"] testpaths = ["src", "tests"] xfail_strict = true -[tool.ruff] # https://github.com/charliermarsh/ruff +[tool.ruff] # https://docs.astral.sh/ruff/settings/ +docstring-code-format = true fix = true line-length = 100 src = ["src", "tests"] From b9081871ae3fe800baf8436f9fd458113e45ca8c Mon Sep 17 00:00:00 2001 From: Laurent Sorber Date: Thu, 16 Jan 2025 13:34:52 +0000 Subject: [PATCH 2/7] fix: fix project.authors formatting --- {{ cookiecutter.__project_name_kebab_case }}/pyproject.toml | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/{{ cookiecutter.__project_name_kebab_case }}/pyproject.toml b/{{ cookiecutter.__project_name_kebab_case }}/pyproject.toml index eeb9adf..2703012 100644 --- a/{{ cookiecutter.__project_name_kebab_case }}/pyproject.toml +++ b/{{ cookiecutter.__project_name_kebab_case }}/pyproject.toml @@ -8,7 +8,9 @@ version = "0.0.0" description = "{{ cookiecutter.project_description }}" readme = "README.md" license-files = ["LICENSE*"] -authors = ["{{ cookiecutter.author_name }} <{{ cookiecutter.author_email }}>"] +authors = [ + { name = "{{ cookiecutter.author_name }}", email = "{{ cookiecutter.author_email }}" }, +] requires-python = ">={{ cookiecutter.python_version }},<4.0" [project.urls] # https://packaging.python.org/en/latest/specifications/well-known-project-urls/#well-known-labels From e0a36b85265019529b0b777575db491c56a9667f Mon Sep 17 00:00:00 2001 From: Laurent Sorber Date: Thu, 16 Jan 2025 13:38:37 +0000 Subject: [PATCH 3/7] fix: move project.dependencies --- .../pyproject.toml | 20 +++++++++---------- 1 file changed, 10 insertions(+), 10 deletions(-) diff --git a/{{ cookiecutter.__project_name_kebab_case }}/pyproject.toml b/{{ cookiecutter.__project_name_kebab_case }}/pyproject.toml index 2703012..edd5ebc 100644 --- a/{{ cookiecutter.__project_name_kebab_case }}/pyproject.toml +++ b/{{ cookiecutter.__project_name_kebab_case }}/pyproject.toml @@ -12,16 +12,6 @@ authors = [ { name = "{{ cookiecutter.author_name }}", email = "{{ cookiecutter.author_email }}" }, ] requires-python = ">={{ cookiecutter.python_version }},<4.0" - -[project.urls] # https://packaging.python.org/en/latest/specifications/well-known-project-urls/#well-known-labels -homepage = "{{ cookiecutter.project_url }}" -source = "{{ cookiecutter.project_url }}" -{%- if cookiecutter.with_conventional_commits|int %} -changelog = "{{ cookiecutter.project_url }}/{% if cookiecutter.continuous_integration == "GitLab" %}-/{% endif %}blob/main/CHANGELOG.md" -{%- endif %} -releasenotes = "{{ cookiecutter.project_url }}/{% if cookiecutter.continuous_integration == "GitLab" %}-/{% endif %}releases" -documentation = "{{ cookiecutter.project_url }}" -issues = "{{ cookiecutter.project_url }}/{% if cookiecutter.continuous_integration == "GitLab" %}-/{% endif %}issues" dependencies = [ {%- if cookiecutter.with_fastapi_api|int %} "coloredlogs (>=15.0.1)", @@ -44,6 +34,16 @@ dependencies = [ {{ cookiecutter.__project_name_kebab_case }} = "{{ cookiecutter.__project_name_snake_case }}.cli:app" {%- endif %} +[project.urls] # https://packaging.python.org/en/latest/specifications/well-known-project-urls/#well-known-labels +homepage = "{{ cookiecutter.project_url }}" +source = "{{ cookiecutter.project_url }}" +{%- if cookiecutter.with_conventional_commits|int %} +changelog = "{{ cookiecutter.project_url }}/{% if cookiecutter.continuous_integration == "GitLab" %}-/{% endif %}blob/main/CHANGELOG.md" +{%- endif %} +releasenotes = "{{ cookiecutter.project_url }}/{% if cookiecutter.continuous_integration == "GitLab" %}-/{% endif %}releases" +documentation = "{{ cookiecutter.project_url }}" +issues = "{{ cookiecutter.project_url }}/{% if cookiecutter.continuous_integration == "GitLab" %}-/{% endif %}issues" + [tool.poetry.group.test.dependencies] # https://python-poetry.org/docs/managing-dependencies#dependency-groups {%- if cookiecutter.with_conventional_commits|int %} commitizen = ">=3.21.3" From ec2718511f4770bc37bc10f983ce673ff01dad41 Mon Sep 17 00:00:00 2001 From: Laurent Sorber Date: Thu, 16 Jan 2025 16:40:36 +0000 Subject: [PATCH 4/7] feat: upgrade dependencies --- .../.pre-commit-config.yaml | 3 +- .../pyproject.toml | 34 +++++++++---------- 2 files changed, 18 insertions(+), 19 deletions(-) diff --git a/{{ cookiecutter.__project_name_kebab_case }}/.pre-commit-config.yaml b/{{ cookiecutter.__project_name_kebab_case }}/.pre-commit-config.yaml index c665b51..6101881 100644 --- a/{{ cookiecutter.__project_name_kebab_case }}/.pre-commit-config.yaml +++ b/{{ cookiecutter.__project_name_kebab_case }}/.pre-commit-config.yaml @@ -16,13 +16,14 @@ repos: - id: rst-inline-touching-normal - id: text-unicode-replacement-char - repo: https://github.com/pre-commit/pre-commit-hooks - rev: v4.5.0 + rev: v5.0.0 hooks: - id: check-added-large-files - id: check-ast - id: check-builtin-literals - id: check-case-conflict - id: check-docstring-first + - id: check-illegal-windows-names - id: check-json - id: check-merge-conflict - id: check-shebang-scripts-are-executable diff --git a/{{ cookiecutter.__project_name_kebab_case }}/pyproject.toml b/{{ cookiecutter.__project_name_kebab_case }}/pyproject.toml index edd5ebc..b8f9327 100644 --- a/{{ cookiecutter.__project_name_kebab_case }}/pyproject.toml +++ b/{{ cookiecutter.__project_name_kebab_case }}/pyproject.toml @@ -14,18 +14,17 @@ authors = [ requires-python = ">={{ cookiecutter.python_version }},<4.0" dependencies = [ {%- if cookiecutter.with_fastapi_api|int %} - "coloredlogs (>=15.0.1)", - "fastapi[all] (>=0.110.1)", - "gunicorn (>=21.2.0)", + "fastapi[all] (>=0.115.6)", + "gunicorn (>=23.0.0)", {%- endif %} {%- if cookiecutter.project_type == "app" %} - "poethepoet (>=0.25.0)", + "poethepoet (>=0.32.1)", {%- endif %} {%- if cookiecutter.with_typer_cli|int %} - "typer[all] (>=0.12.0)", + "typer[all] (>=0.15.1)", {%- endif %} {%- if cookiecutter.with_fastapi_api|int %} - "uvicorn[standard] (>=0.29.0)", + "uvicorn[standard] (>=0.34.0)", {%- endif %} ] {%- if cookiecutter.with_typer_cli|int %} @@ -46,30 +45,29 @@ issues = "{{ cookiecutter.project_url }}/{% if cookiecutter.continuous_integrati [tool.poetry.group.test.dependencies] # https://python-poetry.org/docs/managing-dependencies#dependency-groups {%- if cookiecutter.with_conventional_commits|int %} -commitizen = ">=3.21.3" +commitizen = ">=4.1.0" {%- endif %} -coverage = { extras = ["toml"], version = ">=7.4.4" } -mypy = ">=1.9.0" +coverage = { extras = ["toml"], version = ">=7.6.10" } +mypy = ">=1.14.1" {%- if cookiecutter.project_type == "package" %} -poethepoet = ">=0.25.0" +poethepoet = ">=0.32.1" {%- endif %} -pre-commit = ">=3.7.0" -pytest = ">=8.1.1" +pre-commit = ">=4.0.1" +pytest = ">=8.3.4" pytest-mock = ">=3.14.0" -pytest-xdist = ">=3.5.0" -ruff = ">=0.5.7" +pytest-xdist = ">=3.6.1" +ruff = ">=0.9.2" {%- if cookiecutter.development_environment == "strict" %} -safety = ">=3.1.0" shellcheck-py = ">=0.10.0.1" -typeguard = ">=4.2.1" +typeguard = ">=4.4.1" {%- endif %} [tool.poetry.group.dev.dependencies] # https://python-poetry.org/docs/managing-dependencies#dependency-groups -cruft = ">=2.15.0" +cruft = ">=2.16.0" ipykernel = ">=6.29.4" ipython = ">=8.18.0" ipywidgets = ">=8.1.2" -pdoc = ">=14.4.0" +pdoc = ">=15.0.1" {%- if cookiecutter.private_package_repository_name %} [[tool.poetry.source]] From d06a62202ac58f56e3a139a75dc48e3b1c319389 Mon Sep 17 00:00:00 2001 From: Laurent Sorber Date: Thu, 16 Jan 2025 16:49:56 +0000 Subject: [PATCH 5/7] fix: move ruff formatting setting and update rule code --- {{ cookiecutter.__project_name_kebab_case }}/pyproject.toml | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/{{ cookiecutter.__project_name_kebab_case }}/pyproject.toml b/{{ cookiecutter.__project_name_kebab_case }}/pyproject.toml index b8f9327..f547bb4 100644 --- a/{{ cookiecutter.__project_name_kebab_case }}/pyproject.toml +++ b/{{ cookiecutter.__project_name_kebab_case }}/pyproject.toml @@ -139,15 +139,17 @@ testpaths = ["src", "tests"] xfail_strict = true [tool.ruff] # https://docs.astral.sh/ruff/settings/ -docstring-code-format = true fix = true line-length = 100 src = ["src", "tests"] target-version = "py{{ cookiecutter.python_version.split('.')[:2]|join }}" +[tool.ruff.format] +docstring-code-format = true + [tool.ruff.lint] {%- if cookiecutter.development_environment == "strict" %} -select = ["A", "ASYNC", "B", "BLE", "C4", "C90", "D", "DTZ", "E", "EM", "ERA", "F", "FBT", "FLY", "FURB", "G", "I", "ICN", "INP", "INT", "ISC", "LOG", "N", "NPY", "PERF", "PGH", "PIE", "PL", "PT", "PTH", "PYI", "Q", "RET", "RSE", "RUF", "S", "SIM", "SLF", "SLOT", "T10", "T20", "TCH", "TID", "TRY", "UP", "W", "YTT"] +select = ["A", "ASYNC", "B", "BLE", "C4", "C90", "D", "DTZ", "E", "EM", "ERA", "F", "FBT", "FLY", "FURB", "G", "I", "ICN", "INP", "INT", "ISC", "LOG", "N", "NPY", "PERF", "PGH", "PIE", "PL", "PT", "PTH", "PYI", "Q", "RET", "RSE", "RUF", "S", "SIM", "SLF", "SLOT", "T10", "T20", "TC", "TID", "TRY", "UP", "W", "YTT"] ignore = ["D203", "D213", "E501", "RET504", "S101", "S307"] unfixable = ["ERA001", "F401", "F841", "T201", "T203"] {%- else %} From 08cc14de9dc5f2ba67b629f22ad87a3fa04e2f60 Mon Sep 17 00:00:00 2001 From: Laurent Sorber Date: Thu, 16 Jan 2025 17:09:44 +0000 Subject: [PATCH 6/7] fix: remove coloredlogs --- .../src/{{ cookiecutter.__project_name_snake_case }}/api.py | 6 +----- 1 file changed, 1 insertion(+), 5 deletions(-) diff --git a/{{ cookiecutter.__project_name_kebab_case }}/src/{{ cookiecutter.__project_name_snake_case }}/api.py b/{{ cookiecutter.__project_name_kebab_case }}/src/{{ cookiecutter.__project_name_snake_case }}/api.py index 02bd6a9..32bf803 100644 --- a/{{ cookiecutter.__project_name_kebab_case }}/src/{{ cookiecutter.__project_name_snake_case }}/api.py +++ b/{{ cookiecutter.__project_name_kebab_case }}/src/{{ cookiecutter.__project_name_snake_case }}/api.py @@ -5,19 +5,15 @@ from collections.abc import AsyncGenerator from contextlib import asynccontextmanager -import coloredlogs from fastapi import FastAPI @asynccontextmanager async def lifespan(app: FastAPI) -> AsyncGenerator[None, None]: """Handle FastAPI startup and shutdown events.""" - # Startup events: - # - Remove all handlers associated with the root logger object. + # Startup events. for handler in logging.root.handlers: logging.root.removeHandler(handler) - # - Add coloredlogs' colored StreamHandler to the root logger. - coloredlogs.install() yield # Shutdown events. From 192d60b57c8ed658fefca6a5f2b0194e99caba6b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Xavier=20Go=C3=A1s=20Aguililla?= Date: Mon, 20 Jan 2025 10:47:20 +0100 Subject: [PATCH 7/7] fix: Use --without instead of --only If you use PEP621, there is no longer a `main` dependency group with that name, which breaks `poetry install --only main`. The alternative is to actively exclude the test and dev dependency groups, which is not optimal but fixes things. This flow broke on my machine but not in CI. It's worth investigating why that is the case. --- {{ cookiecutter.__project_name_kebab_case }}/Dockerfile | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/{{ cookiecutter.__project_name_kebab_case }}/Dockerfile b/{{ cookiecutter.__project_name_kebab_case }}/Dockerfile index 2b9b181..1d2e38e 100644 --- a/{{ cookiecutter.__project_name_kebab_case }}/Dockerfile +++ b/{{ cookiecutter.__project_name_kebab_case }}/Dockerfile @@ -60,7 +60,7 @@ RUN --mount=type=cache,uid=$UID,gid=$GID,target=/home/user/.cache/pypoetry/ \ {%- if cookiecutter.private_package_repository_name %} --mount=type=secret,id=poetry-auth,uid=$UID,gid=$GID,target=/home/user/.config/pypoetry/auth.toml \ {%- endif %} - poetry install --only main --all-extras --no-interaction + poetry install --without test,dev --all-extras --no-interaction