Search code examples
pythonmypy

Onboarding a new codebase to mypy - silencing errors one-by-one


I am currently converting an existing codebase to mypy.

There are ~500 type errors. I am not familiar with the code so fixing all of the errors would be time consuming.

I would like to:

  1. Run mypy
  2. For each error listed, edit the code and add a # type: ignore # Legacy types. Ignoring for now. See <ticket number>. If you edit this code, please fix the types.

What is the best way to do this?


Solution

  • Here's a DIY way script to silence mypy errors:

    import re
    import subprocess
    
    mypy_command = ["poetry", "run", "mypy", "."]
    ignore = " # type: ignore  # IF YOU EDIT THIS LINE, FIX THE TYPE. Do not add more type:ignores. SEE: PR#123"
    
    
    def do_it() -> None:
        out = subprocess.run(
            mypy_command,
            capture_output=True,
            text=True,
        ).stdout
        for line in out.split("\n"):
            if is_last_line(line):
                print("Processed all lines")
                break
            handle_line(line)
    
    
    def handle_line(line: str) -> None:
        items = line.split(":")
        file: str = items[0]
        line_num: int = int(items[1])
    
        print(f"Fixing: {file} --- {line_num}")
    
        fix_line(file, line_num)
    
    
    def fix_line(filename: str, line_num: int) -> None:
        line_num -= 1 # File lines are 1 indexed according to mypy but 0 indexed in an array
    
        with open(filename, 'r') as txt:
            text = txt.readlines()
    
        if "#" in text[line_num]:
            print("WARNING: This line already has a comment - manual intervention required.")
            return
    
        new_line = text[line_num][0:-1] + ignore + "\n"
    
        text[line_num] = new_line
    
        with open(filename, 'w') as txt:
            txt.writelines(text)
    
    
    def is_last_line(line: str) -> bool:
        last_line_pattern = "Found [0-9]* errors in [0-9]* files"
        return bool(re.match(last_line_pattern, line))
    
    
    do_it()
    

    There are several OSS packages for this job as well:

    There are other solutions - check "similar projects" at the end of the first README,