Skip to main content

amdsmi-python-style-guide

ROCm Python style guide based on TheRock. Use when: writing Python code, reviewing Python PRs, checking Python style, creating Python scripts, type hints, error handling patterns, pathlib usage, argparse CLI design.

Zur Installation springen

Quellinformationen

Repository
ROCm/rocm-systems
Letzte Quellaktivität
24. April 2026 um 22:53
Erkannte Sprache von SKILL.md
Englisch
Sterne
508
Forks
414

Installationsoptionen

Standardmäßig ist der Prompt ausgewählt, der zuerst die Quelle prüft. Sie können zu einem direkten Befehl wechseln oder eine lokale Kopie herunterladen.

Quelldateien prüfen

Lesen Sie SKILL.md und alle von SkillsMP angezeigten Begleitdateien, bevor Sie sich für eine Installation entscheiden.

SKILL.md wird angezeigt

SKILL.md
Quellanweisungen · Schreibgeschützte Vorschau
name
amdsmi-python-style-guide
description
ROCm Python style guide based on TheRock. Use when: writing Python code, reviewing Python PRs, checking Python style, creating Python scripts, type hints, error handling patterns, pathlib usage, argparse CLI design.
# Python Style Guide (ROCm / TheRock) Follows PEP 8, enforced by **Ruff** (amd-smi) or **Black** (TheRock) via pre-commit. Source: [TheRock python_style_guide.md](https://github.com/ROCm/TheRock/blob/main/docs/development/style_guides/python_style_guide.md) ## Core Principles - Fail fast and loud — false positives over silent corruption - When in doubt, raise an exception --- ## Type Hints - Type hints on **all** function signatures - Syntax that is compatible with python 3.6.8+ - **Never** use `Any` except in rare generic code - **Never** use `Optional[T]`, `Union[X, Y]`, `List`, `Dict` — use built-in equivalents - **Do NOT** use `from __future__ import annotations` ### Extract Complex Types - Type appears in multiple signatures → `NamedTuple` or `TypeAlias` - Dict/tuple with 3+ fields → `dataclass` or `NamedTuple` - If you document what tuple fields mean → use `NamedTuple` ```python # Good class KpackInfo(NamedTuple): kpack_path: Path size: int kernel_count: int # Bad def get_info() -> tuple[Path, int, int]: ... ``` ### Dataclasses Over Tuples Structured data with multiple fields → `@dataclass` or `NamedTuple`, not raw tuples. Tuples OK for: simple pairs `(x, y)`, stdlib unpacking, single-use immediate unpacking. --- ## Function Calls & Arguments - 3+ parameters or ambiguous types → **use keyword arguments** - Multiple booleans → **always** use keyword arguments ```python # Good result = build(amdgpu_family="gfx942", enable_testing=True, use_ccache=False) # Bad result = build("gfx942", True, False) ``` --- ## Code Organization - All imports at **top of file** — inline only for documented circular deps (add comment explaining why) - Scripts must have `if __name__ == "__main__":` guard - CLI scripts must use `argparse` (not raw `sys.argv`) - Access `argparse` attrs directly: `args.foo`, not `getattr(args, "foo", default)` - No duplicate code — extract to shared functions - No magic numbers or fake estimates - Methods < 30 lines, classes < 200 lines (ideally) - If a class has 7+ responsibilities → split into focused classes - God objects doing everything → multiple focused classes; 100+ line methods → extract helpers --- ## Error Handling | Rule | Detail | |------|--------| | Fail fast | Never silently continue or produce incomplete results | | Specific exceptions | `FileNotFoundError`, `subprocess.CalledProcessError` — not bare `except Exception` | | Preserve chains | Always use `from e` when re-raising | | Validate results | After critical ops: check file exists, non-empty, expected size | | No binutils timeouts | Never `timeout=` on `readelf`, `objcopy`, etc. | ```python # Good — distinguish error conditions try: output = subprocess.check_output([readelf, "-S", str(file_path)]) except subprocess.CalledProcessError as e: if e.returncode == 1: return False # legitimate "not found" raise RuntimeError(f"readelf failed: {e.output}") from e except FileNotFoundError as e: raise RuntimeError(f"readelf not found: {readelf}") from e # Bad — swallows everything try: output = subprocess.check_output([readelf, "-S", str(file_path)]) except Exception: return False ``` --- ## Filesystem & Paths - **`pathlib.Path` everywhere** — no `os.path`, no string concatenation for paths - No assumptions about CWD — derive from `Path(__file__).resolve().parent` - No hard-coded project paths — use env vars, `tempfile`, or relative to `__file__` ```python # Good THIS_DIR = Path(__file__).resolve().parent config = THIS_DIR / "config.json" # Bad config = Path("build_tools/config.json") # assumes CWD config = Path("/home/user/project/config.json") # hard-coded ``` --- ## Performance - Compile regexes at **module level**, not inside functions - Check cheap conditions before expensive ones (magic bytes before subprocess) - Cache expensive computations when called repeatedly - Use generators for large datasets --- ## Testing - Verify fail-fast behavior with `pytest.raises` - Use real temp files over mocks for filesystem operations - Mock only external dependencies (network, expensive tools) - Integration tests should exercise the full path --- ## amd-smi Python Conventions ### Naming - `py-interface/amdsmi_interface.py` mirrors C API names (`amdsmi_get_*`, `amdsmi_set_*`) - `amdsmi_cli/` uses `snake_case` methods - Private functions/methods: `_` prefix ### Project Layout | Directory | Purpose | |-----------|---------| | `py-interface/` | Python bindings — `amdsmi_interface.py`, `amdsmi_wrapper.py`, `amdsmi_exception.py` | | `amdsmi_cli/` | CLI tool — `amdsmi_commands.py`, `amdsmi_parser.py`, `amdsmi_helpers.py` | ### Critical Python Files (high churn — review carefully) - `amdsmi_cli/amdsmi_commands.py` — CLI behavior regressions, output format changes - `py-interface/amdsmi_interface.py` — must stay in sync with C header `amdsmi.h` - `py-interface/amdsmi_wrapper.py` — generated bindings + library loader (see loader rules below) - `amdsmi_cli/amdsmi_parser.py` — argument parsing ### Library Loader Rules (`amdsmi_wrapper.py`) Changes to `_detect_install_context`, `_build_candidate_paths`, or `_load_library` are **❌ BLOCKING** if they break system or pip install context. Verify: - `Path(__file__).resolve()` used correctly - pip detection logic intact - `_libraries['libamd_smi.so']` key preserved - Sync with `tools/generator.py` ### Python Testing - Tests must work with **both** system-installed and pip-installed amdsmi - CLI tests live in `amdsmi_cli/` - Verify fail-fast behavior with `pytest.raises` - Use real temp files over mocks for filesystem operations - Mock only external dependencies (network, expensive tools) - Integration tests should exercise the full path --- ## Review Checklist When reviewing Python code, verify: - [ ] Type hints on all functions — modern syntax, no `Any` - [ ] No `from __future__ import annotations` - [ ] Complex types extracted to `NamedTuple`/`dataclass` - [ ] Specific exception handling — no bare `except Exception` - [ ] Fail-fast — no silent `continue` on errors - [ ] `from e` on all re-raises - [ ] `pathlib.Path` for all filesystem ops - [ ] No CWD assumptions, no hard-coded paths - [ ] No magic numbers or fake estimates - [ ] No duplicate code - [ ] `argparse` for CLI, `__main__` guard for scripts - [ ] Keyword args for complex function calls - [ ] All imports at top (inline only with circular-dep comment) - [ ] No timeouts on binutils - [ ] Output validation after critical operations - [ ] Methods < 30 lines, classes < 200 lines
Auf GitHub ansehen