Merge pull request #728 from bluetech/hookimpl-decorators

Add explicit pytest.hookspec/hookimpl annotations, avoid legacy tryfirst/trylast marks
This commit is contained in:
Ran Benita
2021-11-02 12:28:36 +02:00
committed by GitHub
7 changed files with 40 additions and 6 deletions

View File

@@ -67,7 +67,7 @@ class DSession:
if self.terminal and self.config.option.verbose >= 0:
self.terminal.write_line(line)
@pytest.mark.trylast
@pytest.hookimpl(trylast=True)
def pytest_sessionstart(self, session):
"""Creates and starts the nodes.
@@ -79,6 +79,7 @@ class DSession:
self._active_nodes.update(nodes)
self._session = session
@pytest.hookimpl
def pytest_sessionfinish(self, session):
"""Shutdown all nodes."""
nm = getattr(self, "nodemanager", None) # if not fully initialized
@@ -86,11 +87,12 @@ class DSession:
nm.teardown_nodes()
self._session = None
@pytest.hookimpl
def pytest_collection(self):
# prohibit collection of test items in controller process
return True
@pytest.mark.trylast
@pytest.hookimpl(trylast=True)
def pytest_xdist_make_scheduler(self, config, log):
dist = config.getvalue("dist")
schedulers = {
@@ -101,6 +103,7 @@ class DSession:
}
return schedulers[dist](config, log)
@pytest.hookimpl
def pytest_runtestloop(self):
self.sched = self.config.hook.pytest_xdist_make_scheduler(
config=self.config, log=self.log
@@ -223,6 +226,7 @@ class DSession:
self._clone_node(node)
self._active_nodes.remove(node)
@pytest.hookimpl
def pytest_terminal_summary(self, terminalreporter):
if self.config.option.verbose >= 0 and self._summary_report:
terminalreporter.write_sep("=", "xdist: {}".format(self._summary_report))
@@ -390,6 +394,7 @@ class TerminalDistReporter:
self._lastlen = len(line)
self.tr.rewrite(pline, bold=True)
@pytest.hookimpl
def pytest_xdist_setupnodes(self, specs):
self._specs = specs
for spec in specs:
@@ -397,6 +402,7 @@ class TerminalDistReporter:
self.setstatus(spec, "I", show=True)
self.ensure_show_status()
@pytest.hookimpl
def pytest_xdist_newgateway(self, gateway):
if self.config.option.verbose > 0:
rinfo = gateway._rinfo()
@@ -408,6 +414,7 @@ class TerminalDistReporter:
)
self.setstatus(gateway.spec, "C")
@pytest.hookimpl
def pytest_testnodeready(self, node):
if self.config.option.verbose > 0:
d = node.workerinfo
@@ -417,6 +424,7 @@ class TerminalDistReporter:
self.rewrite(infoline, newline=True)
self.setstatus(node.gateway.spec, "ok")
@pytest.hookimpl
def pytest_testnodedown(self, node, error):
if not error:
return

View File

@@ -13,6 +13,7 @@ import time
import execnet
@pytest.hookimpl
def pytest_addoption(parser):
group = parser.getgroup("xdist", "distributed and subprocess testing")
group._addoption(
@@ -26,6 +27,7 @@ def pytest_addoption(parser):
)
@pytest.hookimpl
def pytest_cmdline_main(config):
if config.getoption("looponfail"):
@@ -178,6 +180,7 @@ class WorkerFailSession:
if self.config.option.debug:
print(" ".join(map(str, args)))
@pytest.hookimpl
def pytest_collection(self, session):
self.session = session
self.trails = self.current_command
@@ -192,10 +195,12 @@ class WorkerFailSession:
hook.pytest_collection_finish(session=session)
return True
@pytest.hookimpl
def pytest_runtest_logreport(self, report):
if report.failed:
self.recorded_failures.append(report)
@pytest.hookimpl
def pytest_collectreport(self, report):
if report.failed:
self.recorded_failures.append(report)

View File

@@ -14,18 +14,22 @@ must be taken in plugins in case ``xdist`` is not installed. Please see:
import pytest
@pytest.hookspec()
def pytest_xdist_setupnodes(config, specs):
"""called before any remote node is set up."""
@pytest.hookspec()
def pytest_xdist_newgateway(gateway):
"""called on new raw gateway creation."""
@pytest.hookspec()
def pytest_xdist_rsyncstart(source, gateways):
"""called before rsyncing a directory to remote gateways takes place."""
@pytest.hookspec()
def pytest_xdist_rsyncfinish(source, gateways):
"""called after rsyncing a directory to remote gateways takes place."""
@@ -35,18 +39,22 @@ def pytest_xdist_getremotemodule():
"""called when creating remote node"""
@pytest.hookspec()
def pytest_configure_node(node):
"""configure node information before it gets instantiated."""
@pytest.hookspec()
def pytest_testnodeready(node):
"""Test Node is ready to operate."""
@pytest.hookspec()
def pytest_testnodedown(node, error):
"""Test Node is down."""
@pytest.hookspec()
def pytest_xdist_node_collection_finished(node, ids):
"""called by the controller node when a worker node finishes collecting."""

View File

@@ -12,6 +12,7 @@ PYTEST_GTE_7 = hasattr(pytest, "version_tuple") and pytest.version_tuple >= (7,
_sys_path = list(sys.path) # freeze a copy of sys.path at interpreter startup
@pytest.hookimpl
def pytest_xdist_auto_num_workers(config):
try:
import psutil
@@ -50,6 +51,7 @@ def parse_numprocesses(s):
return int(s)
@pytest.hookimpl
def pytest_addoption(parser):
group = parser.getgroup("xdist", "distributed and subprocess testing")
group._addoption(
@@ -171,6 +173,7 @@ def pytest_addoption(parser):
# -------------------------------------------------------------------------
@pytest.hookimpl
def pytest_addhooks(pluginmanager):
from xdist import newhooks
@@ -182,7 +185,7 @@ def pytest_addhooks(pluginmanager):
# -------------------------------------------------------------------------
@pytest.mark.trylast
@pytest.hookimpl(trylast=True)
def pytest_configure(config):
if config.getoption("dist") != "no" and not config.getvalue("collectonly"):
from xdist.dsession import DSession
@@ -202,7 +205,7 @@ def pytest_configure(config):
config.option.forked = True
@pytest.mark.tryfirst
@pytest.hookimpl(tryfirst=True)
def pytest_cmdline_main(config):
usepdb = config.getoption("usepdb", False) # a core option
if config.option.numprocesses in ("auto", "logical"):

View File

@@ -47,12 +47,14 @@ class WorkerInteractor:
self.log("sending", name, kwargs)
self.channel.send((name, kwargs))
@pytest.hookimpl
def pytest_internalerror(self, excrepr):
formatted_error = str(excrepr)
for line in formatted_error.split("\n"):
self.log("IERROR>", line)
interactor.sendevent("internal_error", formatted_error=formatted_error)
@pytest.hookimpl
def pytest_sessionstart(self, session):
self.session = session
workerinfo = getinfodict()
@@ -65,9 +67,11 @@ class WorkerInteractor:
yield
self.sendevent("workerfinished", workeroutput=self.config.workeroutput)
@pytest.hookimpl
def pytest_collection(self, session):
self.sendevent("collectionstart")
@pytest.hookimpl
def pytest_runtestloop(self, session):
self.log("entering main loop")
torun = []
@@ -112,6 +116,7 @@ class WorkerInteractor:
"runtest_protocol_complete", item_index=self.item_index, duration=duration
)
@pytest.hookimpl
def pytest_collection_finish(self, session):
try:
topdir = str(self.config.rootpath)
@@ -124,12 +129,15 @@ class WorkerInteractor:
ids=[item.nodeid for item in session.items],
)
@pytest.hookimpl
def pytest_runtest_logstart(self, nodeid, location):
self.sendevent("logstart", nodeid=nodeid, location=location)
@pytest.hookimpl
def pytest_runtest_logfinish(self, nodeid, location):
self.sendevent("logfinish", nodeid=nodeid, location=location)
@pytest.hookimpl
def pytest_runtest_logreport(self, report):
data = self.config.hook.pytest_report_to_serializable(
config=self.config, report=report
@@ -140,6 +148,7 @@ class WorkerInteractor:
assert self.session.items[self.item_index].nodeid == report.nodeid
self.sendevent("testreport", data=data)
@pytest.hookimpl
def pytest_collectreport(self, report):
# send only reports that have not passed to controller as optimization (#330)
if not report.passed:
@@ -148,6 +157,7 @@ class WorkerInteractor:
)
self.sendevent("collectreport", data=data)
@pytest.hookimpl
def pytest_warning_recorded(self, warning_message, when, nodeid, location):
self.sendevent(
"warning_recorded",

View File

@@ -212,7 +212,7 @@ class WorkerController:
ENDMARK = -1
class RemoteHook:
@pytest.mark.trylast
@pytest.hookimpl(trylast=True)
def pytest_xdist_getremotemodule(self):
return xdist.remote

View File

@@ -205,7 +205,7 @@ class TestDistribution:
def pytest_addoption(parser):
parser.addoption("--foobar", action="store", dest="foobar_opt")
@pytest.mark.tryfirst
@pytest.hookimpl(tryfirst=True)
def pytest_load_initial_conftests(early_config):
opt = early_config.known_args_namespace.foobar_opt
print("--foobar=%s active! [%s]" % (opt, os.getpid()), file=sys.stderr)