@@ -29,5 +29,5 @@ repos:
|
|||||||
files: ^(src/|testing/)
|
files: ^(src/|testing/)
|
||||||
args: []
|
args: []
|
||||||
additional_dependencies:
|
additional_dependencies:
|
||||||
- pytest>=6.2.0
|
- pytest>=7.0.0
|
||||||
- py>=1.10.0
|
- py>=1.10.0
|
||||||
|
|||||||
1
changelog/1057.removal
Normal file
1
changelog/1057.removal
Normal file
@@ -0,0 +1 @@
|
|||||||
|
pytest>=7.0.0 is now required.
|
||||||
@@ -34,7 +34,7 @@ classifiers = [
|
|||||||
requires-python = ">=3.8"
|
requires-python = ">=3.8"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"execnet>=1.1",
|
"execnet>=1.1",
|
||||||
"pytest>=6.2.0",
|
"pytest>=7.0.0",
|
||||||
]
|
]
|
||||||
dynamic = ["version"]
|
dynamic = ["version"]
|
||||||
|
|
||||||
|
|||||||
@@ -206,9 +206,7 @@ class DSession:
|
|||||||
try:
|
try:
|
||||||
assert False, formatted_error
|
assert False, formatted_error
|
||||||
except AssertionError:
|
except AssertionError:
|
||||||
from _pytest._code import ExceptionInfo
|
excinfo = pytest.ExceptionInfo.from_current()
|
||||||
|
|
||||||
excinfo = ExceptionInfo.from_current()
|
|
||||||
excrepr = excinfo.getrepr()
|
excrepr = excinfo.getrepr()
|
||||||
self.config.hook.pytest_internalerror(excrepr=excrepr, excinfo=excinfo)
|
self.config.hook.pytest_internalerror(excrepr=excrepr, excinfo=excinfo)
|
||||||
|
|
||||||
|
|||||||
@@ -168,7 +168,7 @@ def init_worker_session(channel, args, option_dict):
|
|||||||
sys.path[:] = newpaths
|
sys.path[:] = newpaths
|
||||||
|
|
||||||
# fullwidth, hasmarkup = channel.receive()
|
# fullwidth, hasmarkup = channel.receive()
|
||||||
from _pytest.config import Config
|
from pytest import Config
|
||||||
|
|
||||||
config = Config.fromdictargs(option_dict, list(args))
|
config = Config.fromdictargs(option_dict, list(args))
|
||||||
config.args = args
|
config.args = args
|
||||||
|
|||||||
@@ -6,8 +6,6 @@ import warnings
|
|||||||
import pytest
|
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
|
_sys_path = list(sys.path) # freeze a copy of sys.path at interpreter startup
|
||||||
|
|
||||||
|
|
||||||
@@ -188,16 +186,16 @@ def pytest_addoption(parser):
|
|||||||
parser.addini(
|
parser.addini(
|
||||||
"rsyncdirs",
|
"rsyncdirs",
|
||||||
"list of (relative) paths to be rsynced for remote distributed testing.",
|
"list of (relative) paths to be rsynced for remote distributed testing.",
|
||||||
type="paths" if PYTEST_GTE_7 else "pathlist",
|
type="paths",
|
||||||
)
|
)
|
||||||
parser.addini(
|
parser.addini(
|
||||||
"rsyncignore",
|
"rsyncignore",
|
||||||
"list of (relative) glob-style paths to be ignored for rsyncing.",
|
"list of (relative) glob-style paths to be ignored for rsyncing.",
|
||||||
type="paths" if PYTEST_GTE_7 else "pathlist",
|
type="paths",
|
||||||
)
|
)
|
||||||
parser.addini(
|
parser.addini(
|
||||||
"looponfailroots",
|
"looponfailroots",
|
||||||
type="paths" if PYTEST_GTE_7 else "pathlist",
|
type="paths",
|
||||||
help="directories to check for changes. Default: current directory.",
|
help="directories to check for changes. Default: current directory.",
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|||||||
@@ -201,14 +201,9 @@ class WorkerInteractor:
|
|||||||
|
|
||||||
@pytest.hookimpl
|
@pytest.hookimpl
|
||||||
def pytest_collection_finish(self, session):
|
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(
|
self.sendevent(
|
||||||
"collectionfinish",
|
"collectionfinish",
|
||||||
topdir=topdir,
|
topdir=str(self.config.rootpath),
|
||||||
ids=[item.nodeid for item in session.items],
|
ids=[item.nodeid for item in session.items],
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
from itertools import cycle
|
from itertools import cycle
|
||||||
|
|
||||||
from _pytest.runner import CollectReport
|
import pytest
|
||||||
|
|
||||||
from xdist.remote import Producer
|
from xdist.remote import Producer
|
||||||
from xdist.report import report_collection_diff
|
from xdist.report import report_collection_diff
|
||||||
@@ -307,8 +307,11 @@ class LoadScheduling:
|
|||||||
same_collection = False
|
same_collection = False
|
||||||
self.log(msg)
|
self.log(msg)
|
||||||
if self.config is not None:
|
if self.config is not None:
|
||||||
rep = CollectReport(
|
rep = pytest.CollectReport(
|
||||||
node.gateway.id, "failed", longrepr=msg, result=[]
|
nodeid=node.gateway.id,
|
||||||
|
outcome="failed",
|
||||||
|
longrepr=msg,
|
||||||
|
result=[],
|
||||||
)
|
)
|
||||||
self.config.hook.pytest_collectreport(report=rep)
|
self.config.hook.pytest_collectreport(report=rep)
|
||||||
|
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
from collections import OrderedDict
|
from collections import OrderedDict
|
||||||
|
|
||||||
from _pytest.runner import CollectReport
|
import pytest
|
||||||
|
|
||||||
from xdist.remote import Producer
|
from xdist.remote import Producer
|
||||||
from xdist.report import report_collection_diff
|
from xdist.report import report_collection_diff
|
||||||
@@ -410,7 +410,12 @@ class LoadScopeScheduling:
|
|||||||
if self.config is None:
|
if self.config is None:
|
||||||
continue
|
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)
|
self.config.hook.pytest_collectreport(report=rep)
|
||||||
|
|
||||||
return same_collection
|
return same_collection
|
||||||
|
|||||||
@@ -3,7 +3,7 @@ from __future__ import annotations
|
|||||||
from typing import Any
|
from typing import Any
|
||||||
from typing import NamedTuple
|
from typing import NamedTuple
|
||||||
|
|
||||||
from _pytest.runner import CollectReport
|
import pytest
|
||||||
|
|
||||||
from xdist.remote import Producer
|
from xdist.remote import Producer
|
||||||
from xdist.report import report_collection_diff
|
from xdist.report import report_collection_diff
|
||||||
@@ -323,8 +323,11 @@ class WorkStealingScheduling:
|
|||||||
same_collection = False
|
same_collection = False
|
||||||
self.log(msg)
|
self.log(msg)
|
||||||
if self.config is not None:
|
if self.config is not None:
|
||||||
rep = CollectReport(
|
rep = pytest.CollectReport(
|
||||||
node.gateway.id, "failed", longrepr=msg, result=[]
|
nodeid=node.gateway.id,
|
||||||
|
outcome="failed",
|
||||||
|
longrepr=msg,
|
||||||
|
result=[],
|
||||||
)
|
)
|
||||||
self.config.hook.pytest_collectreport(report=rep)
|
self.config.hook.pytest_collectreport(report=rep)
|
||||||
|
|
||||||
|
|||||||
@@ -401,9 +401,7 @@ class WorkerController:
|
|||||||
# should not land in receiver-thread
|
# should not land in receiver-thread
|
||||||
raise
|
raise
|
||||||
except BaseException:
|
except BaseException:
|
||||||
from _pytest._code import ExceptionInfo
|
excinfo = pytest.ExceptionInfo.from_current()
|
||||||
|
|
||||||
excinfo = ExceptionInfo.from_current()
|
|
||||||
print("!" * 20, excinfo)
|
print("!" * 20, excinfo)
|
||||||
self.config.notify_exception(excinfo)
|
self.config.notify_exception(excinfo)
|
||||||
self.shutdown()
|
self.shutdown()
|
||||||
|
|||||||
@@ -1112,14 +1112,11 @@ def test_error_report_styles(pytester, tb) -> None:
|
|||||||
result.assert_outcomes(failed=1)
|
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.
|
"""Skip collect progress report when working on non-terminals.
|
||||||
|
|
||||||
Similar to pytest-dev/pytest#1397
|
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(
|
pytester.makepyfile(
|
||||||
"""
|
"""
|
||||||
import pytest
|
import pytest
|
||||||
|
|||||||
@@ -12,9 +12,6 @@ from xdist.looponfail import RemoteControl
|
|||||||
from xdist.looponfail import StatRecorder
|
from xdist.looponfail import StatRecorder
|
||||||
|
|
||||||
|
|
||||||
PYTEST_GTE_7 = hasattr(pytest, "version_tuple") and pytest.version_tuple >= (7, 0) # type: ignore[attr-defined]
|
|
||||||
|
|
||||||
|
|
||||||
class TestStatRecorder:
|
class TestStatRecorder:
|
||||||
def test_filechange(self, tmp_path: Path) -> None:
|
def test_filechange(self, tmp_path: Path) -> None:
|
||||||
tmp = tmp_path
|
tmp = tmp_path
|
||||||
@@ -128,9 +125,8 @@ class TestRemoteControl:
|
|||||||
failures = control.runsession()
|
failures = control.runsession()
|
||||||
assert failures
|
assert failures
|
||||||
control.setup()
|
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")
|
||||||
item_path.write_text("def test_func():\n assert 1\n")
|
removepyc(item.path)
|
||||||
removepyc(item_path)
|
|
||||||
topdir, failures = control.runsession()[:2]
|
topdir, failures = control.runsession()[:2]
|
||||||
assert not failures
|
assert not failures
|
||||||
|
|
||||||
@@ -146,10 +142,7 @@ class TestRemoteControl:
|
|||||||
control = RemoteControl(modcol.config)
|
control = RemoteControl(modcol.config)
|
||||||
control.loop_once()
|
control.loop_once()
|
||||||
assert control.failures
|
assert control.failures
|
||||||
if PYTEST_GTE_7:
|
modcol_path = modcol.path # type:ignore[attr-defined]
|
||||||
modcol_path = modcol.path # type:ignore[attr-defined]
|
|
||||||
else:
|
|
||||||
modcol_path = Path(str(modcol.fspath))
|
|
||||||
|
|
||||||
modcol_path.write_text(
|
modcol_path.write_text(
|
||||||
textwrap.dedent(
|
textwrap.dedent(
|
||||||
@@ -179,10 +172,7 @@ class TestRemoteControl:
|
|||||||
"""
|
"""
|
||||||
)
|
)
|
||||||
)
|
)
|
||||||
if PYTEST_GTE_7:
|
parent = modcol.path.parent.parent # type: ignore[attr-defined]
|
||||||
parent = modcol.path.parent.parent # type: ignore[attr-defined]
|
|
||||||
else:
|
|
||||||
parent = Path(modcol.fspath.dirpath().dirpath())
|
|
||||||
monkeypatch.chdir(parent)
|
monkeypatch.chdir(parent)
|
||||||
modcol.config.args = [
|
modcol.config.args = [
|
||||||
str(Path(x).relative_to(parent)) for x in modcol.config.args
|
str(Path(x).relative_to(parent)) for x in modcol.config.args
|
||||||
@@ -248,8 +238,7 @@ class TestLooponFailing:
|
|||||||
remotecontrol.loop_once()
|
remotecontrol.loop_once()
|
||||||
assert len(remotecontrol.failures) == 1
|
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(
|
textwrap.dedent(
|
||||||
"""
|
"""
|
||||||
def test_one():
|
def test_one():
|
||||||
@@ -259,7 +248,7 @@ class TestLooponFailing:
|
|||||||
"""
|
"""
|
||||||
)
|
)
|
||||||
)
|
)
|
||||||
removepyc(modcol_path)
|
removepyc(modcol.path)
|
||||||
remotecontrol.loop_once()
|
remotecontrol.loop_once()
|
||||||
assert not remotecontrol.failures
|
assert not remotecontrol.failures
|
||||||
|
|
||||||
@@ -277,8 +266,7 @@ class TestLooponFailing:
|
|||||||
assert len(remotecontrol.failures) == 1
|
assert len(remotecontrol.failures) == 1
|
||||||
assert "test_one" in remotecontrol.failures[0]
|
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(
|
textwrap.dedent(
|
||||||
"""
|
"""
|
||||||
def test_one():
|
def test_one():
|
||||||
@@ -288,7 +276,7 @@ class TestLooponFailing:
|
|||||||
"""
|
"""
|
||||||
)
|
)
|
||||||
)
|
)
|
||||||
removepyc(modcol_path)
|
removepyc(modcol.path)
|
||||||
remotecontrol.loop_once()
|
remotecontrol.loop_once()
|
||||||
assert len(remotecontrol.failures) == 0
|
assert len(remotecontrol.failures) == 0
|
||||||
remotecontrol.loop_once()
|
remotecontrol.loop_once()
|
||||||
|
|||||||
@@ -338,9 +338,7 @@ def test_remote_mainargv(pytester: pytest.Pytester) -> None:
|
|||||||
assert result.ret == 0
|
assert result.ret == 0
|
||||||
|
|
||||||
|
|
||||||
def test_remote_usage_prog(pytester: pytest.Pytester, request) -> None:
|
def test_remote_usage_prog(pytester: pytest.Pytester) -> None:
|
||||||
if not hasattr(request.config._parser, "prog"):
|
|
||||||
pytest.skip("prog not available in config parser")
|
|
||||||
pytester.makeconftest(
|
pytester.makeconftest(
|
||||||
"""
|
"""
|
||||||
import pytest
|
import pytest
|
||||||
|
|||||||
2
tox.ini
2
tox.ini
@@ -9,7 +9,7 @@ isolated_build = true
|
|||||||
[testenv]
|
[testenv]
|
||||||
extras = testing
|
extras = testing
|
||||||
deps =
|
deps =
|
||||||
pytestmin: pytest==6.2.0
|
pytestmin: pytest==7.0.0
|
||||||
pytestlatest: pytest
|
pytestlatest: pytest
|
||||||
pytestmain: git+https://github.com/pytest-dev/pytest.git
|
pytestmain: git+https://github.com/pytest-dev/pytest.git
|
||||||
commands=
|
commands=
|
||||||
|
|||||||
Reference in New Issue
Block a user