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