[svn r63869] * moving execnet events to become api plugin calls.
* defining Execnet hooks in an explicit API --HG-- branch : trunk
This commit is contained in:
parent
92a06c3787
commit
66c64e6b97
|
@ -25,8 +25,8 @@ version = "1.0.0b1"
|
|||
|
||||
initpkg(__name__,
|
||||
description = "pylib and py.test: agile development and test support library",
|
||||
revision = int('$LastChangedRevision: 63808 $'.split(':')[1][:-1]),
|
||||
lastchangedate = '$LastChangedDate: 2009-04-07 22:46:50 +0200 (Tue, 07 Apr 2009) $',
|
||||
revision = int('$LastChangedRevision: 63869 $'.split(':')[1][:-1]),
|
||||
lastchangedate = '$LastChangedDate: 2009-04-08 19:50:14 +0200 (Wed, 08 Apr 2009) $',
|
||||
version = version,
|
||||
url = "http://pylib.org",
|
||||
download_url = "http://codespeak.net/py/%s/download.html" % version,
|
||||
|
@ -146,6 +146,7 @@ initpkg(__name__,
|
|||
|
||||
# gateways into remote contexts
|
||||
'execnet.__doc__' : ('./execnet/__init__.py', '__doc__'),
|
||||
'execnet._API' : ('./execnet/gateway.py', 'ExecnetAPI'),
|
||||
'execnet.SocketGateway' : ('./execnet/register.py', 'SocketGateway'),
|
||||
'execnet.PopenGateway' : ('./execnet/register.py', 'PopenGateway'),
|
||||
'execnet.SshGateway' : ('./execnet/register.py', 'SshGateway'),
|
||||
|
|
44
py/_com.py
44
py/_com.py
|
@ -36,26 +36,8 @@ class MultiCall:
|
|||
|
||||
def execute(self, firstresult=False):
|
||||
while self.methods:
|
||||
self.currentmethod = currentmethod = self.methods.pop()
|
||||
# provide call introspection if "__call__" is the first positional argument
|
||||
if hasattr(currentmethod, 'im_self'):
|
||||
varnames = currentmethod.im_func.func_code.co_varnames
|
||||
needscall = varnames[1:2] == ('__call__',)
|
||||
else:
|
||||
try:
|
||||
varnames = currentmethod.func_code.co_varnames
|
||||
except AttributeError:
|
||||
# builtin function
|
||||
varnames = ()
|
||||
needscall = varnames[:1] == ('__call__',)
|
||||
if needscall:
|
||||
res = currentmethod(self, *self.args, **self.kwargs)
|
||||
else:
|
||||
#try:
|
||||
res = currentmethod(*self.args, **self.kwargs)
|
||||
#except TypeError:
|
||||
# print currentmethod.__module__, currentmethod.__name__, self.args, self.kwargs
|
||||
# raise
|
||||
currentmethod = self.methods.pop()
|
||||
res = self.execute_method(currentmethod)
|
||||
if hasattr(self, '_ex1'):
|
||||
self.results = [res]
|
||||
break
|
||||
|
@ -70,6 +52,28 @@ class MultiCall:
|
|||
if self.results:
|
||||
return self.results[-1]
|
||||
|
||||
def execute_method(self, currentmethod):
|
||||
self.currentmethod = currentmethod
|
||||
# provide call introspection if "__call__" is the first positional argument
|
||||
if hasattr(currentmethod, 'im_self'):
|
||||
varnames = currentmethod.im_func.func_code.co_varnames
|
||||
needscall = varnames[1:2] == ('__call__',)
|
||||
else:
|
||||
try:
|
||||
varnames = currentmethod.func_code.co_varnames
|
||||
except AttributeError:
|
||||
# builtin function
|
||||
varnames = ()
|
||||
needscall = varnames[:1] == ('__call__',)
|
||||
if needscall:
|
||||
return currentmethod(self, *self.args, **self.kwargs)
|
||||
else:
|
||||
#try:
|
||||
return currentmethod(*self.args, **self.kwargs)
|
||||
#except TypeError:
|
||||
# print currentmethod.__module__, currentmethod.__name__, self.args, self.kwargs
|
||||
# raise
|
||||
|
||||
def exclude_other_results(self):
|
||||
self._ex1 = True
|
||||
|
||||
|
|
|
@ -57,6 +57,17 @@ class ExecnetAPI:
|
|||
""" signal initialisation of new gateway. """
|
||||
def pyexecnet_gateway_exit(self, gateway):
|
||||
""" signal exitting of gateway. """
|
||||
|
||||
def pyexecnet_gwmanage_newgateway(self, gateway, platinfo):
|
||||
""" called when a manager has made a new gateway. """
|
||||
|
||||
def pyexecnet_gwmanage_rsyncstart(self, source, gateways):
|
||||
""" called before rsyncing a directory to remote gateways takes place. """
|
||||
|
||||
def pyexecnet_gwmanage_rsyncfinish(self, source, gateways):
|
||||
""" called after rsyncing a directory to remote gateways takes place. """
|
||||
|
||||
|
||||
|
||||
# ----------------------------------------------------------
|
||||
# Base Gateway (used for both remote and local side)
|
||||
|
@ -76,12 +87,11 @@ class Gateway(object):
|
|||
self._io = io
|
||||
self._channelfactory = ChannelFactory(self, _startcount)
|
||||
self._cleanup.register(self)
|
||||
try:
|
||||
if _startcount == 1: # only import 'py' on the "client" side
|
||||
from py._com import PluginAPI
|
||||
except ImportError:
|
||||
self.api = ExecnetAPI()
|
||||
else:
|
||||
self.api = PluginAPI(ExecnetAPI)
|
||||
else:
|
||||
self.api = ExecnetAPI()
|
||||
|
||||
def _initreceive(self, requestqueue=False):
|
||||
if requestqueue:
|
||||
|
|
|
@ -21,6 +21,7 @@ class GatewayManager:
|
|||
if not spec.chdir and not spec.popen:
|
||||
spec.chdir = defaultchdir
|
||||
self.specs.append(spec)
|
||||
self.api = py._com.PluginAPI(py.execnet._API)
|
||||
|
||||
def trace(self, msg):
|
||||
self.notify("trace", "gatewaymanage", msg)
|
||||
|
@ -34,7 +35,8 @@ class GatewayManager:
|
|||
gw = py.execnet.makegateway(spec)
|
||||
self.gateways.append(gw)
|
||||
gw.id = "[%s]" % len(self.gateways)
|
||||
self.notify("gwmanage_newgateway", gw, gw._rinfo())
|
||||
self.api.pyexecnet_gwmanage_newgateway(
|
||||
gateway=gw, platinfo=gw._rinfo())
|
||||
|
||||
def getgateways(self, remote=True, inplacelocal=True):
|
||||
if not self.gateways and self.specs:
|
||||
|
@ -79,9 +81,15 @@ class GatewayManager:
|
|||
rsync.add_target_host(gateway, finished=finished)
|
||||
seen[spec] = gateway
|
||||
if seen:
|
||||
self.notify("gwmanage_rsyncstart", source=source, gateways=seen.values())
|
||||
self.api.pyexecnet_gwmanage_rsyncstart(
|
||||
source=source,
|
||||
gateways=seen.values(),
|
||||
)
|
||||
rsync.send()
|
||||
self.notify("gwmanage_rsyncfinish", source=source, gateways=seen.values())
|
||||
self.api.pyexecnet_gwmanage_rsyncfinish(
|
||||
source=source,
|
||||
gateways=seen.values()
|
||||
)
|
||||
else:
|
||||
self.trace("rsync: nothing to do.")
|
||||
|
||||
|
|
|
@ -20,16 +20,15 @@ class TestGatewayManagerPopen:
|
|||
for spec in GatewayManager(l, defaultchdir="abc").specs:
|
||||
assert spec.chdir == "abc"
|
||||
|
||||
def test_popen_makegateway_events(self, eventrecorder):
|
||||
def test_popen_makegateway_events(self, _pytest):
|
||||
rec = _pytest.getcallrecorder(py.execnet._API)
|
||||
hm = GatewayManager(["popen"] * 2)
|
||||
hm.makegateways()
|
||||
event = eventrecorder.popevent("gwmanage_newgateway")
|
||||
gw, platinfo = event.args[:2]
|
||||
assert gw.id == "[1]"
|
||||
platinfo.executable = gw._rinfo().executable
|
||||
event = eventrecorder.popevent("gwmanage_newgateway")
|
||||
gw, platinfo = event.args[:2]
|
||||
assert gw.id == "[2]"
|
||||
call = rec.popcall("pyexecnet_gwmanage_newgateway")
|
||||
assert call.gateway.id == "[1]"
|
||||
assert call.platinfo.executable == call.gateway._rinfo().executable
|
||||
call = rec.popcall("pyexecnet_gwmanage_newgateway")
|
||||
assert call.gateway.id == "[2]"
|
||||
assert len(hm.gateways) == 2
|
||||
hm.exit()
|
||||
assert not len(hm.gateways)
|
||||
|
@ -60,18 +59,17 @@ class TestGatewayManagerPopen:
|
|||
assert dest.join("dir1", "dir2").check()
|
||||
assert dest.join("dir1", "dir2", 'hello').check()
|
||||
|
||||
def test_hostmanage_rsync_same_popen_twice(self, source, dest, eventrecorder):
|
||||
def test_hostmanage_rsync_same_popen_twice(self, source, dest, _pytest):
|
||||
rec = _pytest.getcallrecorder(py.execnet._API)
|
||||
hm = GatewayManager(["popen//chdir=%s" %dest] * 2)
|
||||
hm.makegateways()
|
||||
source.ensure("dir1", "dir2", "hello")
|
||||
hm.rsync(source)
|
||||
event = eventrecorder.popevent("gwmanage_rsyncstart")
|
||||
source2 = event.kwargs['source']
|
||||
gws = event.kwargs['gateways']
|
||||
assert source2 == source
|
||||
assert len(gws) == 1
|
||||
assert hm.gateways[0] == gws[0]
|
||||
event = eventrecorder.popevent("gwmanage_rsyncfinish")
|
||||
call = rec.popcall("pyexecnet_gwmanage_rsyncstart")
|
||||
assert call.source == source
|
||||
assert len(call.gateways) == 1
|
||||
assert hm.gateways[0] == call.gateways[0]
|
||||
call = rec.popcall("pyexecnet_gwmanage_rsyncfinish")
|
||||
|
||||
def test_multi_chdir_popen_with_path(self, testdir):
|
||||
import os
|
||||
|
|
|
@ -77,18 +77,6 @@ class Events:
|
|||
def pyevent__NOP(self, *args, **kwargs):
|
||||
""" the no-operation call. """
|
||||
|
||||
def pyevent__gateway_init(self, gateway):
|
||||
""" called after a gateway has been initialized. """
|
||||
|
||||
def pyevent__gateway_exit(self, gateway):
|
||||
""" called when gateway is being exited. """
|
||||
|
||||
def pyevent__gwmanage_rsyncstart(self, source, gateways):
|
||||
""" called before rsyncing a directory to remote gateways takes place. """
|
||||
|
||||
def pyevent__gwmanage_rsyncfinish(self, source, gateways):
|
||||
""" called after rsyncing a directory to remote gateways takes place. """
|
||||
|
||||
def pyevent__trace(self, category, msg):
|
||||
""" called for tracing events. """
|
||||
|
||||
|
|
|
@ -11,12 +11,12 @@ class ExecnetcleanupPlugin:
|
|||
if self._debug:
|
||||
print "[execnetcleanup %0x] %s %s" %(id(self), msg, args)
|
||||
|
||||
def pyevent__gateway_init(self, gateway):
|
||||
def pyexecnet_gateway_init(self, gateway):
|
||||
self.trace("init", gateway)
|
||||
if self._gateways is not None:
|
||||
self._gateways.append(gateway)
|
||||
|
||||
def pyevent__gateway_exit(self, gateway):
|
||||
def pyexecnet_gateway_exit(self, gateway):
|
||||
self.trace("exit", gateway)
|
||||
if self._gateways is not None:
|
||||
self._gateways.remove(gateway)
|
||||
|
|
|
@ -86,18 +86,18 @@ class TerminalReporter:
|
|||
for line in str(excrepr).split("\n"):
|
||||
self.write_line("INTERNALERROR> " + line)
|
||||
|
||||
def pyevent__gwmanage_newgateway(self, gateway, rinfo):
|
||||
def pyexecnet_gwmanage_newgateway(self, gateway, platinfo):
|
||||
#self.write_line("%s instantiated gateway from spec %r" %(gateway.id, gateway.spec._spec))
|
||||
d = {}
|
||||
d['version'] = repr_pythonversion(rinfo.version_info)
|
||||
d['version'] = repr_pythonversion(platinfo.version_info)
|
||||
d['id'] = gateway.id
|
||||
d['spec'] = gateway.spec._spec
|
||||
d['platform'] = rinfo.platform
|
||||
d['platform'] = platinfo.platform
|
||||
if self.config.option.verbose:
|
||||
d['extra'] = "- " + rinfo.executable
|
||||
d['extra'] = "- " + platinfo.executable
|
||||
else:
|
||||
d['extra'] = ""
|
||||
d['cwd'] = rinfo.cwd
|
||||
d['cwd'] = platinfo.cwd
|
||||
infoline = ("%(id)s %(spec)s -- platform %(platform)s, "
|
||||
"Python %(version)s "
|
||||
"cwd: %(cwd)s"
|
||||
|
@ -105,14 +105,14 @@ class TerminalReporter:
|
|||
self.write_line(infoline)
|
||||
self.gateway2info[gateway] = infoline
|
||||
|
||||
def pyevent__gwmanage_rsyncstart(self, source, gateways):
|
||||
def pyexecnet_gwmanage_rsyncstart(self, source, gateways):
|
||||
targets = ", ".join([gw.id for gw in gateways])
|
||||
msg = "rsyncstart: %s -> %s" %(source, targets)
|
||||
if not self.config.option.verbose:
|
||||
msg += " # use --verbose to see rsync progress"
|
||||
self.write_line(msg)
|
||||
|
||||
def pyevent__gwmanage_rsyncfinish(self, source, gateways):
|
||||
def pyexecnet_gwmanage_rsyncfinish(self, source, gateways):
|
||||
targets = ", ".join([gw.id for gw in gateways])
|
||||
self.write_line("rsyncfinish: %s -> %s" %(source, targets))
|
||||
|
||||
|
@ -460,17 +460,17 @@ class TestTerminal:
|
|||
executable = "hello"
|
||||
platform = "xyz"
|
||||
cwd = "qwe"
|
||||
|
||||
rep.pyevent__gwmanage_newgateway(gw1, rinfo)
|
||||
|
||||
rep.pyexecnet_gwmanage_newgateway(gw1, rinfo)
|
||||
linecomp.assert_contains_lines([
|
||||
"X1*popen*xyz*2.5*"
|
||||
])
|
||||
|
||||
rep.pyevent__gwmanage_rsyncstart(source="hello", gateways=[gw1, gw2])
|
||||
rep.pyexecnet_gwmanage_rsyncstart(source="hello", gateways=[gw1, gw2])
|
||||
linecomp.assert_contains_lines([
|
||||
"rsyncstart: hello -> X1, X2"
|
||||
])
|
||||
rep.pyevent__gwmanage_rsyncfinish(source="hello", gateways=[gw1, gw2])
|
||||
rep.pyexecnet_gwmanage_rsyncfinish(source="hello", gateways=[gw1, gw2])
|
||||
linecomp.assert_contains_lines([
|
||||
"rsyncfinish: hello -> X1, X2"
|
||||
])
|
||||
|
|
Loading…
Reference in New Issue