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 change —
pdm.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 impact —
astral-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.)
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:
[tool.pdm.dev-dependencies]with PEP 735[dependency-groups](docs,lint,test) so the manifest is tool-agnostic.[tool.pdm.scripts]; task shortcuts (lint,test,docs-serve,ci) move to theMakefileand are also documented as rawuv run ...calls in the README.Makefiletargets (install,upgrade,lint,test,coverage,docs,docs-serve) to calluv sync/uv run/uv lock --upgrade; removeinstall-pdm.ci.yaml,test.yaml,publish.yaml,docs.yaml) to useastral-sh/setup-uv@v8(latest: 8.2.0) instead ofpdm-project/setup-pdm, anduv buildfor publish.pdm.lock, generateuv.lock, and update.gitignore/.pre-commit-config.yaml(pdm-lock-checkhook) /[tool.codespell] skipaccordingly.hatchling) andrequires-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.tomlshape after the migration:Local workflows:
CI (
test.yaml) snippet:Drawbacks and Impact
.venvfrom PDM will need to re-runmake install. The README will call this out.[tool.pdm.scripts]map disappears. Mitigation: keep parity inMakefileand document rawuv runinvocations.pdm.lockis removed anduv.lockis committed. One-time noise in the diff; from then on lockfile diffs become smaller and faster.astral-sh/setup-uvis meaningfully faster thansetup-pdm, so CI wall time should drop slightly.Unresolved questions
requires-pythonto>=3.9to match currentlitestarcore, or keep>=3.8,<4.0and handle that in a follow-up? (Currently planning to keep>=3.8.)astral-sh/setup-uvto the floating@v8major (currently 8.2.0), or pin exactly to@v8.2.0for reproducibility? (Planning floating@v8.)sonarandcodeqljobs untouched (they don't touch PDM today), or harmonize them onto uv too for consistency? (Planning: leave untouched.)