Python Coding Standards
Python Coding Standards¶
This section extends the SuperGenius C++ Coding Standards to Python source
files (e.g. gnus-poc/, tooling, test harnesses). The classifications are
identical: Required rules must be followed (enforced by ruff + mypy,
which play the roles of clang-format and clang-tidy); Recommended
rules should be followed unless there is a compelling reason to deviate.
The §1.1 General Principles apply unchanged: maintainability first, think of the reader, be explicit, minimize scope.
1 Comments and Docstrings¶
Required: Every module shall have a top-of-file docstring stating its purpose (the analogue of the §2.1 top-of-file comment).
Required: All public classes, functions, and modules shall have docstrings (Google style). Comment size should match the function's size and complexity.
Required: Use # single-line comments for inline comments. Block comments
sit on their own line, at the same indentation level as the code they describe.
2 Code Layout¶
Required: Indentation is 4 spaces. Never tabs (PEP 8; enforced by ruff format).
Recommended: Lines should not exceed 100 columns (the C++ limit of 120 is acceptable where the team prefers consistency with C++).
Required: One statement per line. Each declaration on a new line.
Required: Break long lines inside parentheses, brackets, or braces rather than with backslash continuations. Indent the continuation past the current indent column. Wrap conditional expressions after the logical operators.
Recommended: Two blank lines between top-level definitions, one between method definitions. At most one blank line within a function body.
3 Naming Conventions¶
| Entity | Case | Example | Enforced |
|---|---|---|---|
| Modules / packages | snake_case | sgfp4_format.py |
Required |
| Classes / Exceptions | PascalCase | QuadtreeEncoder |
Required |
| Functions / methods | snake_case, verb-noun | decode_v2() |
Required |
| Variables / parameters | snake_case | leaf_index |
Required |
| Compile-time constants | UPPER_CASE |
SPLIT_MAP_BYTES |
Required |
| Enum types | PascalCase | class CodeMode(IntEnum) |
Required |
| Enum members | UPPER_CASE |
FP4_AFFINE |
Recommended |
| Non-public members | single leading _ |
_build_split_map |
Required |
Required: No Hungarian notation or type prefixes.
Recommended: Boolean-returning functions start with is_ or has_
(the analogue of §4.6). Factory functions start with create_; teardown
functions with destroy_.
Required: Wire-format and protocol "magic numbers" shall be named exactly
once in a dedicated constants module (the analogue of §4.5
avoid-magic-numbers), imported by every producer and consumer of the format.
Do not duplicate literal masks, shifts, or sizes across files.
4 Language Usage¶
Required: Use enum.Enum / enum.IntEnum for closed sets of values.
Bare integer constants with a comment are not an enum (analogue of §5.9
enum class).
Required: All non-boolean conditional expressions shall be explicit
(analogue of §5.12). Test None with is / is not; test bit flags with
!= 0; do not rely on truthiness of objects whose falsy value is ambiguous.
if flags & RESERVED_MASK != 0: # correct
if flags & RESERVED_MASK: # incorrect
if node is None: # correct
if not node: # incorrect
Required: No mutable default arguments (def f(items=[])). Use
Optional[...] = None and initialize in the body.
Required: Acquire resources with context managers (with) — the RAII
analogue. Files, sockets, and locks shall not rely on __del__.
Required: Type hints on all public function signatures. mypy (or
equivalent) must pass on new code.
Recommended: Prefer pathlib.Path over os.path string manipulation.
Prefer f-strings over % or .format(). Prefer dataclasses for simple
data carriers.
Recommended: Use nonlocal/class state instead of single-element list
closure hacks (idx = [0]).
Recommended: Minimize break/continue in loops, as in §5.13. Count
loops ascending.
5 Class Design¶
Required: Data members shall not be public (§6.1 analogue): prefix with
_; expose behavior through methods or @property.
Recommended: Prefer composition over inheritance (§6.4 applies unchanged).
Use abc.ABC for interfaces.
Required: A class's public surface shall be documented in its docstring;
__all__ shall be defined in package __init__.py files that re-export.
6 Error Handling¶
Required: Raise specific exception types, never bare except: and never
except Exception without re-raising or wrapping. Define a small custom
exception hierarchy per package (e.g. SGFP4FormatError(ValueError)).
Required: assert documents invariants only (§7.2 analogue). Never use
assert for input validation or error handling — it is stripped under
python -O.
Recommended: Functions should document raised exceptions in their docstrings.
7 Module and File Layout¶
Required: Import order: (1) standard library, (2) third-party,
(3) project-local (the analogue of §8.3; enforced by ruff isort rules).
Required: No circular imports. Shared constants/types live in a leaf
module (e.g. *_format.py) that imports nothing from the package.
Required: Executable module code guarded by if __name__ == "__main__":.
Recommended: Functions should fit within approximately 100 lines (§8.4 applies unchanged). Extract helpers rather than nesting logic.
Recommended: Avoid monkey-patching and runtime modification of other modules' objects.
8 Platform Abstraction¶
Required: No scattered sys.platform checks in source files (§10
analogue). Isolate platform differences in a single platform_utils module.
9 Testing¶
Required: New logic ships with pytest tests in the same change.
Recommended: Tests use seeded RNGs (np.random.default_rng(seed)) for
determinism. Binary-format code shall include hand-constructed golden
vectors, not only round-trip self-consistency checks.
10 Tooling¶
| C++ tool | Python analogue | Purpose |
|---|---|---|
| clang-format | ruff format (or black) |
Layout enforcement |
| clang-tidy | ruff check |
Static analysis, naming, import order |
| — | mypy |
Type checking (Required checks must pass clean) |
Before committing, always: format, lint, type-check, and run tests (§12.3 applies unchanged).