Skip to content

← Interfaces with Protocols and ABCs step 19 of 26

Easy Framework

Clean Up type: ignore Comments

A # type: ignore comment tells mypy to hide the errors on its line. A bare one hides every error there, including errors that later changes add. A coded one, such as # type: ignore[import-untyped], hides only errors with that code.

You are cleaning up a file. You deleted every ignore comment, ran mypy, and wrote down the error codes it reported on each line. Now work out the new comment for each line.

What to write

Fill in plan, is_bare and solve.

plan(codes) takes the codes reported on one line and returns its new comment:

Codes on the line New comment
No codes ""
All of them are in SUPPRESSIBLE "# type: ignore[a, b]"
At least one is not in SUPPRESSIBLE "# FIX: a, b"

In both comments, list each code once, sorted, and joined by ", ". A FIX comment lists every code on the line, including any that are in SUPPRESSIBLE.

SUPPRESSIBLE holds the codes this project allows you to hide: import-untyped, import-not-found, no-any-unimported and override. Any other code is a problem to fix.

is_bare(comment) returns True when the comment starts with "# type: ignore" but not with "# type: ignore[". Compare the string as it is, without stripping spaces.

solve(current, reported) gets two lists of the same length. current[i] is line i's old comment, or "" if it had none. reported[i] lists the codes mypy reported on line i, and a code can appear more than once. Leave both lists unchanged, and return a dictionary with these keys:

Key Value
"lines" The new comment for each line, in order
"suppressions" How many new comments are ignores
"fixes" How many new comments are FIX comments
"removed" How many lines had an old comment and now have ""
"bare" How many old comments are bare, by is_bare

A line whose old ignore becomes a FIX comment does not count as removed. Empty input lists give an empty "lines" list and zero for every count.

Example

current = ["# type: ignore", "", "# type: ignore[override]"]
reported = [[], ["import-untyped", "import-untyped"], ["override", "arg-type"]]

solve(current, reported) returns:

{
    "lines": ["", "# type: ignore[import-untyped]", "# FIX: arg-type, override"],
    "suppressions": 1,
    "fixes": 1,
    "removed": 1,
    "bare": 1,
}

The first line has no errors left, so its ignore goes. The repeated code on the second line appears once. The third line has arg-type, which is not in SUPPRESSIBLE, so it needs a fix.

Going further

In strict mode, mypy reports an ignore that no longer hides any error, as Unused "type: ignore" comment. To make it reject bare ignores too, add --enable-error-code ignore-without-code.