diff --git a/py/__init__.py b/py/__init__.py index 9de9c5fbb..b00a7bb5d 100644 --- a/py/__init__.py +++ b/py/__init__.py @@ -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'), diff --git a/py/_com.py b/py/_com.py index cb9b2fb1d..3a27a9eee 100644 --- a/py/_com.py +++ b/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 diff --git a/py/execnet/gateway.py b/py/execnet/gateway.py index de5e354f3..8bdf0467e 100644 --- a/py/execnet/gateway.py +++ b/py/execnet/gateway.py @@ -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: diff --git a/py/execnet/gwmanage.py b/py/execnet/gwmanage.py index eb89654c0..08b2f9a34 100644 --- a/py/execnet/gwmanage.py +++ b/py/execnet/gwmanage.py @@ -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.") diff --git a/py/execnet/testing/test_gwmanage.py b/py/execnet/testing/test_gwmanage.py index 94a607c99..6abb3eea8 100644 --- a/py/execnet/testing/test_gwmanage.py +++ b/py/execnet/testing/test_gwmanage.py @@ -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 diff --git a/py/test/plugin/api.py b/py/test/plugin/api.py index a8d51a857..de6fe5ddf 100644 --- a/py/test/plugin/api.py +++ b/py/test/plugin/api.py @@ -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. """ diff --git a/py/test/plugin/pytest_execnetcleanup.py b/py/test/plugin/pytest_execnetcleanup.py index 147ff3efa..69d6ace1a 100644 --- a/py/test/plugin/pytest_execnetcleanup.py +++ b/py/test/plugin/pytest_execnetcleanup.py @@ -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) diff --git a/py/test/plugin/pytest_terminal.py b/py/test/plugin/pytest_terminal.py index 9867c0767..392b0202c 100644 --- a/py/test/plugin/pytest_terminal.py +++ b/py/test/plugin/pytest_terminal.py @@ -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" ])