Codebase Orientation
How to read a Python service repository - folder structure, ownership, conventions, and the fastest path from clone to confident navigation.
Search across all documentation pages
How to read a Python service repository - folder structure, ownership, conventions, and the fastest path from clone to confident navigation.
service/
├── src/billing/ # application package
├── tests/ # mirrors src layout
├── alembic/ # DB migrations (if SQLAlchemy)
├── pyproject.toml # deps, ruff, pytest config
├── uv.lock # reproducible resolve
├── docs/ # ADRs, onboarding, runbooks
└── .github/workflows/ # CI truth sourceWhen to reach for this:
# Orientation session script (30-60 min self-guided)
tree -L 2 src/ tests/
rg -l "router|Blueprint|urlpatterns" src/ # find HTTP entrypoints
cat pyproject.toml | rg "name|requires-python|scripts"
cat docs/adr/0001-*.md 2>/dev/null || ls docs/
gh api repos/:owner/:repo/contents/CODEOWNERS 2>/dev/null || cat CODEOWNERS
uv run pytest --collect-only -q | head # see test modulesTrace one user story:
src/billing/api/routes/orders.py).services/order_service.py).repositories/order_repo.py).alembic/versions/).What this demonstrates:
src/ layout separates importable package from repo rootsrc/<name>/ avoids accidental imports from repo root on PYTHONPATH.tests/billing/api/test_orders.py maps to src/billing/api/orders.py.CODEOWNERS auto-requests domain experts on PRs.| Artifact | Answers |
|---|---|
| README | Quickstart commands |
docs/onboarding.md | Team-specific gotchas |
| ADRs | Framework and schema decisions |
| CI workflow | Required quality gates |
CONTRIBUTING.md | PR and commit rules |
# Discover package version and entrypoints programmatically
import importlib.metadata as m
m.version("billing")
# console_scripts from pyproject [project.scripts]pyproject frameworks list..env.example stale. Fix: file doc bug on first missing key.docs/onboarding.md.| Alternative | Use When | Don't Use When |
|---|---|---|
| Architecture diagram wiki | High-level only | Diagram stale vs code |
pydeps / import graphs | Untangling cycles | First hour on repo |
| Code search IDE | Symbol jump | No local clone yet |
| Pairing tour | Complex legacy | Self-serve onboarding scale |
Read root README for package list; cd services/billing-api per service with own uv.lock.
Teams use services/ layer or domain package - avoid fat route handlers; search class *Service.
Check Makefile / scripts/generate - do not hand-edit OpenAPI client output.
Search settings or LaunchDarkly SDK init - flags hide incomplete paths.
Follow git submodule or monorepo libs/ - note separate version bump process.
May be pre-src migration - README should say migration status; prefer src/ for new code.
CODEOWNERS on infra/ or platform team tag in README.
Date in filename - if older than 2 years, verify still true with buddy.
Each apps/* is bounded context - start at urls.py and models.py per app.
rg "@app.task" src/ or celery.py include list.
Stack versions: This page was written for Python 3.14.0 (stable 3.14, maintenance 3.13), FastAPI 0.115+, Django 5.2, Flask 3.1, Pydantic 2, PyTorch 2.6+, pandas 2.2+, Polars 1.x, ruff 0.9+, and uv 0.6+.
Reviewed by Chris St. John·Last updated Jul 16, 2026