* simplify stdout/stderr handling and modules and for now remove support
for directly stdout/stderr directly on remote_exec --HG-- branch : trunk
This commit is contained in:
		
							parent
							
								
									73fc2f01f2
								
							
						
					
					
						commit
						6c3e961bc5
					
				|  | @ -9,7 +9,6 @@ from py.__.execnet.gateway_base import ExecnetAPI | |||
| # XXX we'd like to have a leaner and meaner bootstrap mechanism  | ||||
| 
 | ||||
| startup_modules = [ | ||||
|     'py.__.thread.io',  | ||||
|     'py.__.execnet.gateway_base',  | ||||
| ] | ||||
| 
 | ||||
|  | @ -48,7 +47,7 @@ class InitiatingGateway(BaseGateway): | |||
|         self._remote_bootstrap_gateway(io) | ||||
|         super(InitiatingGateway, self).__init__(io=io, _startcount=1)  | ||||
|         # XXX we dissallow execution form the other side | ||||
|         self._initreceive(requestqueue=False)  | ||||
|         self._initreceive() | ||||
|         self.hook = py._com.HookRelay(ExecnetAPI, py._com.comregistry) | ||||
|         self.hook.pyexecnet_gateway_init(gateway=self) | ||||
|         self._cleanup.register(self)  | ||||
|  | @ -103,20 +102,15 @@ class InitiatingGateway(BaseGateway): | |||
|             self._cache_rinfo = RInfo(**ch.receive()) | ||||
|         return self._cache_rinfo | ||||
| 
 | ||||
|     def remote_exec(self, source, stdout=None, stderr=None):  | ||||
|     def remote_exec(self, source):  | ||||
|         """ return channel object and connect it to a remote | ||||
|             execution thread where the given 'source' executes | ||||
|             and has the sister 'channel' object in its global  | ||||
|             namespace.  The callback functions 'stdout' and  | ||||
|             'stderr' get called on receival of remote  | ||||
|             stdout/stderr output strings.  | ||||
|             namespace. | ||||
|         """ | ||||
|         source = str(py.code.Source(source)) | ||||
|         channel = self.newchannel()  | ||||
|         outid = self._newredirectchannelid(stdout)  | ||||
|         errid = self._newredirectchannelid(stderr)  | ||||
|         self._send(Message.CHANNEL_OPEN( | ||||
|                     channel.id, (source, outid, errid))) | ||||
|         self._send(Message.CHANNEL_OPEN(channel.id, source)) | ||||
|         return channel  | ||||
| 
 | ||||
|     def remote_init_threads(self, num=None): | ||||
|  | @ -131,7 +125,7 @@ class InitiatingGateway(BaseGateway): | |||
|             execpool = WorkerPool(maxthreads=%r) | ||||
|             gw = channel.gateway | ||||
|             while 1: | ||||
|                 task = gw._requestqueue.get() | ||||
|                 task = gw._execqueue.get() | ||||
|                 if task is None: | ||||
|                     gw._stopsend() | ||||
|                     execpool.shutdown() | ||||
|  | @ -141,21 +135,13 @@ class InitiatingGateway(BaseGateway): | |||
|         """ % num) | ||||
|         self._remotechannelthread = self.remote_exec(source) | ||||
| 
 | ||||
|     def _newredirectchannelid(self, callback):  | ||||
|         if callback is None:  | ||||
|             return   | ||||
|         if hasattr(callback, 'write'):  | ||||
|             callback = callback.write  | ||||
|         assert callable(callback)  | ||||
|         chan = self.newchannel() | ||||
|         chan.setcallback(callback) | ||||
|         return chan.id  | ||||
| 
 | ||||
|     def _remote_redirect(self, stdout=None, stderr=None):  | ||||
|         """ return a handle representing a redirection of a remote  | ||||
|             end's stdout to a local file object.  with handle.close()  | ||||
|             the redirection will be reverted.    | ||||
|         """  | ||||
|         # XXX implement a remote_exec_in_globals(...) | ||||
|         #     to send ThreadOut implementation over  | ||||
|         clist = [] | ||||
|         for name, out in ('stdout', stdout), ('stderr', stderr):  | ||||
|             if out:  | ||||
|  | @ -164,7 +150,7 @@ class InitiatingGateway(BaseGateway): | |||
|                 channel = self.remote_exec("""  | ||||
|                     import sys | ||||
|                     outchannel = channel.receive()  | ||||
|                     outchannel.gateway._ThreadOut(sys, %r).setdefaultwriter(outchannel.send) | ||||
|                     ThreadOut(sys, %r).setdefaultwriter(outchannel.send) | ||||
|                 """ % name)  | ||||
|                 channel.send(outchannel) | ||||
|                 clist.append(channel) | ||||
|  |  | |||
|  | @ -18,11 +18,6 @@ try: | |||
| except ImportError: | ||||
|     import Queue as queue | ||||
| 
 | ||||
| # XXX the following lines should not be here | ||||
| if 'ThreadOut' not in globals():  | ||||
|     import py  | ||||
|     ThreadOut = py._thread.ThreadOut  | ||||
| 
 | ||||
| if sys.version_info > (3, 0): | ||||
|     exec("""def do_exec(co, loc): | ||||
|     exec(co, loc)""") | ||||
|  | @ -594,14 +589,14 @@ class ExecnetAPI: | |||
| 
 | ||||
|     def pyexecnet_gwmanage_rsyncfinish(self, source, gateways): | ||||
|         """ called after rsyncing a directory to remote gateways takes place. """ | ||||
| 
 | ||||
|          | ||||
| class BaseGateway(object): | ||||
|     hook = ExecnetAPI() | ||||
|     exc_info = sys.exc_info  | ||||
| 
 | ||||
|     class _StopExecLoop(Exception): pass | ||||
|     _ThreadOut = ThreadOut  | ||||
|     _requestqueue = None | ||||
|     class _StopExecLoop(Exception):  | ||||
|         pass | ||||
| 
 | ||||
|     def __init__(self, io, _startcount=2):  | ||||
|         """ initialize core gateway, using the given inputoutput object.  | ||||
|  | @ -610,9 +605,7 @@ class BaseGateway(object): | |||
|         self._channelfactory = ChannelFactory(self, _startcount) | ||||
|         self._receivelock = threading.RLock() | ||||
| 
 | ||||
