[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:
hpk 2009-04-08 19:50:14 +02:00
parent 92a06c3787
commit 66c64e6b97
8 changed files with 79 additions and 70 deletions

View File

@ -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'),

View File

@ -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

View File

@ -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:

View File

@ -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.")

View File

@ -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

View File

@ -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. """

View File

@ -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)

View File

@ -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"
])