ADR 029: Docstring Style
Context
Our codebase uses Django with strong type hints, Pydantic models for data validation, and Django REST Framework (DRF) for API development. Consistent and clear documentation is essential for maintainability, onboarding, and effective collaboration, especially as type annotations and third-party integrations become more prevalent.
Docstrings also have a second reader: Sphinx autodoc renders them as the technical reference on docs.smarter.sh. A docstring is therefore reStructuredText, whatever its field style, and it cross-references other objects with Sphinx roles such as :class: and :meth:.
Alternatives Considered
No Standard Docstring Style: Leads to inconsistent documentation and confusion.
reStructuredText (Sphinx) Style: Sphinx’s native field lists. Rendered by autodoc without an extension, and consistent with the reST markup that the rest of a docstring already uses.
NumPy Style: Popular in scientific computing, but more complex than necessary for our needs.
Google Style: Clean and concise, but it needs the napoleon extension, and mixes a second syntax into otherwise reST docstrings.
Decision
Adopt the reStructuredText field list docstring format for all Python code, including Django models, views, DRF serializers, and Pydantic models.
Use type hints in function signatures.
sphinx_autodoc_typehintsrenders them, so:type:and:rtype:are needed only where an annotation is missing.Document parameters with
:param name:, the return value with:returns:, and exceptions with:raises SomeError:.Leverage field descriptions in Pydantic models where appropriate.
Ensure docstrings are concise and focused on intent and usage.
pydocstringformatter, a pre-commit hook, enforces the layout: an opening
"""on its own line, then a one-line summary that ends with a period.
Example:
def create_user(username: str, email: str) -> User:
"""
Create a new user.
:param username: The user's username.
:param email: The user's email address.
:returns: The created user instance.
:raises ValueError: If the username is invalid.
"""
The napoleon extension stays enabled, so the older docstrings that use Google style (Args:, Returns:) still render. New and edited code uses reST fields.
Consequences
Positive:
Improves readability and consistency across the codebase.
Docstrings render in Sphinx without translation, in the same syntax as their cross-references and code blocks.
Matches the code: reST fields are the large majority of the codebase’s docstrings.
Negative:
Requires discipline to maintain consistency.
Some legacy docstrings use Google style, and are converted when they are edited.
References
Related ADRs: None