|     def _initreceive(self, requestqueue=False): | ||||
|         if requestqueue:  | ||||
|             self._requestqueue = queue.Queue() | ||||
|     def _initreceive(self): | ||||
|         self._receiverthread = threading.Thread(name="receiver",  | ||||
|                                  target=self._thread_receiver) | ||||
|         self._receiverthread.setDaemon(1) | ||||
|  | @ -678,36 +671,23 @@ class BaseGateway(object): | |||
|         self._send(None) | ||||
| 
 | ||||
|     def _stopexec(self): | ||||
|         if self._requestqueue is not None: | ||||
|             self._requestqueue.put(None) | ||||
| 
 | ||||
|     def _local_redirect_thread_output(self, outid, errid):  | ||||
|         l = [] | ||||
|         for name, id in ('stdout', outid), ('stderr', errid):  | ||||
|             if id:  | ||||
|                 channel = self._channelfactory.new(outid) | ||||
|                 out = self._ThreadOut(sys, name) | ||||
|                 out.setwritefunc(channel.send)  | ||||
|                 l.append((out, channel)) | ||||
|         def close():  | ||||
|             for out, channel in l:  | ||||
|                 out.delwritefunc()  | ||||
|                 channel.close()  | ||||
|         return close  | ||||
|         if hasattr(self, '_execqueue'): | ||||
|             self._execqueue.put(None) | ||||
| 
 | ||||
|     def _local_schedulexec(self, channel, sourcetask): | ||||
|         if self._requestqueue is not None: | ||||
|             self._requestqueue.put((channel, sourcetask))  | ||||
|         if hasattr(self, '_execqueue'): | ||||
|             self._execqueue.put((channel, sourcetask))  | ||||
|         else: | ||||
|             # we will not execute, let's send back an error | ||||
|             # to inform the other side | ||||
|             channel.close("execution disallowed") | ||||
| 
 | ||||
|     def _servemain(self, joining=True): | ||||
|         self._initreceive(requestqueue=True) | ||||
|         self._execqueue = queue.Queue() | ||||
|         self._initreceive() | ||||
|         try: | ||||
|             while 1: | ||||
|                 item = self._requestqueue.get() | ||||
|                 item = self._execqueue.get() | ||||
|                 if item is None: | ||||
|                     self._stopsend() | ||||
|                     break | ||||
|  | @ -722,17 +702,15 @@ class BaseGateway(object): | |||
| 
 | ||||
|     def _executetask(self, item): | ||||
|         """ execute channel/source items. """ | ||||
|         channel, (source, outid, errid) = item  | ||||
|         channel, source = item  | ||||
|         try: | ||||
|             loc = { 'channel' : channel, '__name__': '__channelexec__'} | ||||
|             #open("task.py", 'w').write(source) | ||||
|             self._trace("execution starts: %s" % repr(source)[:50]) | ||||
|             close = self._local_redirect_thread_output(outid, errid)  | ||||
|             try: | ||||
|                 co = compile(source+'\n', '', 'exec') | ||||
|                 do_exec(co, loc) | ||||
|             finally: | ||||
|                 close()  | ||||
|                 self._trace("execution finished") | ||||
|         except sysex: | ||||
|             pass  | ||||
|  |  | |||
|  | @ -429,6 +429,7 @@ class BasicRemoteExecution: | |||
|         assert err | ||||
|         assert str(err).find("ValueError") != -1 | ||||
| 
 | ||||
|     @py.test.mark.xfail | ||||
|     def test_remote_redirect_stdout(self):  | ||||
|         out = py.io.TextIO()  | ||||
|         handle = self.gw._remote_redirect(stdout=out)  | ||||
|  | @ -438,6 +439,7 @@ class BasicRemoteExecution: | |||
|         s = out.getvalue()  | ||||
|         assert s.strip() == "42"  | ||||
| 
 | ||||
|     @py.test.mark.xfail | ||||
|     def test_remote_exec_redirect_multi(self):  | ||||
|         num = 3 | ||||
|         l = [[] for x in range(num)] | ||||
|  |  | |||
		Loading…
	
		Reference in New Issue