pytest-mypy icon indicating copy to clipboard operation
pytest-mypy copied to clipboard

Add mypy excludes for collect_ignore entries

Open jaraco opened this issue 2 years ago • 4 comments

The jaraco.site project has a file in the tree that's ignored for tests.

However, even with that configuration, the file gets collected and is run by mypy and causes tests to fail:

__________________________________________________________________ test session ___________________________________________________________________
mypy exited with status 1.
...
====================================================================== mypy =======================================================================
jaraco/site/projecthoneypot/croakysteel.py:528: error: "Callable[[Any, Any, Any, Any], Any]" has no attribute "getSettings"  [attr-defined]
jaraco/site/projecthoneypot/croakysteel.py:529: error: "Callable[[Any, Any, Any, Any], Any]" has no attribute "makeHTML"  [attr-defined]
jaraco/site/projecthoneypot/croakysteel.py:533: error: "Callable[[Any, Any, Any, Any], Any]" not callable  [operator]
Found 3 errors in 1 file (checked 11 source files)
============================================================= short test summary info =============================================================
FAILED conftest.py::mypy-status
============================================== 1 failed, 25 passed, 10 skipped, 3 warnings in 5.09s ===============================================
py: exit 1 (5.43 seconds) /Users/jaraco/code/jaraco/jaraco.site> pytest pid=33733

Is there a way that pytest-mypy can honor collect_ignore?

jaraco avatar Aug 06 '23 01:08 jaraco

I think mypy is following this import.

dmtucker avatar Aug 06 '23 16:08 dmtucker

Oh, right. I hadn't considered that the checking has to be done holistically. Yeah, that makes sense. I did find that I could suppress the errors by configuring the project to ignore types for that module.

I guess it's conceivable that pytest-mypy could translate the collect_ignore setting into mypy excludes, but that's definitely more of a feature request.

jaraco avatar Aug 07 '23 05:08 jaraco

I've found another project affected by this issue: keyrings.alt. This project has a module _win_crypto.py that imports ctypes and accesses attributes of ctypes that are only available on Windows. Thus when checking mypy, it fails its type checks. The module is excluded from tests, but that's insufficient to prevent mypy from failing, even when run under pytest:

keyrings/alt/_win_crypto.py:13: error: Module "ctypes" has no attribute "windll"  [attr-defined]
keyrings/alt/_win_crypto.py:13: error: Module "ctypes" has no attribute "WinDLL"  [attr-defined]
keyrings/alt/_win_crypto.py:13: error: Module "ctypes" has no attribute "WINFUNCTYPE"; maybe "PYFUNCTYPE"?  [attr-defined]
Found 3 errors in 1 file (checked 21 source files)

jaraco avatar Apr 02 '24 00:04 jaraco

Ya, also likely because of this import...

It's actually interesting to see that collect_ignore is generally respected:

$ tree
.
├── Pipfile
├── Pipfile.lock
└── pkg
    ├── alt
    │   ├── bad.py
    │   └── __init__.py
    └── __init__.py

2 directories, 5 files
$ pipenv run pytest --mypy
====================== test session starts =======================
platform linux -- Python 3.8.18, pytest-8.3.2, pluggy-1.5.0
rootdir: /tmp/tmp.JDvY0VQIdT
plugins: mypy-0.10.3
collected 4 items                                                

pkg/__init__.py .F                                         [ 50%]
pkg/alt/__init__.py .                                      [ 75%]
pkg/alt/bad.py F                                           [100%]

============================ FAILURES ============================
__________________________ test session __________________________
mypy exited with status 1.
_________________________ pkg/alt/bad.py _________________________
1: error: Incompatible types in assignment (expression has type "str", variable has type "int")  [assignment]
============================== mypy ==============================
Found 1 error in 1 file (checked 3 source files)
==================== short test summary info =====================
FAILED pkg/__init__.py::mypy-status
FAILED pkg/alt/bad.py::mypy
================== 2 failed, 2 passed in 1.16s ===================
$ echo 'collect_ignore = ["pkg/alt/bad.py"]' > conftest.py
$ pipenv run pytest --mypy
====================== test session starts =======================
platform linux -- Python 3.8.18, pytest-8.3.2, pluggy-1.5.0
rootdir: /tmp/tmp.JDvY0VQIdT
plugins: mypy-0.10.3
collected 4 items                                                

conftest.py ..                                             [ 50%]
pkg/__init__.py .                                          [ 75%]
pkg/alt/__init__.py .                                      [100%]
============================== mypy ==============================

Success: no issues found in 3 source files
======================= 4 passed in 0.29s ========================

That is because the plugin only creates MypyFiles (and subsequently MypyItems) for files presented by the pytest_collect_file hook. It then runs mypy on the file of any collected Item.

dmtucker avatar Aug 10 '24 21:08 dmtucker