ss-modern-python

Configure Python projects with modern tooling: uv, ruff, ty. Use when creating new Python projects, setting up pyproject.toml, migrating from pip/Poetry/mypy/black, or writing standalone scripts. Triggers on new Python project, setup Python, pyproject.toml, migrate from pip, migrate from Poetry, replace mypy, replace black, uv init, ruff config.

Modern Python

Reference for modern Python tooling and project setup. Adapted from trailofbits/modern-python.

When to Use

  • Creating a new Python project or package
  • Setting up or configuring pyproject.toml
  • Migrating from legacy tools (pip, Poetry, mypy, black, isort)
  • Writing standalone scripts with dependencies

When NOT to Use

  • User explicitly wants to keep legacy tooling
  • Non-Python projects
  • Python < 3.11 required

Tool Stack

ToolPurposeReplaces
uvPackage/dependency managementpip, virtualenv, pip-tools, pipx, pyenv, Poetry
ruffLinting AND formattingflake8, black, isort, pyupgrade
tyType checkingmypy, pyright
pytestTestingunittest

Anti-Patterns

AvoidUse Instead
uv pip installuv add and uv sync
Editing pyproject.toml to add depsuv add <pkg> / uv remove <pkg>
Poetryuv
requirements.txt for projectspyproject.toml + uv.lock
requirements.txt for scriptsPEP 723 inline metadata
mypy / pyrightty
[project.optional-dependencies] for dev tools[dependency-groups] (PEP 735)
Manual virtualenv activationuv run <cmd>
serial type aliasesBIGINT GENERATED ALWAYS AS IDENTITY

Quick Start: New Project

uv init myproject
cd myproject
uv add requests rich
uv add --group dev pytest ruff ty
uv run pytest
uv run ruff check .
uv run ty check src/

Full Project Setup

1. Create structure

uv init --package myproject
cd myproject

2. Configure pyproject.toml

[project]
name = "myproject"
version = "0.1.0"
requires-python = ">=3.13"
dependencies = []

[dependency-groups]
dev = [{include-group = "lint"}, {include-group = "test"}]
lint = ["ruff", "ty"]
test = ["pytest", "pytest-cov"]

[tool.ruff]
line-length = 100

[tool.ruff.lint]
select = ["ALL"]
ignore = ["D", "COM812", "ISC001"]

[tool.pytest.ini_options]
addopts = ["--cov=myproject"]

[tool.ty.environment]
python-version = "3.13"

3. Install and verify

uv sync --all-groups
uv run ruff check .
uv run ty check src/
uv run pytest

PEP 723: Standalone Scripts

For single-file scripts with dependencies, use inline metadata instead of pyproject.toml:

# /// script
# requires-python = ">=3.13"
# dependencies = ["requests", "rich"]
# ///

import requests
from rich import print

data = requests.get("https://httpbin.org/ip").json()
print(data)

Run with: uv run script.py (uv auto-installs dependencies).

Migration Guides

From requirements.txt + pip

uv init --bare
# Add each dependency
uv add requests rich pandas
# Add dev deps
uv add --group dev pytest ruff ty
uv sync

Then delete requirements.txt, requirements-dev.txt, and any virtualenv directories.

From Poetry

uv init --bare
# Transfer deps from [tool.poetry.dependencies]
uv add requests rich
# Transfer dev deps from [tool.poetry.group.dev.dependencies]
uv add --group dev pytest ruff
uv sync

Then delete poetry.lock and [tool.poetry] sections.

From flake8 + black + isort to ruff

  1. uv remove flake8 black isort (if installed)
  2. Delete .flake8, [tool.black], [tool.isort] configs
  3. uv add --group dev ruff
  4. uv run ruff check --fix . && uv run ruff format .

From mypy to ty

  1. uv remove mypy (if installed)
  2. Delete mypy.ini or [tool.mypy] section
  3. uv add --group dev ty
  4. uv run ty check src/

uv Commands Reference

CommandDescription
uv initCreate new project
uv init --packageCreate distributable package
uv add <pkg>Add dependency
uv add --group dev <pkg>Add to dev group
uv remove <pkg>Remove dependency
uv syncInstall dependencies
uv sync --all-groupsInstall all groups
uv run <cmd>Run in project venv
uv run --with <pkg> <cmd>Run with temporary dep
uv buildBuild package
uv publishPublish to PyPI
ss-modern-python — skill by JasonLo | Shared Context