| name | python-dev |
| description | Opinionated Python development setup with uv + ty + ruff + pytest + just. Use when creating new Python projects, setting up pyproject.toml, configuring linting, type checking, testing, or build tooling. Triggers on "python project", "uv init", "pyproject.toml", "ruff config", "ty check", "pytest setup", "justfile", "python linting", "python formatting", "type checking python". |
| metadata | {"version":"0.2.2","upstream":"uv@0.11.8, ty@0.0.33, ruff@0.15.12, ruff-pre-commit@0.15.12, pytest@9.0.3, pytest-asyncio@1.3.0, pre-commit@4.6.0, pre-commit-hooks@6.0.0"} |
Python Development Setup
Opinionated, production-ready Python development stack. No choices to make - just use this.
When to Use
- Starting a new Python project
- Modernizing an existing project (migrating from pip/poetry/mypy/black/flake8)
- Setting up linting, formatting, type checking, or testing
- Creating a Justfile for project commands
- Configuring pyproject.toml as the single source of truth
The Stack
| Tool | Role | Replaces |
|---|
| uv 0.11+ | Package manager, Python versions, runner | pip, poetry, pyenv, virtualenv |
| ty (beta) | Type checker (Astral, Rust) | mypy, pyright |
| ruff | Linter + formatter | flake8, black, isort, pyupgrade |
| pytest | Testing | unittest |
| just | Command runner | make |
Note on ty: ty is in beta (0.0.x). It's fast and improving rapidly, but still missing features and may produce false positives on heavy-typing libraries (Pydantic, Django, SQLAlchemy). For projects that need rock-solid type checking today, swap ty for pyright and keep the rest of the stack unchanged.
Quick Start: New Project
uv init --package my-project
cd my-project
uv python pin 3.13
uv add --dev ruff ty pytest pytest-asyncio pre-commit
just check
pyproject.toml Template
This is the single config file. Copy this and adjust [project] fields.
[project]
name = "my-project"
version = "0.1.0"
description = "Project description"
readme = "README.md"
requires-python = ">=3.13"
license = {text = "MIT"}
dependencies = []
[project.scripts]
my-project = "my_project:main"
[dependency-groups]
dev = [
"ruff>=0.15.0",
"ty>=0.0.30",
"pytest>=9.0.0",
"pytest-asyncio>=1.3.0",
"pre-commit>=4.0.0",
]
[build-system]
requires = ["hatchling"]
build-backend = "hatchling.build"
[tool.hatch.build.targets.wheel]
packages = ["src/my_project"]
[tool.ruff]
target-version = "py313"
line-length = 100
[tool.ruff.lint]
select = [
"E",
"F",
"I",
"UP",
]
ignore = [
"E501",
"E741",
"UP007",
]
exclude = [".git", ".venv", "__pycache__", "build", "dist"]
[tool.ruff.format]
quote-style = "double"
indent-style = "space"
line-ending = "lf"
[tool.ty.environment]
python-version = "3.13"
[tool.ty.src]
include = ["src"]
[tool.pytest.ini_options]
testpaths = ["tests"]
python_files = ["test_*.py"]
python_classes = ["Test*"]
python_functions = ["test_*"]
asyncio_mode = "auto"
addopts = [
"--strict-markers",
"--strict-config",
"-ra",
]
Justfile Template
# Check types and lint
check:
uv run ty check
uv run ruff check --fix && uv run ruff format
# Run tests
test *ARGS:
uv run pytest {{ARGS}}
# Run tests with coverage
test-cov:
uv run pytest --cov=src --cov-report=term-missing
# Auto-fix and format
fix:
uv run ruff check --fix
uv run ruff format
# Install/sync all dependencies
install:
uv sync --all-groups
# Update all dependencies
update:
uv lock --upgrade
uv sync --all-groups
# Clean build artifacts
clean:
rm -rf dist/ build/ .pytest_cache/ .ruff_cache/ htmlcov/
find . -type d -name __pycache__ -exec rm -rf {} + 2>/dev/null || true
Pre-commit Config
Create .pre-commit-config.yaml:
repos:
- repo: https://github.com/pre-commit/pre-commit-hooks
rev: v6.0.0
hooks:
- id: check-added-large-files
args: ['--maxkb=1000']
exclude: ^uv\.lock$
- id: detect-private-key
- id: check-merge-conflict
- id: check-yaml
- id: check-toml
- id: end-of-file-fixer
- id: trailing-whitespace
- id: mixed-line-ending
args: ['--fix=lf']
- repo: https://github.com/astral-sh/ruff-pre-commit
rev: v0.15.12
hooks:
- id: ruff
args: [--fix]
- id: ruff-format
exclude: |
(?x)^(
\.venv/.*|
\.git/.*|
__pycache__/.*|
build/.*|
dist/.*|
uv\.lock
)$
Then run: uv run pre-commit install
Project Structure
Always use src layout:
my-project/
src/
my_project/
__init__.py
cli.py
models.py
tests/
conftest.py
test_models.py
pyproject.toml
Justfile
uv.lock
.python-version
.pre-commit-config.yaml
.gitignore
Daily Workflow
just check
just test
just test -x
just fix
uv add httpx
uv add --dev hypothesis
uv sync
uv sync --all-groups
uv run python -m my_project
CI (GitHub Actions)
Mirror just check + just test in CI. Drop this in .github/workflows/ci.yml:
name: CI
on: [push, pull_request]
jobs:
check:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- uses: astral-sh/setup-uv@v6
with:
enable-cache: true
- run: uv sync --all-groups
- run: uv run ty check
- run: uv run ruff check --output-format github
- run: uv run ruff format --check
- run: uv run pytest
astral-sh/setup-uv installs uv, manages the Python install requested by .python-version, and caches the resolver. No separate setup-python step needed.
Existing Project Migration
brew install uv
uv add -r requirements.txt
uv remove --dev mypy
uv add --dev ty
uv remove --dev black flake8 isort
uv add --dev ruff
Reference Docs
Detailed guides for each tool in references/:
- uv-reference.md - Project init, dependencies, lock/sync, Python versions, build/publish
- ty-reference.md - Configuration, rules, CLI flags, known limitations
- ruff-reference.md - Rule sets, formatter options, per-file ignores, CI integration
- pytest-reference.md - Plugins, fixtures, async testing, conftest patterns
- justfile-reference.md - Syntax, variables, parameters, shebang recipes, settings
Resources