diff --git a/README.md b/README.md index 5399cb5..8ccd0e9 100644 --- a/README.md +++ b/README.md @@ -90,12 +90,20 @@ decorators are extracted from the ast. -U -r requirements.txt`. * Start developing. * To run all tests with [tox](https://tox.readthedocs.io/en/latest/), - Python 3.6, 3.7 and 3.8 must be available. You might want to look + Python 3.7, 3.8, 3.9 and 3.10 must be available. You might want to look into using [pyenv](https://github.com/pyenv/pyenv). # Changelog +## v0.0.9 + +* Disable soft error limit (#21) + +## v0.0.8 + +* Normalize messages to enable support for mypy 0.902 and pytest 6.2.4 (#20) + ## v0.0.7 * Fix `PYTEST_VERSION_INFO` - by [@blueyed](https://github.com/blueyed) (#8) diff --git a/pyproject.toml b/pyproject.toml index 5d53705..763605f 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -18,9 +18,10 @@ classifiers = [ "Operating System :: Microsoft :: Windows", "Operating System :: OS Independent", "Operating System :: POSIX", - "Programming Language :: Python :: 3.6", "Programming Language :: Python :: 3.7", "Programming Language :: Python :: 3.8", + "Programming Language :: Python :: 3.9", + "Programming Language :: Python :: 3.10", "Typing :: Typed", ] description-file = "README.md" @@ -28,10 +29,10 @@ dist-name = "pytest-mypy-testing" home-page = "https://github.com/davidfritzsche/pytest-mypy-testing" license = "Apache-2.0 OR MIT" requires = [ - "pytest", + "pytest<8", "mypy", ] -requires-python = ">=3.6" +requires-python = ">=3.7" [tool.flit.entrypoints.pytest11] mypy-testing = "pytest_mypy_testing.plugin" diff --git a/src/pytest_mypy_testing/plugin.py b/src/pytest_mypy_testing/plugin.py index 2176b96..fdd91c2 100644 --- a/src/pytest_mypy_testing/plugin.py +++ b/src/pytest_mypy_testing/plugin.py @@ -43,10 +43,11 @@ def __init__( *, mypy_item: MypyTestItem, config: Optional[Config] = None, + **kwargs, ) -> None: if config is None: config = parent.config - super().__init__(name, parent=parent, config=config) + super().__init__(name, parent=parent, config=config, **kwargs) self.add_marker("mypy") self.mypy_item = mypy_item for mark in self.mypy_item.marks: @@ -103,22 +104,37 @@ def repr_failure(self, excinfo, style=None): class PytestMypyFile(pytest.File): def __init__( - self, fspath: LocalPath, parent=None, config=None, session=None, nodeid=None + self, + *, + parent=None, + config=None, + session=None, + nodeid=None, + **kwargs, ) -> None: if config is None: config = getattr(parent, "config", None) - super().__init__(fspath, parent, config, session, nodeid) + super().__init__( + parent=parent, + config=config, + session=session, + nodeid=nodeid, + **kwargs, + ) self.add_marker("mypy") - self.mypy_file = parse_file(self.fspath, config=config) + 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_result: Optional[MypyResult] = None @classmethod - def from_parent(cls, parent, fspath): + def from_parent(cls, parent, **kwargs): if PYTEST_VERSION_INFO < (5, 4): config = getattr(parent, "config", None) - return cls(parent=parent, config=config, fspath=fspath) + return cls(parent=parent, config=config, **kwargs) else: - return super().from_parent(parent=parent, fspath=fspath) + return super().from_parent(parent=parent, **kwargs) def collect(self) -> Iterator[PytestMypyTestItem]: for item in self.mypy_file.items: @@ -195,12 +211,23 @@ def _run_mypy(self, filename: str) -> MypyResult: ) -def pytest_collect_file(path: LocalPath, 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 +if PYTEST_VERSION_INFO < (7,): + + def pytest_collect_file(path: LocalPath, 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: LocalPath, 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 _is_pytest_test_file(path: LocalPath, parent): diff --git a/tests/test_plugin.py b/tests/test_plugin.py index 04ab0f2..9be6f36 100644 --- a/tests/test_plugin.py +++ b/tests/test_plugin.py @@ -1,6 +1,7 @@ # SPDX-FileCopyrightText: David Fritzsche # SPDX-License-Identifier: CC0-1.0 +import pathlib from types import SimpleNamespace from unittest.mock import Mock @@ -18,11 +19,22 @@ from pytest_mypy_testing.strutil import dedent +PYTEST_VERSION = pytest.__version__ +PYTEST_VERSION_INFO = tuple(int(part) for part in PYTEST_VERSION.split(".")[:3]) + + ERROR = Severity.ERROR NOTE = Severity.NOTE 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 test_create_mypy_assertion_error(): MypyAssertionError(None, []) @@ -34,6 +46,7 @@ def mk_dummy_parent(tmp_path, filename, content=""): config = Mock(spec=Config) config.rootdir = str(tmp_path) + config.rootpath = str(tmp_path) config.getini.return_value = ["test_*.py", "*_test.py"] session = SimpleNamespace( config=config, isinitpath=lambda p: True, _initialpaths=[] @@ -43,7 +56,7 @@ def mk_dummy_parent(tmp_path, filename, content=""): session=session, nodeid="dummy", fspath=LocalPath(path), - _path=path, + path=path, ) return parent @@ -52,8 +65,9 @@ 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) - - assert pytest_collect_file(parent.fspath, parent) is None + fspath = parent.fspath + actual = call_pytest_collect_file(fspath, parent) + assert actual is None @pytest.mark.parametrize("filename", ["test_z.py", "test_z.mypy-testing"]) @@ -68,10 +82,11 @@ def foo(): parent = mk_dummy_parent(tmp_path, filename, content) expected = MypyTestFile( - filename=str(parent._path), source_lines=content.splitlines() + filename=str(parent.path), source_lines=content.splitlines() ) - actual = pytest_collect_file(parent.fspath, parent) + fspath = parent.fspath + actual = call_pytest_collect_file(fspath, parent) assert isinstance(actual, PytestMypyFile) assert len(actual.mypy_file.items) == 1 diff --git a/tox.ini b/tox.ini index 50fc474..edd250c 100644 --- a/tox.ini +++ b/tox.ini @@ -3,9 +3,9 @@ [tox] isolated_build = True envlist = - {py37,py38,py39}-pytest{60,61,62}-mypy{0910,0921,0930} - {py310}-pytest{62}-mypy{0910,0921,0930} - py-pytest{60,61,62}-mypy{0921,0930} + {py37,py38,py39}-pytest{60,61,62,70}-mypy{0910,0921,0931} + {py310}-pytest{62,70}-mypy{0910,0921,0931} + py-pytest{60,61,62,70}-mypy{0921,0931} linting [testenv] @@ -17,16 +17,18 @@ deps = pytest60: pytest~=6.0.2 pytest61: pytest~=6.1.2 pytest62: pytest~=6.2.5 + pytest70: pytest~=7.0.1 pytest-cov pytest-html mypy0902: mypy==0.902 mypy0910: mypy==0.910 mypy0921: mypy==0.921 - mypy0930: mypy==0.930 + mypy0931: mypy==0.931 setenv = COVERAGE_FILE={toxinidir}/build/{envname}/coverage commands = coverage run --context "{envname}" -m pytest \ + {posargs} \ --html={toxinidir}/build/{envname}/pytest-report.html \ --junitxml={toxinidir}/build/{envname}/junit.xml