home / skills / wdm0006 / python-skills / project-setup
This skill helps you set up professional Python library projects with modern tooling and automation for development, linting, testing, and CI.
npx playbooks add skill wdm0006/python-skills --skill project-setupReview the files below or copy the command above to add this skill to your agents.
---
name: setting-up-python-libraries
description: Sets up professional Python library projects with modern tooling (pyproject.toml, uv, ruff, pytest, pre-commit, GitHub Actions). Use when creating new Python libraries, modernizing existing projects to pyproject.toml, configuring linting/testing/CI, or setting up Makefiles and pre-commit hooks.
---
# Python Library Project Setup
## Quick Start
Create a new library with this structure:
```
my-library/
├── src/my_library/
│ ├── __init__.py
│ └── py.typed
├── tests/
├── pyproject.toml
├── Makefile
├── .pre-commit-config.yaml
└── .github/workflows/ci.yml
```
Use `src/` layout to prevent accidental imports of development code.
## Core Configuration
For complete templates, see:
- **[PYPROJECT.md](PYPROJECT.md)** - Full pyproject.toml with all tool configs
- **[CI.md](CI.md)** - GitHub Actions and pre-commit setup
- **[MAKEFILE.md](MAKEFILE.md)** - Makefile automation patterns
## Minimal pyproject.toml
```toml
[build-system]
requires = ["setuptools>=61.0", "wheel"]
build-backend = "setuptools.build_meta"
[project]
name = "my-library"
version = "0.1.0"
description = "What it does"
readme = "README.md"
requires-python = ">=3.10"
license = {text = "MIT"}
dependencies = []
[project.optional-dependencies]
dev = ["pytest>=7.0", "ruff>=0.1", "mypy>=1.0"]
[tool.setuptools.packages.find]
where = ["src"]
```
## Essential Commands
```bash
# Setup
pip install -e ".[dev]"
pre-commit install
# Daily workflow
ruff check src tests # Lint
ruff format src tests # Format
pytest # Test
mypy src # Type check
```
## Key Decisions
| Choice | Recommendation | Why |
|--------|---------------|-----|
| Layout | `src/` | Catches packaging bugs early |
| Build backend | setuptools | Mature, broad compatibility |
| Linter | ruff | Fast, replaces flake8+isort+black |
| Python range | `>=3.10` | Don't pin exact versions |
| Dependencies | Minimal | Move optional deps to extras |
## Checklist
```
Project Setup:
- [ ] src/ layout with py.typed marker
- [ ] pyproject.toml (not setup.py)
- [ ] Makefile with dev/test/lint/format
- [ ] .pre-commit-config.yaml
- [ ] .github/workflows/ci.yml
- [ ] README.md, LICENSE, CHANGELOG.md
- [ ] .gitignore
```
## Helper Script
Create a new project structure:
```bash
python scripts/create_project.py my-library --author "Name"
```
## Learn More
This skill is based on the [Guide to Developing High-Quality Python Libraries](https://mcginniscommawill.com/guides/python-library-development/) by [Will McGinnis](https://mcginniscommawill.com/). See the full guide for deeper coverage of project structure, tooling choices, and best practices.
This skill sets up professional Python library projects with modern tooling and sensible defaults. It scaffolds a src/ layout, generates pyproject.toml, configures ruff, pytest, mypy, pre-commit hooks, a Makefile, and a CI workflow. Use it to create new libraries or modernize existing projects to a pyproject-based workflow.
The skill generates a standardized project layout (src/, tests/, py.typed) and a minimal pyproject.toml that declares build-system, project metadata, and dev extras. It configures fast linting with ruff, testing with pytest, optional typing with mypy, pre-commit hooks for local safety, and a GitHub Actions CI workflow. It also provides Makefile targets and scripts to automate common developer tasks.
Do I have to use setuptools as the build backend?
Setuptools is the recommended default for broad compatibility, but you can replace the build-backend in pyproject.toml if you prefer alternatives like build or flit.
How do I run the dev workflow locally?
Install dev extras with pip install -e '.[dev]'; run pre-commit install once; then use Makefile targets or run ruff check/ruff format, pytest, and mypy as needed.