Skip to content

Enhancement: Migrate project tooling from PDM to uv #17

Description

@hasansezertasan

Summary

Migrate the template's package and environment management from PDM to uv (Astral), aligning this template with the rest of the Litestar org (e.g. litestar-org/litestar, litestar-org/advanced-alchemy, litestar-org/litestar-saq) which now use uv + PEP 735 [dependency-groups].

Scope of the migration:

  • Replace [tool.pdm.dev-dependencies] with PEP 735 [dependency-groups] (docs, lint, test) so the manifest is tool-agnostic.
  • Drop [tool.pdm.scripts]; task shortcuts (lint, test, docs-serve, ci) move to the Makefile and are also documented as raw uv run ... calls in the README.
  • Rewrite the Makefile targets (install, upgrade, lint, test, coverage, docs, docs-serve) to call uv sync / uv run / uv lock --upgrade; remove install-pdm.
  • Update all four GitHub Actions workflows (ci.yaml, test.yaml, publish.yaml, docs.yaml) to use astral-sh/setup-uv@v8 (latest: 8.2.0) instead of pdm-project/setup-pdm, and uv build for publish.
  • Delete pdm.lock, generate uv.lock, and update .gitignore / .pre-commit-config.yaml (pdm-lock-check hook) / [tool.codespell] skip accordingly.
  • Keep the build backend (hatchling) and requires-python = ">=3.8,<4.0" unchanged in this PR.

Out of scope (deliberately): bumping the minimum Python version, switching the build backend, and any dependency upgrades unrelated to the tooling swap.

Basic Example

pyproject.toml shape after the migration:

[project]
name = "project-template"
requires-python = ">=3.8,<4.0"
dependencies = ["litestar[standard]"]

[build-system]
requires = ["hatchling"]
build-backend = "hatchling.build"

[dependency-groups]
docs   = ["sphinx>=7.1.2", "sphinx-autobuild>=2021.3.14", ...]
lint   = ["ruff>=0.0.289", "mypy>=1.5.1", "pre-commit>=3.4.0", ...]
test   = ["pytest>=7.4.2", "pytest-asyncio>=0.21.1", "pytest-cov>=4.1.0"]

Local workflows:

uv sync --all-groups          # install everything
uv run pytest                 # run tests
uv run pre-commit run -a      # lint
make test                     # same, via Makefile

CI (test.yaml) snippet:

- uses: astral-sh/setup-uv@v8
  with:
    python-version: \${{ inputs.python-version }}
    enable-cache: true
- run: uv sync --all-groups
- run: uv run pytest

Drawbacks and Impact

  • Contributor onboarding churn — anyone with a local .venv from PDM will need to re-run make install. The README will call this out.
  • No native script runner — uv intentionally has none, so the [tool.pdm.scripts] map disappears. Mitigation: keep parity in Makefile and document raw uv run invocations.
  • Lock format changepdm.lock is removed and uv.lock is committed. One-time noise in the diff; from then on lockfile diffs become smaller and faster.
  • Marginal CI impactastral-sh/setup-uv is meaningfully faster than setup-pdm, so CI wall time should drop slightly.
  • Downstream template users — anyone who already forked this template will need to do the same migration in their fork; the README will link to this issue/PR as a reference.

Unresolved questions

  • Should this PR also bump requires-python to >=3.9 to match current litestar core, or keep >=3.8,<4.0 and handle that in a follow-up? (Currently planning to keep >=3.8.)
  • Pin astral-sh/setup-uv to the floating @v8 major (currently 8.2.0), or pin exactly to @v8.2.0 for reproducibility? (Planning floating @v8.)
  • Keep the sonar and codeql jobs untouched (they don't touch PDM today), or harmonize them onto uv too for consistency? (Planning: leave untouched.)

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Fields

    No fields configured for issues without a type.

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions