From 31de42ffa5dbbf9e0c37eb64cd01080381940594 Mon Sep 17 00:00:00 2001 From: Ran Benita Date: Thu, 4 Apr 2024 19:52:09 +0300 Subject: [PATCH] Bump min pytest to 7.0.0 Refs #1057 --- .pre-commit-config.yaml | 2 +- changelog/1057.removal | 1 + pyproject.toml | 2 +- src/xdist/dsession.py | 4 +--- src/xdist/looponfail.py | 2 +- src/xdist/plugin.py | 8 +++----- src/xdist/remote.py | 7 +------ src/xdist/scheduler/load.py | 9 ++++++--- src/xdist/scheduler/loadscope.py | 9 +++++++-- src/xdist/scheduler/worksteal.py | 9 ++++++--- src/xdist/workermanage.py | 4 +--- testing/acceptance_test.py | 5 +---- testing/test_looponfail.py | 28 ++++++++-------------------- testing/test_remote.py | 4 +--- tox.ini | 2 +- 15 files changed, 40 insertions(+), 56 deletions(-) create mode 100644 changelog/1057.removal diff --git a/.pre-commit-config.yaml b/.pre-commit-config.yaml index 70d69c8c..7b6c5e36 100644 --- a/.pre-commit-config.yaml +++ b/.pre-commit-config.yaml @@ -29,5 +29,5 @@ repos: files: ^(src/|testing/) args: [] additional_dependencies: - - pytest>=6.2.0 + - pytest>=7.0.0 - py>=1.10.0 diff --git a/changelog/1057.removal b/changelog/1057.removal new file mode 100644 index 00000000..fbd9c5d6 --- /dev/null +++ b/changelog/1057.removal @@ -0,0 +1 @@ +pytest>=7.0.0 is now required. diff --git a/pyproject.toml b/pyproject.toml index 651e8995..144df633 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -34,7 +34,7 @@ classifiers = [ requires-python = ">=3.8" dependencies = [ "execnet>=1.1", - "pytest>=6.2.0", + "pytest>=7.0.0", ] dynamic = ["version"] diff --git a/src/xdist/dsession.py b/src/xdist/dsession.py index ebba5e23..56b332f1 100644 --- a/src/xdist/dsession.py +++ b/src/xdist/dsession.py @@ -206,9 +206,7 @@ def worker_internal_error(self, node, formatted_error): try: assert False, formatted_error except AssertionError: - from _pytest._code import ExceptionInfo - - excinfo = ExceptionInfo.from_current() + excinfo = pytest.ExceptionInfo.from_current() excrepr = excinfo.getrepr() self.config.hook.pytest_internalerror(excrepr=excrepr, excinfo=excinfo) diff --git a/src/xdist/looponfail.py b/src/xdist/looponfail.py index b67bbe65..05b38f01 100644 --- a/src/xdist/looponfail.py +++ b/src/xdist/looponfail.py @@ -168,7 +168,7 @@ def init_worker_session(channel, args, option_dict): sys.path[:] = newpaths # fullwidth, hasmarkup = channel.receive() - from _pytest.config import Config + from pytest import Config config = Config.fromdictargs(option_dict, list(args)) config.args = args diff --git a/src/xdist/plugin.py b/src/xdist/plugin.py index c9d4c49c..14d081f7 100644 --- a/src/xdist/plugin.py +++ b/src/xdist/plugin.py @@ -6,8 +6,6 @@ import pytest -PYTEST_GTE_7 = hasattr(pytest, "version_tuple") and pytest.version_tuple >= (7, 0) # type: ignore[attr-defined] - _sys_path = list(sys.path) # freeze a copy of sys.path at interpreter startup @@ -188,16 +186,16 @@ def pytest_addoption(parser): parser.addini( "rsyncdirs", "list of (relative) paths to be rsynced for remote distributed testing.", - type="paths" if PYTEST_GTE_7 else "pathlist", + type="paths", ) parser.addini( "rsyncignore", "list of (relative) glob-style paths to be ignored for rsyncing.", - type="paths" if PYTEST_GTE_7 else "pathlist", + type="paths", ) parser.addini( "looponfailroots", - type="paths" if PYTEST_GTE_7 else "pathlist", + type="paths", help="directories to check for changes. Default: current directory.", ) diff --git a/src/xdist/remote.py b/src/xdist/remote.py index ba18da8b..fc3a3ff4 100644 --- a/src/xdist/remote.py +++ b/src/xdist/remote.py @@ -201,14 +201,9 @@ def pytest_collection_modifyitems(self, session, config, items): @pytest.hookimpl def pytest_collection_finish(self, session): - try: - topdir = str(self.config.rootpath) - except AttributeError: # pytest <= 6.1.0 - topdir = str(self.config.rootdir) - self.sendevent( "collectionfinish", - topdir=topdir, + topdir=str(self.config.rootpath), ids=[item.nodeid for item in session.items], ) diff --git a/src/xdist/scheduler/load.py b/src/xdist/scheduler/load.py index 422528c3..bf1316b0 100644 --- a/src/xdist/scheduler/load.py +++ b/src/xdist/scheduler/load.py @@ -1,6 +1,6 @@ from itertools import cycle -from _pytest.runner import CollectReport +import pytest from xdist.remote import Producer from xdist.report import report_collection_diff @@ -307,8 +307,11 @@ def _check_nodes_have_same_collection(self): same_collection = False self.log(msg) if self.config is not None: - rep = CollectReport( - node.gateway.id, "failed", longrepr=msg, result=[] + rep = pytest.CollectReport( + nodeid=node.gateway.id, + outcome="failed", + longrepr=msg, + result=[], ) self.config.hook.pytest_collectreport(report=rep) diff --git a/src/xdist/scheduler/loadscope.py b/src/xdist/scheduler/loadscope.py index fb4bc634..e8addbb9 100644 --- a/src/xdist/scheduler/loadscope.py +++ b/src/xdist/scheduler/loadscope.py @@ -1,6 +1,6 @@ from collections import OrderedDict -from _pytest.runner import CollectReport +import pytest from xdist.remote import Producer from xdist.report import report_collection_diff @@ -410,7 +410,12 @@ def _check_nodes_have_same_collection(self): if self.config is None: continue - rep = CollectReport(node.gateway.id, "failed", longrepr=msg, result=[]) + rep = pytest.CollectReport( + nodeid=node.gateway.id, + outcome="failed", + longrepr=msg, + result=[], + ) self.config.hook.pytest_collectreport(report=rep) return same_collection diff --git a/src/xdist/scheduler/worksteal.py b/src/xdist/scheduler/worksteal.py index 4a2c2fef..5253c1a4 100644 --- a/src/xdist/scheduler/worksteal.py +++ b/src/xdist/scheduler/worksteal.py @@ -3,7 +3,7 @@ from typing import Any from typing import NamedTuple -from _pytest.runner import CollectReport +import pytest from xdist.remote import Producer from xdist.report import report_collection_diff @@ -323,8 +323,11 @@ def _check_nodes_have_same_collection(self): same_collection = False self.log(msg) if self.config is not None: - rep = CollectReport( - node.gateway.id, "failed", longrepr=msg, result=[] + rep = pytest.CollectReport( + nodeid=node.gateway.id, + outcome="failed", + longrepr=msg, + result=[], ) self.config.hook.pytest_collectreport(report=rep) diff --git a/src/xdist/workermanage.py b/src/xdist/workermanage.py index d1cef01c..d183dc99 100644 --- a/src/xdist/workermanage.py +++ b/src/xdist/workermanage.py @@ -401,9 +401,7 @@ def process_from_remote(self, eventcall): # should not land in receiver-thread raise except BaseException: - from _pytest._code import ExceptionInfo - - excinfo = ExceptionInfo.from_current() + excinfo = pytest.ExceptionInfo.from_current() print("!" * 20, excinfo) self.config.notify_exception(excinfo) self.shutdown() diff --git a/testing/acceptance_test.py b/testing/acceptance_test.py index 97797773..e63443a8 100644 --- a/testing/acceptance_test.py +++ b/testing/acceptance_test.py @@ -1112,14 +1112,11 @@ def test_error_report_styles(): result.assert_outcomes(failed=1) -def test_color_yes_collection_on_non_atty(pytester, request) -> None: +def test_color_yes_collection_on_non_atty(pytester) -> None: """Skip collect progress report when working on non-terminals. Similar to pytest-dev/pytest#1397 """ - tr = request.config.pluginmanager.getplugin("terminalreporter") - if not hasattr(tr, "isatty"): - pytest.skip("only valid for newer pytest versions") pytester.makepyfile( """ import pytest diff --git a/testing/test_looponfail.py b/testing/test_looponfail.py index 2879e4d9..348aa3e8 100644 --- a/testing/test_looponfail.py +++ b/testing/test_looponfail.py @@ -12,9 +12,6 @@ from xdist.looponfail import StatRecorder -PYTEST_GTE_7 = hasattr(pytest, "version_tuple") and pytest.version_tuple >= (7, 0) # type: ignore[attr-defined] - - class TestStatRecorder: def test_filechange(self, tmp_path: Path) -> None: tmp = tmp_path @@ -128,9 +125,8 @@ def test_failures_somewhere(self, pytester: pytest.Pytester) -> None: failures = control.runsession() assert failures control.setup() - item_path = item.path if PYTEST_GTE_7 else Path(str(item.fspath)) # type: ignore[attr-defined] - item_path.write_text("def test_func():\n assert 1\n") - removepyc(item_path) + item.path.write_text("def test_func():\n assert 1\n") + removepyc(item.path) topdir, failures = control.runsession()[:2] assert not failures @@ -146,10 +142,7 @@ def test_func(): control = RemoteControl(modcol.config) control.loop_once() assert control.failures - if PYTEST_GTE_7: - modcol_path = modcol.path # type:ignore[attr-defined] - else: - modcol_path = Path(str(modcol.fspath)) + modcol_path = modcol.path # type:ignore[attr-defined] modcol_path.write_text( textwrap.dedent( @@ -179,10 +172,7 @@ def test_func(): """ ) ) - if PYTEST_GTE_7: - parent = modcol.path.parent.parent # type: ignore[attr-defined] - else: - parent = Path(modcol.fspath.dirpath().dirpath()) + parent = modcol.path.parent.parent # type: ignore[attr-defined] monkeypatch.chdir(parent) modcol.config.args = [ str(Path(x).relative_to(parent)) for x in modcol.config.args @@ -248,8 +238,7 @@ def test_two(): remotecontrol.loop_once() assert len(remotecontrol.failures) == 1 - modcol_path = modcol.path if PYTEST_GTE_7 else Path(modcol.fspath) - modcol_path.write_text( + modcol.path.write_text( textwrap.dedent( """ def test_one(): @@ -259,7 +248,7 @@ def test_two(): """ ) ) - removepyc(modcol_path) + removepyc(modcol.path) remotecontrol.loop_once() assert not remotecontrol.failures @@ -277,8 +266,7 @@ def test_one(): assert len(remotecontrol.failures) == 1 assert "test_one" in remotecontrol.failures[0] - modcol_path = modcol.path if PYTEST_GTE_7 else Path(modcol.fspath) - modcol_path.write_text( + modcol.path.write_text( textwrap.dedent( """ def test_one(): @@ -288,7 +276,7 @@ def test_two(): """ ) ) - removepyc(modcol_path) + removepyc(modcol.path) remotecontrol.loop_once() assert len(remotecontrol.failures) == 0 remotecontrol.loop_once() diff --git a/testing/test_remote.py b/testing/test_remote.py index 8645029e..245f27d0 100644 --- a/testing/test_remote.py +++ b/testing/test_remote.py @@ -338,9 +338,7 @@ def test_mainargv(request): assert result.ret == 0 -def test_remote_usage_prog(pytester: pytest.Pytester, request) -> None: - if not hasattr(request.config._parser, "prog"): - pytest.skip("prog not available in config parser") +def test_remote_usage_prog(pytester: pytest.Pytester) -> None: pytester.makeconftest( """ import pytest diff --git a/tox.ini b/tox.ini index c4f24387..6a3e9db2 100644 --- a/tox.ini +++ b/tox.ini @@ -9,7 +9,7 @@ isolated_build = true [testenv] extras = testing deps = - pytestmin: pytest==6.2.0 + pytestmin: pytest==7.0.0 pytestlatest: pytest pytestmain: git+https://github.com/pytest-dev/pytest.git commands=