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.

Ir para a instalação

Informações da origem

Repositório
ROCm/rocm-systems
Última atividade na origem
24 de abril de 2026 às 22:53
Idioma detectado do SKILL.md
inglês
Estrelas
497
Forks
406

Opções de instalação

Por padrão, está selecionado o prompt que primeiro revisa a origem. Você pode mudar para um comando direto ou baixar uma cópia local.

Revise os arquivos de origem

Leia o SKILL.md e os arquivos complementares exibidos pelo SkillsMP antes de decidir se vai instalar.

Exibindo SKILL.md

SKILL.md
Instruções da origem · Visualização somente leitura
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
Ver no GitHub