aio-libs / aio-libs/aiobotocore
Reduce pyright baseline: 173 errors, most intentional-pattern noise but some look like real bugs
- 主要語言
- Python
- 星號
- 1.4k
- 分支
- 209
- 平均合併
- 4 天 15 小時
- 30 天內合併 PR
- 16
描述
## Summary
`uv run --with pyright pyright aiobotocore/` currently reports **173 errors**. Our workflow prompts (and the new [`/aiobotocore-bot:pyright-delta`](plugins/aiobotocore-bot/commands/pyright-delta.md) command) acknowledge this as a long-standing baseline and only gate on *delta* error counts in PR-touched files. That's a pragmatic workaround, but:
- It assumes a contributor can eyeball whether a new error is real or baseline — brittle.
- Real bugs can hide in the noise (see suspicious categories below).
- The baseline grows unchecked; every new override adds another incompatible-method-override error.
## Current breakdown
| Count | Category | Likely disposition |
|-:|-|-|
| 101 | `reportIncompatibleMethodOverride` | **Intentional**. Async methods overriding sync base methods. Fix: `@typing.override` + targeted `# type: ignore[override]`, or a pyrightconfig entry excluding this rule for specific subclasses. |
| 16 | `reportOptionalMemberAccess` | Mix. Some are "we know this isn't None because of earlier guard" (real), some could be latent bugs. Needs per-site review. |
| 14 | `reportAttributeAccessIssue` | Mix. Some are accessing attributes pyright can't see on dynamic botocore classes; others may be typos. |
| 9 | `reportArgumentType` | Mostly likely real — argument-type mismatches often indicate bugs. |
| 6 | `reportIndexIssue` | Optional subscripting without check. |
| 5 | `reportGeneralTypeIssues` | `CachedProperty` — missing type stub; probably a pyright limitation not a real bug. |
| 4 | `reportMissingImports` | `httpx` — optional dependency; already conditional at runtime, need `# type: ignore[import-untyped]` or configure pyright to ignore. |
| 3 | `reportPossiblyUnboundVariable` | **`waiter.py:127,139` — real bugs.** `acceptor` is referenced outside the loop that binds it. |
| 3 | `reportOptionalSubscript` | Optional subscripting — real or missing guards. |
| 3 | `reportOptionalCall` | Calling Optional — real or missing guards. |
| 3 | `reportCallIssue` | Call-signature mismatches. |
| 2 | `reportPrivateImportUsage` | **Intentional** — we import private symbols from botocore to override them. `# type: ignore[attr-defined]` at the import sites. |
| 2 | `reportIncompatibleVariableOverride` | Same class as the 101 overrides above, but for class variables. |
| 1 | `reportInvalidTypeForm` | Single-instance; needs inspection. |
| 1 | `reportAssignmentType` | Single-instance; needs inspection. |
## Proposed phased cleanup
1. **Silence the known-intentional noise** (101 + 2 + 2 + 4 = ~109 errors). Either use `typing.override` on subclasses + targeted `# type: ignore[override]` where signatures genuinely differ, or configure `pyrightconfig.json` to exclude the rule for specific classes/paths. Net: baseline drops to ~64.
2. **Fix the obvious real bugs** — `waiter.py:127,139` unbound `acceptor`; the `reportArgumentType`, `reportIndexIssue`, `reportOptionalCall` categories.
3. **Investigate the rest** — categorize as real bug, missing guard, or pyright limitation. Add `# type: ignore[reason]` only where pyright is demonstrably wrong.
4. **Enforce via pre-commit** — once the baseline is at zero (or a tightly-bounded set of explicitly-ignored cases), add a `pyright` hook to `.pre-commit-config.yaml` so errors are caught at commit time, not at review time. This is the natural end state: pyright sits alongside ruff and yamllint as a local gate, and CI re-runs the same hook for belt-and-suspenders. The `/aiobotocore-bot:pyright-delta` command becomes obsolete for the sync-bot flow (absolute pyright is the gate) and is retained only for ad-hoc delta inspection.
Note: pre-commit runs per-changed-file by default. Pyright's type-checking isn't sound when run on a subset of files (cross-module type inference breaks), so the hook should run on the whole `aiobotocore/` tree regardless of which files changed — `pass_filenames: false` + `always_run: true`. This is how mypy/pyright hooks are usually configured.
5. **Remove `/aiobotocore-bot:pyright-delta`** — once step 4 lands, the command has no callers. Delete `plugins/aiobotocore-bot/commands/pyright-delta.md` and update `.github/botocore-sync-prompt.md` Step 6 to run absolute pyright via pre-commit (or directly) instead of the delta command. Also drop the pyright-delta row from `docs/ai-workflows.md` and `plugins/aiobotocore-bot/README.md`.
## Why now
The new AI workflow plumbing (#1563) explicitly documents the baseline as a known limitation. Every reference to "long-standing baseline" in `plugins/aiobotocore-bot/commands/pyright-delta.md` is a marker that we've moved the problem rather than solving it. A focused cleanup PR per category would be tractable — none of the 14 categories is individually huge.
## References
- `plugins/aiobotocore-bot/commands/pyright-delta.md` — current delta-only approach
- `.github/botocore-sync-prompt.md` Step 6 — sync bot runs pyright-delta, not absolute pyright
- `CLAUDE.md` §"How aiobotocore overrides botocore" — async-overriding-sync is the intentional pattern driving the override-error count
## Reproduce
```bash
uv run --with pyright pyright aiobotocore/ 2>&1 | tail -1
# 173 errors, 0 warnings, 0 informations
```
Category counts:
```bash
uv run --with pyright pyright aiobotocore/ 2>&1 \
| grep -oE '\(report[A-Za-z]+\)' | sort | uniq -c | sort -rn
```
貢獻指南
評估
這個 Issue 還沒有評估資料。