1try: 2 import fcntl 3except: 4 fcntl = None 5import os 6import sys 7from subprocess import Popen, PIPE 8import socket 9from StringIO import StringIO 10from netrepr import NetRepr, RemoteObjectPool, RemoteObjectReference 11 12IMPORT_MODULES = ['netrepr', 'remote_console', 'remote_pipe', 'remote_bootstrap'] 13source = StringIO() 14for fn in IMPORT_MODULES: 15 for line in file(fn+'.py', 'rU'): 16 source.write(line) 17 source.write('\n\n') 18SOURCE = repr(source.getvalue()) + '\n' 19 20def ensure_utf8(s): 21 if isinstance(s, unicode): 22 s = s.encode('utf-8') 23 return s 24 25def bind_and_listen(hostport): 26 if isinstance(hostport, str): 27 host, port = hostport.split(':') 28 hostport = (host, int(port)) 29 serversock = socket.socket(socket.AF_INET, socket.SOCK_STREAM) 30 # set close-on-exec 31 if hasattr(fcntl, 'FD_CLOEXEC'): 32 old = fcntl.fcntl(serversock.fileno(), fcntl.F_GETFD) 33 fcntl.fcntl(serversock.fileno(), fcntl.F_SETFD, old | fcntl.FD_CLOEXEC) 34 # allow the address to be re-used in a reasonable amount of time 35 if os.name == 'posix' and sys.platform != 'cygwin': 36 serversock.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1) 37 38 serversock.bind(hostport) 39 serversock.listen(5) 40 return serversock 41 42def open_connection(executable=sys.executable): 43 serversock = bind_and_listen(('127.0.0.1', 0)) 44 hostport = serversock.getsockname() 45 proc = Popen([executable, 'tcpinterpreter.py', repr(hostport)], stdin=PIPE, stdout=PIPE, stderr=PIPE, close_fds=True) 46 clientsock, address = serversock.accept() 47 serversock.shutdown(2) 48 return clientsock, proc 49 50def start_client(clientsock): 51 f = clientsock.makefile('r+b', 0) 52 f.write(SOURCE) 53 f.flush() 54 return f 55 56def client_loop(f): 57 def writecode(code): 58 #print '[code: %r]' % (code,) 59 f.write(repr(code) + '\n') 60 pool = RemoteObjectPool(writecode) 61 netRepr = NetRepr(pool) 62 netrepr = netRepr.netrepr 63 def neteval(s): 64 return eval(s, pool.namespace, pool.namespace) 65 while True: 66 code = f.readline().rstrip() 67 pool.push() 68 try: 69 if not code: 70 break 71 command = eval(code) 72 basic = eval(command[0]) 73 if basic == 'expect': 74 seq = eval(command[1]) 75 name = eval(command[2]) 76 args = map(neteval, command[3:]) 77 code = None 78 rval = None 79 if name == 'RemoteConsole.raw_input': 80 try: 81 rval = raw_input(*args) 82 except EOFError: 83 code = 'raise EOFError' 84 elif name == 'RemoteConsole.write': 85 sys.stdout.write(ensure_utf8(args[0])) 86 elif name == 'RemoteConsole.displayhook': 87 pass 88 obj = args[0] 89 if obj is None: 90 pass 91 elif isinstance(obj, RemoteObjectReference): 92 writecode('interp.write(repr(%s) + "\\n")' % (netrepr(obj),)) 93 else: 94 print repr(obj) 95 elif name.startswith('RemoteFileLike.'): 96 fh = getattr(sys, args[0]) 97 meth = getattr(fh, name[len('RemoteFileLike.'):]) 98 rval = meth(*map(ensure_utf8, args[1:])) 99 else: 100 print name, args 101 if code is None: 102 code = '__result__[%r] = %r' % (seq, rval) 103 writecode(code) 104 finally: 105 pool.pop() 106 107def main(): 108 clientsock, proc = open_connection() 109 f = start_client(clientsock) 110 try: 111 client_loop(f) 112 finally: 113 f.close() 114 clientsock.close() 115 proc.stdin.close() 116 print '[stdout]', proc.stdout.read() 117 print '[stderr]', proc.stderr.read() 118 119if __name__ == '__main__': 120 main() 121