From 749faf5e7c29fc6fdefbe15a88b2871fb2abb868 Mon Sep 17 00:00:00 2001 From: holger krekel Date: Mon, 27 Sep 2010 16:13:55 +0200 Subject: [PATCH] re-introduce slaveinput/slaveoutput configure protocol --- testing/acceptance_test.py | 11 ++++++----- xdist/dsession.py | 7 ++++++- xdist/remote.py | 25 ++++++++++++++----------- 3 files changed, 26 insertions(+), 17 deletions(-) diff --git a/testing/acceptance_test.py b/testing/acceptance_test.py index 8e9709a..578cb58 100644 --- a/testing/acceptance_test.py +++ b/testing/acceptance_test.py @@ -175,8 +175,8 @@ class TestDistribution: node.slaveinput['a'] = 42 node.slaveinput['b'] = 7 - # This hook only takes action on slave. def pytest_configure(config): + # this attribute is only set on slaves if hasattr(config, 'slaveinput'): a = config.slaveinput['a'] b = config.slaveinput['b'] @@ -187,7 +187,6 @@ class TestDistribution: def pytest_testnodedown(node, error): node.config.calc_result = node.slaveoutput['r'] - # This hook only takes action on master. def pytest_terminal_summary(terminalreporter): if not hasattr(terminalreporter.config, 'slaveinput'): calc_result = terminalreporter.config.calc_result @@ -210,18 +209,20 @@ class TestDistribution: """) testdir.makeconftest(""" def pytest_sessionfinish(session): + # on the slave if hasattr(session.config, 'slaveoutput'): session.config.slaveoutput['s2'] = 42 + # on the master def pytest_testnodedown(node, error): assert node.slaveoutput['s2'] == 42 print ("s2call-finished") """) - args = ["-n1"] + args = ["-n1", "--debug"] result = testdir.runpytest(*args) s = result.stdout.str() - assert result.ret - assert 'SIGINT' in s + assert result.ret == 2 assert 's2call' in s + assert "Interrupted" in s def test_keyboard_interrupt_dist(self, testdir): # xxx could be refined to check for return code diff --git a/xdist/dsession.py b/xdist/dsession.py index 3b812c2..4d11c40 100644 --- a/xdist/dsession.py +++ b/xdist/dsession.py @@ -162,8 +162,13 @@ class DSession: node.shutdown() def slave_slavefinished(self, node): + self.config.hook.pytest_testnodedown(node=node, error=None) + if node.slaveoutput['exitstatus'] == 2: # keyboard-interrupt + self.shouldstop = "%s received keyboard-interrupt" % (node,) + self.slave_errordown(node, "keyboard-interrupt") + return crashitem = self.sched.remove_node(node) - assert not crashitem, (crashitem, node) + #assert not crashitem, (crashitem, node) if self.shuttingdown and not self.sched.hasnodes(): self.session_finished = True diff --git a/xdist/remote.py b/xdist/remote.py index e057158..92b557f 100644 --- a/xdist/remote.py +++ b/xdist/remote.py @@ -4,11 +4,10 @@ import py import sys -import execnet from py._plugin import pytest_runner as runner # XXX load dynamically def make_reltoroot(roots, args): - # XXX introduce/use public API for splitting args + # XXX introduce/use public API for splitting py.test args splitcode = "::" l = [] for arg in args: @@ -32,6 +31,7 @@ class SlaveController(object): self.putevent = putevent self.gateway = gateway self.config = config + self.slaveinput = {'slaveid': gateway.id} self._down = False self.log = py.log.Producer("slavectl-%s" % gateway.id) if not self.config.option.debug: @@ -46,7 +46,9 @@ class SlaveController(object): args = self.config.args if not spec.popen or spec.chdir: args = make_reltoroot(self.nodemanager.roots, args) + self.config.hook.pytest_configure_node(node=self) self.channel = self.gateway.remote_exec(init_slave_session, + slaveinput=self.slaveinput, args=args, option_dict=vars(self.config.option), ) if self.putevent: @@ -123,14 +125,12 @@ class SlaveController(object): py.builtin.print_("!" * 20, excinfo) self.config.pluginmanager.notify_exception(excinfo) -def init_slave_session(channel, args, option_dict): +def init_slave_session(channel, slaveinput, args, option_dict): import py - #outchannel = channel.gateway.newchannel() - #sys.stdout = sys.stderr = outchannel.makefile('w') - #channel.send(outchannel) - #fullwidth, hasmarkup = channel.receive() from xdist.remote import remote_initconfig, SlaveInteractor config = remote_initconfig(py.test.config, option_dict, args) + config.slaveinput = slaveinput + config.slaveoutput = {} interactor = SlaveInteractor(config, channel) config.hook.pytest_cmdline_main(config=config) @@ -148,7 +148,8 @@ def remote_initconfig(config, option_dict, args): class SlaveInteractor: def __init__(self, config, channel): self.config = config - self.log = py.log.Producer("slave") + self.slaveid = config.slaveinput.get('slaveid', "?") + self.log = py.log.Producer("slave-%s" % self.slaveid) if not config.option.debug: py.log.setconsumer(self.log._keywords, None) self.channel = channel @@ -167,8 +168,11 @@ class SlaveInteractor: self.collection = session.collection self.sendevent("slaveready") - def pytest_sessionfinish(self): - self.sendevent("slavefinished", slaveoutput={}) + def pytest_sessionfinish(self, __multicall__, exitstatus): + self.config.slaveoutput['exitstatus'] = exitstatus + res = __multicall__.execute() + self.sendevent("slavefinished", slaveoutput=self.config.slaveoutput) + return res def pytest_perform_collection(self, session): self.sendevent("collectionstart") @@ -188,7 +192,6 @@ class SlaveInteractor: return True def pytest_log_finishcollection(self, collection): - self.log("pytest_log_finishcollection") ids = [collection.getid(item) for item in collection.items] self.sendevent("collectionfinish", topdir=str(collection.topdir),