setup-to-pyproject

Migrate Python projects from setup.py/setup.cfg to pyproject.toml for use with uv. Use when upgrading legacy Python packaging, converting setup.py to modern pyproject.toml format, setting up dependency groups for development/testing, and ensuring `uv run pytest` works correctly.

$ Installieren

git clone https://github.com/simonw/skills /tmp/skills && cp -r /tmp/skills/setup-to-pyproject ~/.claude/skills/skills

// tip: Run this command in your terminal to install the skill


name: setup-to-pyproject description: Migrate Python projects from setup.py/setup.cfg to pyproject.toml for use with uv. Use when upgrading legacy Python packaging, converting setup.py to modern pyproject.toml format, setting up dependency groups for development/testing, and ensuring uv run pytest works correctly.

Setup.py to pyproject.toml Migration for uv

Migrate legacy Python packaging to modern pyproject.toml with uv compatibility.

Core Structure

[project]
name = "package-name"
version = "0.1.0"
description = "Package description"
readme = "README.md"
requires-python = ">=3.10"
dependencies = [
    "requests>=2.28",
]
license = "Apache-2.0"

[project.urls]
Homepage = "https://github.com/user/repo"
Changelog = "https://github.com/user/repo/releases"
Issues = "https://github.com/user/repo/issues"
CI = "https://github.com/user/repo/actions"

[dependency-groups]
dev = [
    "pytest>=9.0",
    "black>=25.12.0",
]

[build-system]
requires = ["uv_build>=0.9.18,<0.10.0"]
build-backend = "uv_build"

Key Migration Steps

1. Extract metadata from setup.py

Map setup() arguments to [project] table:

  • namename
  • versionversion
  • descriptiondescription
  • long_descriptionreadme (use filename)
  • author + author_emailauthors = [{name = "...", email = "..."}]
  • urlproject.urls.Homepage
  • python_requiresrequires-python
  • install_requiresdependencies
  • entry_points.console_scripts[project.scripts]

2. Set up dependency-groups for dev dependencies

Critical for uv run pytest to work:

[dependency-groups]
dev = [
    "pytest>=9.0",
    "black>=25.12.0",
]

3. Confirm it works with uv run

Then run tests with:

uv run pytest

The dev group will be picked up automatically by uv run.

4. Confirm it works with uv build

Test that building the package works correctly:

uv build

uv_build defaults to src/ layout. For flat layout (package directory at project root), add:

[tool.uv.build-backend]
module-root = ""

Files to Delete After Migration

  • setup.py
  • setup.cfg
  • MANIFEST.in (usually, unless complex includes)
  • requirements.txt / requirements-dev.txt (optional, uv manages these)