We can't find the internet
Attempting to reconnect
Something went wrong!
Attempting to reconnect
← Structural Typing and the Hard Parts step 21 of 24
Suppression hygiene: planning the minimum set of type: ignore
Ignore comments are how a strictly-typed codebase decays. A bare
# type: ignore on an import line swallows the import-untyped it was
written for and the genuine attr-defined that appears three refactors
later. Nobody notices, because the line already had a comment on it.
The scope ladder — never go higher than necessary
-
line-level coded ignore:
# type: ignore[import-untyped] -
file-level
# mypy: disable-error-code="..." -
per-module override in
pyproject.toml - global config
Two flags make the ladder enforceable. --enable-error-code ignore-without-code rejects a bare ignore. --warn-unused-ignores (already
part of --strict) retires the graveyard: an ignore whose diagnostic no
longer fires becomes an error itself.
Pyright diverges here in a way worth knowing. It uses
# pyright: ignore[rule], and its reportUnnecessaryTypeIgnoreComment is
none even in strict mode. Stale suppressions rot silently there; if
pyright is your only checker, nothing expires them.
Your task
You are handed a module’s suppression state as data — because deciding what to do with an ignore requires knowing what mypy says with the ignore removed, which is a fact about a checker run, not about the source.
def solve(current: list[str], reported: list[list[str]]) -> dict[str, object]:
-
current[i]— the trailing comment on lineitoday (""if none) -
reported[i]— the error codes mypy emits on lineiwith all suppressions removed
Produce lines[i], the minimal correct replacement:
-
no reported codes →
"". The ignore is unnecessary;--warn-unused-ignoreswould flag it, so delete it. -
every reported code is in
SUPPRESSIBLE→"# type: ignore[a, b]", codes de-duplicated, sorted, joined with", ". -
otherwise →
"# FIX: a, b"over all the reported codes, sorted. This line does not get suppressed; it gets fixed.
SUPPRESSIBLE is given: import-untyped, import-not-found,
no-any-unimported, override. The principle behind the list is the one
that matters — a suppression is defensible only when the cause is outside
the module. A dependency ships no annotations; a third-party base class
has a signature you cannot change. An attr-defined or an arg-type is
your own code being wrong, and suppressing it converts a compile-time error
into a production one.
Also return:
| key | value |
|---|---|
"suppressions" |
how many lines end up with a # type: ignore[...] |
"fixes" |
how many lines need a human |
"removed" |
lines that had a comment and now have none |
"bare" |
how many of current are bare ignores (no [...]) |
The number that matters
"bare" is the audit metric. Once every suppression is coded,
grep -c 'type: ignore\[' | sort by error code tells you where the type
debt actually is — and --warn-unused-ignores starts expiring the dead ones
for you.
Loading visualization…
Stuck?
Python reference solution
Sign in to attempt this problem and reveal the reference solution.