|
| 1 | +--- |
| 2 | +applyTo: "**/*.py" |
| 3 | +description: "Always-on Python style rules for the llm-patch monorepo (SOLID, OOP, type hints, OOD). Aligned with SPEC.md." |
| 4 | +--- |
| 5 | + |
| 6 | +# Python Style — Always On |
| 7 | + |
| 8 | +These rules apply to every `.py` file in the workspace. They derive |
| 9 | +from [SPEC.md](../../SPEC.md). Where this file and `SPEC.md` disagree, |
| 10 | +`SPEC.md` wins. |
| 11 | + |
| 12 | +## Type Hints |
| 13 | + |
| 14 | +- All public functions, methods, and class attributes have full type |
| 15 | + annotations. Use `from __future__ import annotations` at the top of |
| 16 | + modules that need forward references. |
| 17 | +- Prefer `collections.abc` over `typing` for ABCs (e.g., |
| 18 | + `Iterable`, `Mapping`). Use `|` union syntax (Python 3.11+). |
| 19 | +- No `Any` in public signatures unless documented and justified. |
| 20 | + |
| 21 | +## OOP / OOD |
| 22 | + |
| 23 | +- Use `abc.ABC` for new interfaces. Prefix interface names with `I` |
| 24 | + (e.g., `IWeightGenerator`). |
| 25 | +- Prefer **composition** over inheritance. Inherit only to satisfy an |
| 26 | + ABC or to share invariants. |
| 27 | +- Constructors take dependencies as parameters (DI). Don't reach out |
| 28 | + to module-level singletons. |
| 29 | +- Data classes for value objects: `@dataclass(frozen=True, slots=True)` |
| 30 | + unless the field requires Pydantic validation; in that case use |
| 31 | + `pydantic.BaseModel`. |
| 32 | + |
| 33 | +## Module Hygiene |
| 34 | + |
| 35 | +- **No module-level side effects** — no I/O, no network, no sleep, no |
| 36 | + registration of singletons at import time. |
| 37 | +- Every package has an `__init__.py` with an explicit `__all__` listing |
| 38 | + the public symbols (see [ADR-0003](../../docs/adr/0003-public-api-policy.md)). |
| 39 | +- New packages ship a `py.typed` marker. |
| 40 | + |
| 41 | +## Errors |
| 42 | + |
| 43 | +- Derive new exception types from `llm_patch_shared.errors.LlmPatchError` |
| 44 | + (or one of its subclasses). Never raise bare `Exception`. |
| 45 | +- Catch the narrowest exception possible. Don't swallow exceptions |
| 46 | + silently — log or re-raise. |
| 47 | + |
| 48 | +## Naming |
| 49 | + |
| 50 | +- Modules and packages: `snake_case`. |
| 51 | +- Classes: `PascalCase`. Interfaces: `IPascalCase`. |
| 52 | +- Constants: `UPPER_SNAKE_CASE`. |
| 53 | +- Test files: `test_<unit-under-test>.py`. |
| 54 | + |
| 55 | +## Imports |
| 56 | + |
| 57 | +- One import per line where the import system allows. |
| 58 | +- Group order: stdlib, third-party, first-party (handled by ruff isort). |
| 59 | +- **No** imports from another project's internal modules — see |
| 60 | + [ADR-0002](../../docs/adr/0002-layered-architecture.md) and |
| 61 | + [ADR-0003](../../docs/adr/0003-public-api-policy.md). |
0 commit comments