Search code examples
pythonmypypre-commitpre-commit.com

pre-commit: Mypy local hook reports the same error multiple times


Problem

Mypy as a local hook reports the same error multiple times.

related issues

Difference between running Mypy directly VS with pre-commit run --all-files

.pre-commit-config.yaml

  - repo: local
    hooks:
      - id: mypy
        name: mypy
        # or `entry: poetry run mypy`, but perhaps both are the same
        entry: mypy
        # From the docs it is not clear the difference between `language: python` VS `language: system`
        language: system
        types: [ python ]

sample file

Let's make some silly mistake only to trigger Mypy warnings, e.g.:

# sample.py 

foo: int = "bar"

Note: there are many other files in the project.

pre-commit run --all-files output

The same mistake reported 3 times:

pre-commit run mypy --all-files
mypy.....................................................................Failed
- hook id: mypy
- exit code: 1

src/sample.py:12:12: error: Incompatible types in assignment (expression
has type "str", variable has type "int")  [assignment]
    foo: int = "bar"
               ^
Found 1 error in 1 file (checked 23 source files)
src/sample.py:12:12: error: Incompatible types in assignment (expression
has type "str", variable has type "int")  [assignment]
    foo: int = "bar"
               ^
Found 1 error in 1 file (checked 23 source files)
src/sample.py:12:12: error: Incompatible types in assignment (expression
has type "str", variable has type "int")  [assignment]
    foo: int = "bar"
               ^
Found 1 error in 1 file (checked 23 source files)
src/sample.py:12:12: error: Incompatible types in assignment (expression
has type "str", variable has type "int")  [assignment]
    foo: int = "bar"
               ^
Found 1 error in 1 file (checked 22 source files)

mypy src/ output

The mistake is reported only once, which is a correct behavior:

src/cache/cache.py:12:12: error: Incompatible types in assignment (expression has type "str", variable has type "int")  [assignment]
    foo: int = "bar"
               ^
Found 1 error in 1 file (checked 91 source files)

git ls-files --exclude='*.py' --ignored -c -z | xargs -0r mypy output (try to reproduce "pre-commit" behaviour):

  • the same as above (the warning reported only once)

Question

How to avoid duplicate warnings and still use Mypy via "pre-commit"?

PS:

Do not propose me to use https://github.com/pre-commit/mirrors-mypy. It is overkill for my huge project to copy/paste manually dozens of my dependencies to the additional_dependencies to create one more virtual environment. These dependencies will be unpinned, and I will need to update them manually every time I add/remove something. It is only a redundant duplicate work. Anyway, I used to use "mirrors-mypy" before, and it stopped to give consistent results with the plain Mypy. This is why I am trying to use Mypy as a local hook. Currently, I simply run plain Mypy in my CI/CD as one job, and the "pre-commit" with all other hooks as a separate job.


Solution

  • It looks like you can use

    require_serial: true
    

    in your .pre-commit-config.yaml file for the hooks: section, like this:

    - repo: local
      hooks:
        - id: mypy
          name: mypy
          # or `entry: poetry run mypy`, but perhaps both are the same
          entry: mypy
          require_serial: true
          # From the docs it is not clear the difference between `language: python` VS `language: system`
          language: system
          types: [ python ]
    

    That will pass all the necessary files to the mypy in one piece, without splitting the file list into several processes.

    Yes, this can cause a longer check, but the output will be clean.