blob: fd7aef7cb7894df59e809ac73e71dfcf4ab663d4 [file] [view]
# Python Conventions
## pytest
* Register helper fixtures using `pytest_plugins = ["<module_path>"]`.
* Name fixture functions with `fixture_` prefix and pass public name via
`@pytest.fixture(name="foo")`.
## CLI & Arguments
* Use direct attribute access (e.g. `args.foo`) on `argparse.Namespace` with
well-defined shapes. Avoid defensive `getattr()`.
## Interface & ABC Docstrings
* In abstract base class / interface methods, always document `Args:`,
`Returns:`, and all custom exceptions raised under `Raises:`.
## Exception Handling
* Inherit custom exceptions from `Exception`, not `RuntimeError`.
## Subprocess
* Demarcate captured stdout/stderr in exceptions with 20 `=` characters:
`==================== STDOUT BEGIN ====================` /
`==================== STDOUT END ====================` (same for STDERR).
## TypedDict
* **External Objects**: When defining a `TypedDict` for an external object,
link to its definition in the docstring.
## Type Checking & Annotations
* **Version differences**: Guard version-specific arguments or APIs with runtime
checks (e.g. `if sys.version_info >= (3, 13):`) instead of
`# pyrefly: ignore[...]` comments.
* **`importlib.metadata` `PackagePath`**: `f.locate()` is typed as `PathLike`.
Wrap with `pathlib.Path(f.locate())` to call `.exists()`, `.is_file()`, etc.
* **In-file disables vs target skipping**: Prefer
`# pyrefly: ignore[<error-code>]` (e.g. `[missing-import]`) over
`tags = ["no-pyrefly"]`.
* **No blanket ignores**: NEVER use bare `# type: ignore` or literal
`# type: ignore[...]`. Use error-specific ignores instead.
* **Ignore comments**: When adding `# pyrefly: ignore[...]` or type
suppressions, add an explanatory comment indicating why it is suppressed.
* **Type assertions**: When adding assertions for type narrowing, add an
end-of-line comment: `assert foo is not None # type assert`.
* **Consent for `Any`**: Require user consent before changing type annotations
to `Any`.
* **Union syntax (`X | None`)**: Use `X | None` instead of `typing.Optional[X]`.
Add `from __future__ import annotations` if necessary.
* **Collections generics**: Use `collections.abc` (e.g., `Sequence`, `Iterable`,
`Iterator`, `Callable`, `Mapping`) and builtin generics (`list`, `dict`,
`tuple`, `set`) instead of `typing.XXX` collection types.
## Runfiles
* **Fail-fast creation**: Prefer `runfiles.CreateOrRaise()` over
`runfiles.Create()` + `assert`.
* **Path navigation**: Prefer `rf.root() / "<repo>/<path>"` over `Rlocation()`;
use `.glob()` on `runfiles.Path` instead of multi-root fallback loops.
## Delegating Functions
* Module-level functions delegating to class methods should have a docstring
referring to the class method (e.g. `"""Refer to \`Class.method\`."""`).