# encoding: utf-8 from . import repl from queue import Queue import sys import execnet REMOTE_CODE = """ from __future__ import with_statement from __future__ import division from __future__ import absolute_import #if '{activate_file}': # execfile('{activate_file}', dict(__file__='{activate_file}')) import code import sys import time import contextlib import threading try: from Queue import Queue except ImportError: from queue import Queue # py3 class ChannelOut(object): def write(self, data): channel.send(data) def flush(self): pass @contextlib.contextmanager def redirect_stdio(): orig = (sys.stdout, sys.stderr) sys.stdout = sys.stderr = ChannelOut() yield (sys.stdout, sys.stderr) = orig class InterceptingConsole(code.InteractiveConsole): PS1 = "{ps1}" PS2 = "... " def __init__(self): code.InteractiveConsole.__init__(self) self.input = Queue() self.output = channel self.output.send(self.PS1) def write(self, data): self.output.send(data) def push(self, line): with redirect_stdio(): more = code.InteractiveConsole.push(self, line) self.output.send(self.PS2 if more else self.PS1) return more def run(self): while True: line = self.input.get() if line is None: break self.push(line) ic = InterceptingConsole() _thread = threading.Thread(target=ic.run) _thread.start() channel.setcallback(ic.input.put, endmarker=None) while not channel.isclosed(): time.sleep(1.0) """ class ExecnetRepl(repl.Repl): TYPE = "execnet_repl" def __init__(self, encoding, connection_string=None, activate_file="", ps1=">>> "): super(ExecnetRepl, self).__init__(encoding, "python", "\n", False) self._connections_string = connection_string self._ps1 = ps1 self._gw = execnet.makegateway(connection_string) remote_code = REMOTE_CODE.format(ps1=ps1, activate_file=activate_file) self._channel = self._gw.remote_exec(remote_code) self.output = Queue() self._channel.setcallback(self.output.put, endmarker=None) self._alive = True self._killed = False def name(self): return "execnet " + self._ps1.split()[0] def is_alive(self): return self._alive def write_bytes(self, bytes): if self._channel.isclosed(): self._alive = False else: self._channel.send(bytes) def read_bytes(self): bytes = self.output.get() if bytes is None: self._gw.exit() else: return bytes def kill(self): self._killed = True self._channel.close() self._gw.exit()