diff --git a/src/pytest_mypy.py b/src/pytest_mypy.py index 9714cab..7c2ca8d 100644 --- a/src/pytest_mypy.py +++ b/src/pytest_mypy.py @@ -75,11 +75,15 @@ def pytest_configure_node(self, node): # xdist hook def pytest_collect_file(path, parent): """Create a MypyFileItem for every file mypy should run on.""" - if path.ext == '.py' and any([ + if path.ext in {'.py', '.pyi'} and any([ parent.config.option.mypy, parent.config.option.mypy_ignore_missing_imports, ]): - return MypyFile.from_parent(parent=parent, fspath=path) + # Do not create MypyFile instance for a .py file if a + # .pyi file with the same name already exists; + # pytest will complain about duplicate modules otherwise + if path.ext == '.pyi' or not path.new(ext='.pyi').isfile(): + return MypyFile.from_parent(parent=parent, fspath=path) return None diff --git a/tests/test_pytest_mypy.py b/tests/test_pytest_mypy.py index 789405d..d00e824 100644 --- a/tests/test_pytest_mypy.py +++ b/tests/test_pytest_mypy.py @@ -36,6 +36,36 @@ def pyfunc(x: int) -> int: assert result.ret == 0 +def test_mypy_pyi(testdir, xdist_args): + """ + Verify that a .py file will be skipped if + a .pyi file exists with the same filename. + """ + # The incorrect signature below should be ignored + # as the .pyi file takes priority + testdir.makefile( + '.py', pyfile=''' + def pyfunc(x: int) -> str: + return x * 2 + ''' + ) + + testdir.makefile( + '.pyi', pyfile=''' + def pyfunc(x: int) -> int: ... + ''' + ) + + result = testdir.runpytest_subprocess(*xdist_args) + result.assert_outcomes() + result = testdir.runpytest_subprocess('--mypy', *xdist_args) + mypy_file_checks = 1 + mypy_status_check = 1 + mypy_checks = mypy_file_checks + mypy_status_check + result.assert_outcomes(passed=mypy_checks) + assert result.ret == 0 + + def test_mypy_error(testdir, xdist_args): """Verify that running on a module with type errors fails.""" testdir.makepyfile('''