# Personal conventions (Python homelab) ## Stack defaults - **Package + venv:** uv. Every project has `pyproject.toml` + `uv.lock` checked in. `uv init`, `uv add `, `uv sync`, `uv run `. Never `pip install` outside a uv-managed venv. - **Python version:** pinned via `.python-version` in each project (uv reads it). Use latest stable unless a dep blocks. - **Linter + formatter:** ruff (replaces black + flake8 + isort). Config in `pyproject.toml` under `[tool.ruff]`. - **Type checker:** ty (Astral, replaces mypy). Config in `pyproject.toml` under `[tool.ty]`. - **Tests:** pytest. Layout: `src//` + `tests/` at repo root. Shared fixtures in `tests/conftest.py`. - **Pre-commit:** every project runs ruff (format + lint) + ty on commit. Config in `.pre-commit-config.yaml`. ## Project bootstrap (preferred) ```bash mkproj # cd ~/work/ && uv init uv add --dev pytest ruff ty pre-commit pre-commit install git add . && git commit -m "chore: scaffold" ``` ## pyproject.toml snippets (use these defaults) ```toml [tool.ruff] line-length = 100 target-version = "py313" [tool.ruff.lint] select = ["E", "F", "I", "UP", "B", "SIM", "RUF"] ignore = ["E501"] # line length handled by formatter [tool.ty] strict = true [tool.pytest.ini_options] testpaths = ["tests"] addopts = "-q --strict-markers --strict-config" ``` ## .pre-commit-config.yaml (use this exact set) ```yaml repos: - repo: https://github.com/astral-sh/ruff-pre-commit rev: v0.9.0 hooks: - id: ruff - id: ruff-format - repo: https://github.com/astral-sh/ty-pre-commit rev: 0.0.1a8 hooks: - id: ty-check ``` ## Git practices - Conventional commit prefixes: `feat:`, `fix:`, `chore:`, `refactor:`, `docs:`, `test:`. One concern per commit; keep messages in imperative mood. - Branch off `main`. No long-lived feature branches; rebase before merge. - **Never** `--force` push to `main`, never `reset --hard` other people's work. (Both denied in my permissions.) - Run `uv run pytest && uv run ruff check && uv run ty check` before pushing. pre-commit hook should catch most of it locally first. ## Don'ts - No `pip install` directly. Use `uv` so the lockfile is honored. - No mocking the database in integration tests if a real one is reachable (uv-managed sqlite is fine). - Don't add deps for trivial helpers — three lines of stdlib beats a transitive tree. - Don't write code comments that restate what the code does. Comment only on non-obvious *why*.