* introduce explicit pytest_configure_node hook for node configuration,
simplifying implementation of slaveinput/slaveoutput data exchange * only require the already released execnet-1.0.5
This commit is contained in:
2
setup.py
2
setup.py
@@ -22,7 +22,7 @@ setup(
|
|||||||
packages = ['xdist'],
|
packages = ['xdist'],
|
||||||
entry_points = {'pytest11': ['xdist = xdist.plugin'],},
|
entry_points = {'pytest11': ['xdist = xdist.plugin'],},
|
||||||
zip_safe=False,
|
zip_safe=False,
|
||||||
install_requires = ['execnet>=1.0.6', 'py>=1.2.2'],
|
install_requires = ['execnet>=1.0.5', 'py>=1.2.2'],
|
||||||
classifiers=[
|
classifiers=[
|
||||||
'Development Status :: 4 - Beta',
|
'Development Status :: 4 - Beta',
|
||||||
'Intended Audience :: Developers',
|
'Intended Audience :: Developers',
|
||||||
|
|||||||
@@ -120,30 +120,30 @@ class TestDistribution:
|
|||||||
|
|
||||||
def test_data_exchange(self, testdir):
|
def test_data_exchange(self, testdir):
|
||||||
c1 = testdir.makeconftest("""
|
c1 = testdir.makeconftest("""
|
||||||
# This hook only called on master.
|
# This hook only called on master.
|
||||||
def pytest_testnodeready(node):
|
def pytest_configure_node(node):
|
||||||
node.slaveinput['a'] = 42
|
node.slaveinput['a'] = 42
|
||||||
node.slaveinput['b'] = 7
|
node.slaveinput['b'] = 7
|
||||||
|
|
||||||
# This hook only take action on slave.
|
# This hook only takes action on slave.
|
||||||
def pytest_sessionstart(session):
|
def pytest_configure(config):
|
||||||
if hasattr(session.config, 'slaveinput'):
|
if hasattr(config, 'slaveinput'):
|
||||||
a = session.config.slaveinput['a']
|
a = config.slaveinput['a']
|
||||||
b = session.config.slaveinput['b']
|
b = config.slaveinput['b']
|
||||||
r = a + b
|
r = a + b
|
||||||
session.config.slaveoutput['r'] = r
|
config.slaveoutput['r'] = r
|
||||||
|
|
||||||
# This hook only called on master.
|
# This hook only called on master.
|
||||||
def pytest_testnodedown(node, error):
|
def pytest_testnodedown(node, error):
|
||||||
node.config.calc_result = node.slaveoutput['r']
|
node.config.calc_result = node.slaveoutput['r']
|
||||||
|
|
||||||
# This hook only take action on master.
|
# This hook only takes action on master.
|
||||||
def pytest_terminal_summary(terminalreporter):
|
def pytest_terminal_summary(terminalreporter):
|
||||||
if not hasattr(terminalreporter.config, 'slaveinput'):
|
if not hasattr(terminalreporter.config, 'slaveinput'):
|
||||||
calc_result = terminalreporter.config.calc_result
|
calc_result = terminalreporter.config.calc_result
|
||||||
terminalreporter._tw.sep('-', 'calculated result is %s' % calc_result)
|
terminalreporter._tw.sep('-',
|
||||||
|
'calculated result is %s' % calc_result)
|
||||||
""")
|
""")
|
||||||
|
|
||||||
p1 = testdir.makepyfile("def test_func(): pass")
|
p1 = testdir.makepyfile("def test_func(): pass")
|
||||||
result = testdir.runpytest(p1, '-d', '--tx=popen')
|
result = testdir.runpytest(p1, '-d', '--tx=popen')
|
||||||
result.stdout.fnmatch_lines([
|
result.stdout.fnmatch_lines([
|
||||||
|
|||||||
@@ -8,6 +8,9 @@ def pytest_gwmanage_rsyncstart(source, gateways):
|
|||||||
def pytest_gwmanage_rsyncfinish(source, gateways):
|
def pytest_gwmanage_rsyncfinish(source, gateways):
|
||||||
""" called after rsyncing a directory to remote gateways takes place. """
|
""" called after rsyncing a directory to remote gateways takes place. """
|
||||||
|
|
||||||
|
def pytest_configure_node(node):
|
||||||
|
""" configure node information before it gets instantiated. """
|
||||||
|
|
||||||
def pytest_testnodeready(node):
|
def pytest_testnodeready(node):
|
||||||
""" Test Node is ready to operate. """
|
""" Test Node is ready to operate. """
|
||||||
|
|
||||||
@@ -19,3 +22,4 @@ def pytest_rescheduleitems(items):
|
|||||||
|
|
||||||
def pytest_looponfailinfo(failreports, rootdirs):
|
def pytest_looponfailinfo(failreports, rootdirs):
|
||||||
""" info for repeating failing tests. """
|
""" info for repeating failing tests. """
|
||||||
|
|
||||||
|
|||||||
@@ -18,12 +18,10 @@ class TXNode(object):
|
|||||||
self.config = config
|
self.config = config
|
||||||
self.putevent = putevent
|
self.putevent = putevent
|
||||||
self.gateway = gateway
|
self.gateway = gateway
|
||||||
self.channel = install_slave(gateway, config)
|
self.slaveinput = {}
|
||||||
|
self.channel = install_slave(self)
|
||||||
self.channel.setcallback(self.callback, endmarker=self.ENDMARK)
|
self.channel.setcallback(self.callback, endmarker=self.ENDMARK)
|
||||||
self._down = False
|
self._down = False
|
||||||
self.slaveinputsent = False
|
|
||||||
self.slaveinput = {}
|
|
||||||
self.slaveoutput = {}
|
|
||||||
|
|
||||||
def __repr__(self):
|
def __repr__(self):
|
||||||
id = self.gateway.id
|
id = self.gateway.id
|
||||||
@@ -72,30 +70,22 @@ class TXNode(object):
|
|||||||
py.builtin.print_("!" * 20, excinfo)
|
py.builtin.print_("!" * 20, excinfo)
|
||||||
self.config.pluginmanager.notify_exception(excinfo)
|
self.config.pluginmanager.notify_exception(excinfo)
|
||||||
|
|
||||||
def sendslaveinput(self):
|
|
||||||
if not self.slaveinputsent:
|
|
||||||
self.channel.send(self.slaveinput)
|
|
||||||
self.slaveinputsent = True
|
|
||||||
|
|
||||||
def send(self, item):
|
def send(self, item):
|
||||||
assert item is not None
|
assert item is not None
|
||||||
self.sendslaveinput()
|
|
||||||
self.channel.send(item)
|
self.channel.send(item)
|
||||||
|
|
||||||
def sendlist(self, itemlist):
|
def sendlist(self, itemlist):
|
||||||
self.sendslaveinput()
|
|
||||||
self.channel.send(itemlist)
|
self.channel.send(itemlist)
|
||||||
|
|
||||||
def shutdown(self, kill=False):
|
def shutdown(self, kill=False):
|
||||||
if kill:
|
if kill:
|
||||||
self.gateway.exit()
|
self.gateway.exit()
|
||||||
else:
|
else:
|
||||||
self.sendslaveinput()
|
|
||||||
self.channel.send(None)
|
self.channel.send(None)
|
||||||
|
|
||||||
# setting up slave code
|
# configuring and setting up slave node
|
||||||
def install_slave(gateway, config):
|
def install_slave(node):
|
||||||
channel = gateway.remote_exec(source="""
|
channel = node.gateway.remote_exec(source="""
|
||||||
import os, sys
|
import os, sys
|
||||||
sys.path.insert(0, os.getcwd())
|
sys.path.insert(0, os.getcwd())
|
||||||
from xdist.mypickle import PickleChannel
|
from xdist.mypickle import PickleChannel
|
||||||
@@ -108,12 +98,14 @@ def install_slave(gateway, config):
|
|||||||
channel.receive()
|
channel.receive()
|
||||||
channel = PickleChannel(channel)
|
channel = PickleChannel(channel)
|
||||||
basetemp = None
|
basetemp = None
|
||||||
if gateway.spec.popen:
|
config = node.config
|
||||||
|
config.hook.pytest_configure_node(node=node)
|
||||||
|
if node.gateway.spec.popen:
|
||||||
popenbase = config.ensuretemp("popen")
|
popenbase = config.ensuretemp("popen")
|
||||||
basetemp = py.path.local.make_numbered_dir(prefix="slave-",
|
basetemp = py.path.local.make_numbered_dir(prefix="slave-",
|
||||||
keep=0, rootdir=popenbase)
|
keep=0, rootdir=popenbase)
|
||||||
basetemp = str(basetemp)
|
basetemp = str(basetemp)
|
||||||
channel.send((config, basetemp, gateway.id))
|
channel.send((config, node.slaveinput, basetemp, node.gateway.id))
|
||||||
return channel
|
return channel
|
||||||
|
|
||||||
class SlaveNode(object):
|
class SlaveNode(object):
|
||||||
@@ -134,15 +126,15 @@ class SlaveNode(object):
|
|||||||
|
|
||||||
def run(self):
|
def run(self):
|
||||||
channel = self.channel
|
channel = self.channel
|
||||||
self.config, basetemp, self.nodeid = channel.receive()
|
self.config, slaveinput, basetemp, self.nodeid = channel.receive()
|
||||||
if basetemp:
|
if basetemp:
|
||||||
self.config.basetemp = py.path.local(basetemp)
|
self.config.basetemp = py.path.local(basetemp)
|
||||||
|
self.config.slaveinput = slaveinput
|
||||||
|
self.config.slaveoutput = {}
|
||||||
self.config.pluginmanager.do_configure(self.config)
|
self.config.pluginmanager.do_configure(self.config)
|
||||||
self.config.pluginmanager.register(self)
|
self.config.pluginmanager.register(self)
|
||||||
self.runner = self.config.pluginmanager.getplugin("pytest_runner")
|
self.runner = self.config.pluginmanager.getplugin("pytest_runner")
|
||||||
self.sendevent("slaveready")
|
self.sendevent("slaveready")
|
||||||
self.config.slaveinput = channel.receive()
|
|
||||||
self.config.slaveoutput = {}
|
|
||||||
try:
|
try:
|
||||||
self.config.hook.pytest_sessionstart(session=self)
|
self.config.hook.pytest_sessionstart(session=self)
|
||||||
while 1:
|
while 1:
|
||||||
|
|||||||
Reference in New Issue
Block a user