1# tooling 2 3ruff for linting and formatting. ty for type checking. pre-commit to enforce both. 4 5## ruff 6 7replaces black, isort, flake8, and dozens of plugins. one tool, fast. 8 9```bash 10uv run ruff format src/ tests/ # format 11uv run ruff check src/ tests/ # lint 12uv run ruff check --fix # lint and auto-fix 13``` 14 15### pyproject.toml config 16 17```toml 18[tool.ruff] 19line-length = 88 20 21[tool.ruff.lint] 22fixable = ["ALL"] 23extend-select = [ 24 "I", # isort 25 "B", # flake8-bugbear 26 "C4", # flake8-comprehensions 27 "UP", # pyupgrade 28 "SIM", # flake8-simplify 29 "RUF", # ruff-specific 30] 31ignore = [ 32 "COM812", # conflicts with formatter 33] 34 35[tool.ruff.lint.per-file-ignores] 36"__init__.py" = ["F401", "I001"] # unused imports ok in __init__ 37"tests/**/*.py" = ["S101"] # assert ok in tests 38``` 39 40## ty 41 42astral's new type checker. still early but fast and improving. 43 44```bash 45uv run ty check 46``` 47 48### pyproject.toml config 49 50```toml 51[tool.ty.src] 52include = ["src", "tests"] 53exclude = ["**/node_modules", "**/__pycache__", ".venv"] 54 55[tool.ty.environment] 56python-version = "3.10" 57 58[tool.ty.rules] 59# start permissive, tighten over time 60unknown-argument = "ignore" 61no-matching-overload = "ignore" 62``` 63 64## pre-commit 65 66enforce standards before commits reach the repo. 67 68### .pre-commit-config.yaml 69 70```yaml 71repos: 72 - repo: https://github.com/abravalheri/validate-pyproject 73 rev: v0.24.1 74 hooks: 75 - id: validate-pyproject 76 77 - repo: https://github.com/astral-sh/ruff-pre-commit 78 rev: v0.8.0 79 hooks: 80 - id: ruff-check 81 args: [--fix, --exit-non-zero-on-fix] 82 - id: ruff-format 83 84 - repo: local 85 hooks: 86 - id: type-check 87 name: type check 88 entry: uv run ty check 89 language: system 90 types: [python] 91 pass_filenames: false 92 93 - repo: https://github.com/pre-commit/pre-commit-hooks 94 rev: v5.0.0 95 hooks: 96 - id: no-commit-to-branch 97 args: [--branch, main] 98``` 99 100install with: 101 102```bash 103uv run pre-commit install 104``` 105 106never use `--no-verify` to skip hooks. fix the issue instead. 107 108## pytest 109 110```toml 111[tool.pytest.ini_options] 112asyncio_mode = "auto" 113asyncio_default_fixture_loop_scope = "function" 114testpaths = ["tests"] 115``` 116 117`asyncio_mode = "auto"` means async tests just work - no `@pytest.mark.asyncio` needed. 118 119## alternatives 120 121- [typsht](https://github.com/zzstoatzz/typsht) - parallel type checking across multiple checkers 122- [prek](https://github.com/zzstoatzz/prek) - pre-commit reimplemented in rust 123 124sources: 125- [pdsx/.pre-commit-config.yaml](https://github.com/zzstoatzz/pdsx/blob/main/.pre-commit-config.yaml) 126- [pdsx/pyproject.toml](https://github.com/zzstoatzz/pdsx/blob/main/pyproject.toml)