# tooling ruff for linting and formatting. ty for type checking. pre-commit to enforce both. ## ruff replaces black, isort, flake8, and dozens of plugins. one tool, fast. ```bash uv run ruff format src/ tests/ # format uv run ruff check src/ tests/ # lint uv run ruff check --fix # lint and auto-fix ``` ### pyproject.toml config ```toml [tool.ruff] line-length = 88 [tool.ruff.lint] fixable = ["ALL"] extend-select = [ "I", # isort "B", # flake8-bugbear "C4", # flake8-comprehensions "UP", # pyupgrade "SIM", # flake8-simplify "RUF", # ruff-specific ] ignore = [ "COM812", # conflicts with formatter ] [tool.ruff.lint.per-file-ignores] "__init__.py" = ["F401", "I001"] # unused imports ok in __init__ "tests/**/*.py" = ["S101"] # assert ok in tests ``` ## ty astral's new type checker. still early but fast and improving. ```bash uv run ty check ``` ### pyproject.toml config ```toml [tool.ty.src] include = ["src", "tests"] exclude = ["**/node_modules", "**/__pycache__", ".venv"] [tool.ty.environment] python-version = "3.10" [tool.ty.rules] # start permissive, tighten over time unknown-argument = "ignore" no-matching-overload = "ignore" ``` ## pre-commit enforce standards before commits reach the repo. ### .pre-commit-config.yaml ```yaml repos: - repo: https://github.com/abravalheri/validate-pyproject rev: v0.24.1 hooks: - id: validate-pyproject - repo: https://github.com/astral-sh/ruff-pre-commit rev: v0.8.0 hooks: - id: ruff-check args: [--fix, --exit-non-zero-on-fix] - id: ruff-format - repo: local hooks: - id: type-check name: type check entry: uv run ty check language: system types: [python] pass_filenames: false - repo: https://github.com/pre-commit/pre-commit-hooks rev: v5.0.0 hooks: - id: no-commit-to-branch args: [--branch, main] ``` install with: ```bash uv run pre-commit install ``` never use `--no-verify` to skip hooks. fix the issue instead. ## pytest ```toml [tool.pytest.ini_options] asyncio_mode = "auto" asyncio_default_fixture_loop_scope = "function" testpaths = ["tests"] ``` `asyncio_mode = "auto"` means async tests just work - no `@pytest.mark.asyncio` needed. ## alternatives - [typsht](https://github.com/zzstoatzz/typsht) - parallel type checking across multiple checkers - [prek](https://github.com/zzstoatzz/prek) - pre-commit reimplemented in rust sources: - [pdsx/.pre-commit-config.yaml](https://github.com/zzstoatzz/pdsx/blob/main/.pre-commit-config.yaml) - [pdsx/pyproject.toml](https://github.com/zzstoatzz/pdsx/blob/main/pyproject.toml)