Project conventions beyond what ruff enforces (ruff config lives in [tool.ruff] in pyproject.toml).
- Line length 80 (72 for docstrings and comments).
- Single quotes.
- Rules:
E, F, W, I, G.
- Annotate function arguments and returns. Modern union syntax (
X | None), nottyping.Optional. - Explicit
-> None. - Don't annotate obvious locals. Do annotate empty collections,
Any-returning calls,None-initialized vars.
- Validate input at the boundary.
raise TypeError/ValueErrorwith the offending type or value in the message.
logging.basicConfigonly insidemain(). Module scope keeps justlogger = logging.getLogger(__name__).%-style placeholders, no f-strings (enforced byG004).
- NumPy-style. Public functions only — private (
_name) helpers don't get docstrings. - Sections: one-line summary;
Parameters;Returns(when non-None);Raises(when applicable). - Blank line after every docstring.
- 72-char limit (enforced by
W505).
__all__in every__init__.pythat re-exports symbols.
- Only split parenthesized expressions when a single line would exceed 80 chars.
- Blank line before the final
returnin non-trivial functions.
- Mirror source layout (
pyment/x/y.py→tests/x/test_y.py). - Testing private (
_name) functions is fine. - Assert messages follow
'Expected <subject> to <verb> <outcome>'. The subject is the function or the value it returns. Usereturnfor scalars/objects,yieldfor images/arrays. Reference parameter names rather than their values when the expected result is input-derived; state values explicitly only when they are hardcoded in the implementation. Append a condition clause (for ...,when ...) when the scenario needs disambiguation.