fix
This commit is contained in:
@@ -0,0 +1,56 @@
|
||||
# Default Config
|
||||
|
||||
Baseline mypy and ruff settings used when `pyproject.toml` is absent or incomplete.
|
||||
|
||||
## mypy (strict mode)
|
||||
|
||||
```ini
|
||||
[mypy]
|
||||
python_version = 3.13
|
||||
strict = true
|
||||
warn_return_any = true
|
||||
warn_unused_ignores = true
|
||||
warn_redundant_casts = true
|
||||
disallow_untyped_defs = true
|
||||
disallow_incomplete_defs = true
|
||||
check_untyped_defs = true
|
||||
disallow_any_generics = true
|
||||
no_implicit_reexport = true
|
||||
```
|
||||
|
||||
## ruff
|
||||
|
||||
```toml
|
||||
[tool.ruff]
|
||||
target-version = "py313"
|
||||
line-length = 88
|
||||
|
||||
[tool.ruff.lint]
|
||||
select = [
|
||||
"E", # pycodestyle errors
|
||||
"W", # pycodestyle warnings
|
||||
"F", # pyflakes
|
||||
"UP", # pyupgrade
|
||||
"B", # flake8-bugbear
|
||||
"SIM", # flake8-simplify
|
||||
"I", # isort
|
||||
"RUF", # ruff-specific
|
||||
"ANN", # flake8-annotations (public API must be typed)
|
||||
]
|
||||
ignore = [
|
||||
"ANN101", # missing type for self
|
||||
"ANN102", # missing type for cls
|
||||
]
|
||||
```
|
||||
|
||||
## pyproject.toml Priority Rules
|
||||
|
||||
When `pyproject.toml` exists, always prefer its values over these defaults:
|
||||
|
||||
| Config key | Behaviour |
|
||||
|---|---|
|
||||
| `[tool.mypy] strict = false` | Still enforce strict — mention the deviation to the user |
|
||||
| `[tool.mypy] python_version` | Use as-is; warn if < 3.13 |
|
||||
| `[tool.ruff.lint] ignore` | Respect fully — do not flag ignored rules |
|
||||
| `[tool.ruff] line-length` | Use for E501; default 88 if absent |
|
||||
| `[tool.ruff.lint] select` | Merge with defaults — do not drop user selections |
|
||||
@@ -0,0 +1,97 @@
|
||||
# Fix Application Rules
|
||||
|
||||
Rules the agent must follow when applying accepted review fixes.
|
||||
|
||||
## General Rules
|
||||
|
||||
1. **One file at a time** — edit files sequentially, not in parallel, to avoid conflicts
|
||||
2. **Minimal diff** — change only what is needed; do not reformat unrelated code
|
||||
3. **Preserve comments** — keep existing comments unless they are part of the fix
|
||||
4. **No behaviour changes** — fixes must not alter runtime behaviour unless the original was a bug
|
||||
5. **Add imports sparingly** — only add imports that are strictly required by the fix
|
||||
|
||||
## Type Annotation Fixes
|
||||
|
||||
- Add annotations using Python 3.13+ syntax: `X | None` not `Optional[X]`
|
||||
- Use `list[str]` not `List[str]`, `dict[str, int]` not `Dict[str, int]`
|
||||
- For functions with no return: annotate as `-> None`
|
||||
- For `*args` / `**kwargs`: annotate properly, e.g. `*args: str`, `**kwargs: int`
|
||||
- Do not add `from __future__ import annotations` — use native syntax directly
|
||||
|
||||
## mypy `# type: ignore` Usage
|
||||
|
||||
- Never add bare `# type: ignore` — always use specific code: `# type: ignore[assignment]`
|
||||
- Only use `type: ignore` as last resort when fixing the root cause is not feasible
|
||||
- Add a comment explaining why: `# type: ignore[misc] # third-party stub incomplete`
|
||||
|
||||
## ruff Auto-fix Rules
|
||||
|
||||
- Run `ruff check --fix <file>` only for safe auto-fixable rules (F401, UP*, I*)
|
||||
- Do NOT use `--unsafe-fixes` without explicit user confirmation
|
||||
- After auto-fix, re-read the file to verify no logic was altered
|
||||
|
||||
## Mutable Default Arguments
|
||||
|
||||
```python
|
||||
# Before
|
||||
def process(items: list[str] = []) -> None: ...
|
||||
|
||||
# After
|
||||
def process(items: list[str] | None = None) -> None:
|
||||
if items is None:
|
||||
items = []
|
||||
```
|
||||
|
||||
## Union Type Modernization (Python 3.13+)
|
||||
|
||||
```python
|
||||
# Before
|
||||
from typing import Optional, Union
|
||||
def f(x: Optional[str]) -> Union[int, str]: ...
|
||||
|
||||
# After
|
||||
def f(x: str | None) -> int | str: ...
|
||||
```
|
||||
|
||||
Remove now-unused `Optional` / `Union` imports after rewriting.
|
||||
|
||||
## TypeAlias Modernization (PEP 695)
|
||||
|
||||
```python
|
||||
# Before
|
||||
from typing import TypeAlias
|
||||
Vector: TypeAlias = list[float]
|
||||
|
||||
# After
|
||||
type Vector = list[float]
|
||||
```
|
||||
|
||||
## Broad Exception Handling
|
||||
|
||||
```python
|
||||
# Before
|
||||
try:
|
||||
...
|
||||
except Exception:
|
||||
pass
|
||||
|
||||
# After — option A: log and re-raise
|
||||
except Exception:
|
||||
logger.exception("Unexpected error")
|
||||
raise
|
||||
|
||||
# After — option B: specific exception (preferred when possible)
|
||||
except ValueError as exc:
|
||||
logger.warning("Invalid value: %s", exc)
|
||||
```
|
||||
|
||||
## Post-Fix Validation Sequence
|
||||
|
||||
After applying all accepted fixes to a file:
|
||||
|
||||
1. `mypy --strict <file>` — must return exit code 0
|
||||
2. `ruff check <file>` — must return exit code 0
|
||||
3. If any new violations appear that were NOT in the original report — fix them silently and note in the summary
|
||||
4. Report final status:
|
||||
- ✅ Clean — zero violations remaining
|
||||
- ⚠️ Remaining — list unresolved items with reason
|
||||
@@ -0,0 +1,73 @@
|
||||
# Review Checklist
|
||||
|
||||
Full criteria for categorizing findings in the Python review skill.
|
||||
|
||||
## 🔴 Must Fix — Correctness & Type Safety
|
||||
|
||||
These block merge. Apply by default.
|
||||
|
||||
### mypy strict violations
|
||||
- `error:` any mypy error (all are must-fix under strict mode)
|
||||
- Implicit `Any` — untyped function parameters or return values
|
||||
- `type: ignore` without a specific error code (e.g. bare `# type: ignore`)
|
||||
- Incompatible types in assignment or return
|
||||
- Missing `--strict` compatibility: missing `py.typed`, missing stubs
|
||||
|
||||
### Logic & Security (manual review)
|
||||
- Mutable default arguments: `def f(x: list = [])` → use `None` + guard
|
||||
- Shadowing built-ins: `list`, `dict`, `id`, `type`, `input`, etc.
|
||||
- Uncaught exceptions from external I/O without explicit handling
|
||||
- SQL/shell injection risks (string formatting into queries/commands)
|
||||
- Hardcoded secrets or credentials
|
||||
- `assert` used for runtime validation (stripped with `-O`)
|
||||
|
||||
---
|
||||
|
||||
## 🟡 Should Fix — Code Quality
|
||||
|
||||
These hurt maintainability. Fix unless explicitly skipped.
|
||||
|
||||
### ruff violations (common)
|
||||
- `E501` — line too long (respect `line-length` from pyproject.toml)
|
||||
- `F401` — unused import
|
||||
- `F841` — local variable assigned but never used
|
||||
- `B006` — mutable argument default
|
||||
- `B007` — loop variable unused
|
||||
- `UP` prefix — pyupgrade rules (use modern Python syntax)
|
||||
- `SIM` prefix — simplifiable conditions
|
||||
- `RUF` prefix — Ruff-specific best practices
|
||||
|
||||
### Manual quality
|
||||
- Missing return type annotation on public functions/methods
|
||||
- Missing docstring on public API (classes, public methods, module)
|
||||
- `pass` in `except` block without a comment explaining why
|
||||
- `print()` left in production code (use `logging`)
|
||||
- Overly broad `except Exception` without re-raise or specific handling
|
||||
- Dead code: unreachable branches, commented-out code blocks
|
||||
|
||||
---
|
||||
|
||||
## 🟢 Consider — Optimization & Modern Python 3.13+
|
||||
|
||||
Suggestions only. Offer but don't apply without confirmation.
|
||||
|
||||
### Python 3.13+ idioms
|
||||
- Use `type X = ...` (PEP 695) instead of `TypeAlias`
|
||||
- Use `X | Y` union syntax instead of `Union[X, Y]` or `Optional[X]`
|
||||
- Use `TypeVar` with `type` statement (PEP 695) instead of old `TypeVar()`
|
||||
- `@override` decorator (PEP 698) for overriding methods
|
||||
- `tomllib` (stdlib) instead of third-party TOML parsers
|
||||
- `pathlib.Path` instead of `os.path` string operations
|
||||
|
||||
### Performance
|
||||
- Generator expressions instead of list comprehensions when result is iterated once
|
||||
- `__slots__` on data-heavy classes to reduce memory
|
||||
- `functools.cache` / `functools.lru_cache` for pure deterministic functions
|
||||
- Avoid repeated attribute lookup in tight loops (`local = self.attr`)
|
||||
- Prefer `collections.deque` over `list` for O(1) pop from front
|
||||
|
||||
### Readability
|
||||
- Replace long `if/elif` chains with `match/case` (structural pattern matching)
|
||||
- Extract deeply nested logic into named helper functions
|
||||
- Use `dataclasses.dataclass` or `pydantic.BaseModel` for plain data containers
|
||||
- Named tuples or `TypedDict` instead of untyped `dict` returns
|
||||
Reference in New Issue
Block a user