Python 3.x, pinned per project via .python-version. Two project
styles:
- uv projects (default for new): pyproject.toml + uv.lock are the
source of truth for deps;
uv sync,uv run <cmd>. - pip/venv projects: requirements.txt is the single source of truth;
install with
./venv/bin/pip install -r requirements.txt. uv equivalent in the same venv:uv pip sync --python venv/bin/python requirements.txt.
pyproject.toml deps (+ dev extras), build backend, tool config
uv.lock
requirements.txt pip/venv projects instead
src/<package>/ the package (snake_case; repo name kebab-case)
tests/ pytest, mirroring src/ - one test module per module
docs/ specs & domain knowledge, when the project has them
Never touch the global python3 or pip. The only global call in a
project's life is the one-time python3 -m venv venv in the project
dir (uv: uv venv venv); from then on exclusively ./venv/bin/python
and ./venv/bin/pip. uv obeys the same rule by design: uv run and
uv pip never leave the project env.
- ruff for lint + format: line-length 100, select at least
E,F,W,I,UP,B,SIM. - pytest:
asyncio_mode = autofor async projects. Tests never touch the network - fixtures, stub resolvers, in-process servers, memory DBs. - Commit lint:
uvx gitlint. - Optional
Makefilewith achecktarget (ruff + pytest) as the single local gate; CI runs the same commands, so local green means CI green.
repo data-export → package data_export → class DataExport.