aio-libs / aio-libs/aiobotocore

Reduce pyright baseline: 173 errors, most intentional-pattern noise but some look like real bugs

未關閉
#1,564 2 則留言 0 個 reaction 已指派 0 人 在 GitHub 檢視
enhancement
主要語言
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 還沒有評估資料。

把新 issue 寄到你的電子郵件信箱

精選適合新手參與的 GitHub issue 摘要。