ADR 0016: Python Docstrings (Google Style) and pdoc
Ratification
Adopted before ADR 0018. There was no separate ratification process. Git history for this file on main is the record.
- Discussion Issue: not recorded (before ADR 0018)
- Merge PR: see git history for this file
- Accepted: as merged to
main
Context
Why this matters: OpenAPI describes HTTP; it does not replace module-level intent for internal services, repositories, and edge cases. Consistent docstrings make code review faster and give pdoc something stable to render for internal API reference.
One agreed style (Google-style) avoids bikeshedding and helps humans and assistants follow the same checklist
when touching Python under app/, scripts/, tests/, and tools/.
Decision
-
Style: Use Google-style docstrings for all new and updated Python in
app/,scripts/,tests/, andtools/. Public functions and classes MUST have a docstring unless the name is completely self-explanatory and private (leading_); even then, prefer a one-line summary for anything non-trivial. - Language: Docstring text is in English (same as code identifiers and API error keys). Comments for local teams may use other languages in separate docs, not in docstrings.
- First line: Imperative or descriptive one-line summary (subject: verb), ending without a period if it is a phrase fragment, or with a period if it is a full sentence—either is acceptable; stay consistent within a file.
-
Sections (use when applicable):
Args,Returns,Raises,Yields,Note/Notes,Attributes(classes and dataclasses). -
pdoc: Generated HTML under
docs/api/is the browseable view; keeping docstrings accurate is part of maintainability. See Documentation pipeline, §6.
Scope
- In scope: docstrings, module-level
"""..."""for packages, ADR and editor rules. - Out of scope: replacing OpenAPI descriptions; changing Ruff/mypy rules solely for docstrings.
Templates (copy from here)
Module
"""One-line summary of the module responsibility.
Optional longer context: what callers use this for, main exports.
"""
Function
"""Do one specific thing (summary line).
Args:
name: What this parameter represents.
other: Second parameter.
Returns:
What the caller receives.
Raises:
ValueError: When the input is invalid.
HTTPException: When returning a business-layer error (document status if non-obvious).
"""
Class
"""Short description of the class role.
Attributes:
field: Meaning of this attribute.
"""
Method / property
Same as function; use Args including self only when non-obvious.
Checklist for humans and LLM agents
- After changing behavior, update the docstring in the same PR.
- Do not restate type information that is already in type hints unless it adds semantics.
- For FastAPI route handlers, document idempotency, security assumptions, and replay behavior where not obvious from OpenAPI.
- For service/repository methods, document
RaisesforHTTPExceptionand business rules. - Prefer linking related concepts with
:class:`.../:func:`...(Sphinx-style cross-refs) where pdoc can resolve them; otherwise use plain backticks for code names. - Run
make api-docslocally when changing publicappAPIs to verify rendering.
Alternatives considered
-
NumPy-style docstrings.
- Pros: common in data science stacks.
- Cons: heavier visually; Google style already used in this repo (e.g.
scripts/sync_docs.py).
-
Sphinx-only (no pdoc).
- Pros: maximum features.
- Cons: more setup; pdoc matches the desired “cargo doc” workflow with minimal config.
Consequences
Positive
- Single convention for reviews and for generated API HTML.
- Agents can follow the ADR and the Cursor rule without guessing.
Trade-offs
- Existing files may still carry older phrasing until touched; opportunistic updates are welcome.
Page history
| Date | Change | Author |
|---|---|---|
| Added Page history section (repository baseline). | Ivan Boyarkin |