Skip to content

Prepare for removal of deprecated path argument to pytest_collect_file() #52

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 1 commit into from
Mar 4, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 5 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -140,6 +140,9 @@ decorators are extracted from the ast.

## unreleased

* Replace usage of deprecated path argument to pytest hook
``pytest_collect_file()`` with usage of the file_path argument
introduced in pytest 7 ([#51][i51], [#52][p52])

## v0.1.2 (2024-02-26)

Expand Down Expand Up @@ -218,6 +221,7 @@ decorators are extracted from the ast.
[i35]: https://github.com/davidfritzsche/pytest-mypy-testing/issues/35
[i36]: https://github.com/davidfritzsche/pytest-mypy-testing/issues/36
[i46]: https://github.com/davidfritzsche/pytest-mypy-testing/issues/46
[i51]: https://github.com/davidfritzsche/pytest-mypy-testing/issues/51

[p6]: https://github.com/davidfritzsche/pytest-mypy-testing/pull/6
[p7]: https://github.com/davidfritzsche/pytest-mypy-testing/pull/7
Expand All @@ -240,3 +244,4 @@ decorators are extracted from the ast.
[p48]: https://github.com/davidfritzsche/pytest-mypy-testing/pull/48
[p49]: https://github.com/davidfritzsche/pytest-mypy-testing/pull/49
[p50]: https://github.com/davidfritzsche/pytest-mypy-testing/pull/50
[p52]: https://github.com/davidfritzsche/pytest-mypy-testing/pull/52
59 changes: 18 additions & 41 deletions src/pytest_mypy_testing/plugin.py
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@
import pytest
from _pytest._code.code import ReprEntry, ReprFileLocation
from _pytest.config import Config
from _pytest.python import path_matches_patterns

from .message import Message, Severity
from .output_processing import OutputMismatch, diff_message_sequences
Expand Down Expand Up @@ -57,12 +58,7 @@ def __init__(

@classmethod
def from_parent(cls, parent, name, mypy_item):
if PYTEST_VERSION_INFO < (5, 4):
return cls(
parent=parent, name=name, config=parent.config, mypy_item=mypy_item
)
else:
return super().from_parent(parent=parent, name=name, mypy_item=mypy_item)
return super().from_parent(parent=parent, name=name, mypy_item=mypy_item)

def runtest(self) -> None:
returncode, actual_messages = self.parent.run_mypy(self.mypy_item)
Expand All @@ -75,14 +71,12 @@ def runtest(self) -> None:
raise MypyAssertionError(item=self, errors=errors)

def reportinfo(self) -> Tuple[Union["os.PathLike[str]", str], Optional[int], str]:
return self.parent.fspath, self.mypy_item.lineno, self.name
return self.parent.path, self.mypy_item.lineno, self.name

def repr_failure(self, excinfo, style=None):
if not excinfo.errisinstance(MypyAssertionError):
return super().repr_failure(excinfo, style=style) # pragma: no cover
reprfileloc_key = (
"filelocrepr" if PYTEST_VERSION_INFO < (5, 4) else "reprfileloc"
)
reprfileloc_key = "reprfileloc"
exception_repr = excinfo.getrepr(style="short")
exception_repr.reprcrash.message = ""
exception_repr.reprtraceback.reprentries = [
Expand All @@ -93,7 +87,7 @@ def repr_failure(self, excinfo, style=None):
reprfuncargs=None,
**{
reprfileloc_key: ReprFileLocation(
path=self.parent.fspath,
path=str(self.parent.path),
lineno=mismatch.lineno,
message=mismatch.error_message,
)
Expand Down Expand Up @@ -124,19 +118,12 @@ def __init__(
**kwargs,
)
self.add_marker("mypy")
if PYTEST_VERSION_INFO >= (7,):
self.mypy_file = parse_file(self.path, config=config)
else:
self.mypy_file = parse_file(self.fspath, config=config)
self.mypy_file = parse_file(self.path, config=config)
self._mypy_result: Optional[MypyResult] = None

@classmethod
def from_parent(cls, parent, **kwargs):
if PYTEST_VERSION_INFO < (5, 4):
config = getattr(parent, "config", None)
return cls(parent=parent, config=config, **kwargs)
else:
return super().from_parent(parent=parent, **kwargs)
return super().from_parent(parent=parent, **kwargs)

def collect(self) -> Iterator[PytestMypyTestItem]:
for item in self.mypy_file.items:
Expand All @@ -146,7 +133,7 @@ def collect(self) -> Iterator[PytestMypyTestItem]:

def run_mypy(self, item: MypyTestItem) -> Tuple[int, List[Message]]:
if self._mypy_result is None:
self._mypy_result = self._run_mypy(self.fspath)
self._mypy_result = self._run_mypy(self.path)
return (
self._mypy_result.returncode,
sorted(
Expand Down Expand Up @@ -211,31 +198,21 @@ def _run_mypy(self, filename: Union[pathlib.Path, os.PathLike, str]) -> MypyResu
)


if PYTEST_VERSION_INFO < (7,):

def pytest_collect_file(path, parent):
if path.ext == ".mypy-testing" or _is_pytest_test_file(path, parent):
file = PytestMypyFile.from_parent(parent=parent, fspath=path)
if file.mypy_file.items:
return file
return None

else:

def pytest_collect_file(file_path, path, parent): # type: ignore
if path.ext == ".mypy-testing" or _is_pytest_test_file(path, parent):
file = PytestMypyFile.from_parent(parent=parent, path=file_path)
if file.mypy_file.items:
return file
return None
def pytest_collect_file(file_path: pathlib.Path, parent):
if file_path.suffix == ".mypy-testing" or _is_pytest_test_file(file_path, parent):
file = PytestMypyFile.from_parent(parent=parent, path=file_path)
if file.mypy_file.items:
return file
return None


def _is_pytest_test_file(path, parent):
def _is_pytest_test_file(file_path: pathlib.Path, parent):
"""Return `True` if *path* is considered to be a pytest test file."""
# Based on _pytest/python.py::pytest_collect_file
fn_patterns = parent.config.getini("python_files") + ["__init__.py"]
return path.ext == ".py" and (
parent.session.isinitpath(path) or any(path.fnmatch(pat) for pat in fn_patterns)
return file_path.suffix == ".py" and (
parent.session.isinitpath(file_path)
or path_matches_patterns(file_path, fn_patterns)
)


Expand Down
24 changes: 7 additions & 17 deletions tests/test_plugin.py
Original file line number Diff line number Diff line change
Expand Up @@ -18,12 +18,6 @@
from pytest_mypy_testing.strutil import dedent


try:
from py._path.local import LocalPath
except ModuleNotFoundError:
from _pytest._py.path import LocalPath


PYTEST_VERSION = pytest.__version__
PYTEST_VERSION_INFO = tuple(int(part) for part in PYTEST_VERSION.split(".")[:3])

Expand All @@ -33,18 +27,15 @@
WARNING = Severity.WARNING


def call_pytest_collect_file(fspath, parent):
if PYTEST_VERSION_INFO < (7,):
return pytest_collect_file(fspath, parent)
else:
return pytest_collect_file(pathlib.Path(str(fspath)), fspath, parent) # type: ignore
def call_pytest_collect_file(file_path: pathlib.Path, parent):
return pytest_collect_file(file_path, parent)


def test_create_mypy_assertion_error():
MypyAssertionError(None, [])


def mk_dummy_parent(tmp_path, filename, content=""):
def mk_dummy_parent(tmp_path: pathlib.Path, filename, content=""):
path = tmp_path / filename
path.write_text(content)

Expand All @@ -59,7 +50,6 @@ def mk_dummy_parent(tmp_path, filename, content=""):
config=config,
session=session,
nodeid="dummy",
fspath=LocalPath(path),
path=path,
)

Expand All @@ -69,8 +59,8 @@ def mk_dummy_parent(tmp_path, filename, content=""):
@pytest.mark.parametrize("filename", ["z.py", "test_z.mypy-testing"])
def test_pytest_collect_file_not_test_file_name(tmp_path, filename: str):
parent = mk_dummy_parent(tmp_path, filename)
fspath = parent.fspath
actual = call_pytest_collect_file(fspath, parent)
file_path = parent.path
actual = call_pytest_collect_file(file_path, parent)
assert actual is None


Expand All @@ -89,8 +79,8 @@ def foo():
filename=str(parent.path), source_lines=content.splitlines()
)

fspath = parent.fspath
actual = call_pytest_collect_file(fspath, parent)
file_path = parent.path
actual = call_pytest_collect_file(file_path, parent)
assert isinstance(actual, PytestMypyFile)

assert len(actual.mypy_file.items) == 1
Expand Down