1__all__ = ['ConsoleReactor'] 2 3import sys 4from netrepr import NetRepr, RemoteObjectPool, RemoteObjectReference 5from Foundation import * 6 7class ConsoleReactor(NSObject): 8 9 def init(self): 10 self = super(ConsoleReactor, self).init() 11 self.pool = None 12 self.netReprCenter = None 13 self.connection = None 14 self.commands = {} 15 return self 16 17 def connectionEstablished_(self, connection): 18 #NSLog(u'connectionEstablished_') 19 self.connection = connection 20 self.pool = RemoteObjectPool(self.writeCode_) 21 self.netReprCenter = NetRepr(self.pool) 22 23 def connectionClosed_(self, connection): 24 #NSLog(u'connectionClosed_') 25 self.connection = None 26 self.pool = None 27 self.netReprCenter = None 28 29 def writeCode_(self, code): 30 #NSLog(u'writeCode_') 31 self.connection.writeBytes_(repr(code) + '\n') 32 33 def netEval_(self, s): 34 #NSLog(u'netEval_') 35 return eval(s, self.pool.namespace, self.pool.namespace) 36 37 def lineReceived_fromConnection_(self, lineReceived, connection): 38 #NSLog(u'lineReceived_fromConnection_') 39 code = lineReceived.rstrip() 40 if not code: 41 return 42 self.pool.push() 43 command = map(self.netEval_, eval(code)) 44 try: 45 self.handleCommand_(command) 46 finally: 47 self.pool.pop() 48 49 def handleCommand_(self, command): 50 #NSLog(u'handleCommand_') 51 basic = command[0] 52 sel = 'handle%sCommand:' % (basic.capitalize()) 53 cmd = command[1:] 54 if not self.respondsToSelector_(sel): 55 NSLog(u'%r does not respond to %s', self, command) 56 else: 57 # XXX - this crashes PyObjC?? 58 # self.performSelector_withObject_(sel, cmd) 59 getattr(self, sel.replace(':', '_'))(cmd) 60 61 def handleRespondCommand_(self, command): 62 self.doCallback_sequence_args_( 63 self.commands.pop(command[0]), 64 command[0], 65 map(self.netEval_, command[1:]), 66 ) 67 68 def sendResult_sequence_(self, rval, seq): 69 nr = self.netReprCenter 70 code = '__result__[%r] = %s' % (seq, nr.netrepr(rval)) 71 self.writeCode_(code) 72 73 def sendException_sequence_(self, e): 74 nr = self.netReprCenter 75 code = 'raise ' + nr.netrepr_exception(e) 76 print "forwarding:", code 77 self.writeCode_(code) 78 79 def doCallback_sequence_args_(self, callback, seq, args): 80 nr = self.netReprCenter 81 try: 82 rval = callback(*args) 83 except Exception, e: 84 self.sendException_sequence_(e, seq) 85 else: 86 self.sendResult_sequence_(rval, seq) 87 88 def deferCallback_sequence_value_(self, callback, seq, value): 89 self.commands[seq] = callback 90 self.writeCode_('pipe.respond(%r, netrepr(%s))' % (seq, value)) 91 92 def handleExpectCommand_(self, command): 93 #NSLog(u'handleExpectCommand_') 94 seq = command[0] 95 name = command[1] 96 args = command[2:] 97 netrepr = self.netReprCenter.netrepr 98 rval = None 99 code = None 100 if name == 'RemoteConsole.raw_input': 101 self.doCallback_sequence_args_(raw_input, seq, args) 102 elif name == 'RemoteConsole.write': 103 self.doCallback_sequence_args_(sys.stdout.write, seq, args) 104 elif name == 'RemoteConsole.displayhook': 105 obj = args[0] 106 def displayhook_respond(reprobject): 107 print reprobject 108 def displayhook_local(obj): 109 if obj is not None: 110 displayhook_respond(repr(obj)) 111 if isinstance(obj, RemoteObjectReference): 112 self.deferCallback_sequence_value_(displayhook_respond, seq, 'repr(%s)' % (netrepr(obj),)) 113 else: 114 self.doCallback_sequence_args_(displayhook_local, seq, args) 115 elif name.startswith('RemoteFileLike.'): 116 fh = getattr(sys, args[0]) 117 meth = getattr(fh, name[len('RemoteFileLike.'):]) 118 self.doCallback_sequence_args_(meth, seq, args[1:]) 119 elif name == 'RemoteConsole.initialize': 120 self.doCallback_sequence_args_(lambda *args:None, seq, args) 121 else: 122 self.doCallback_sequence_args_(NSLog, seq, [u'%r does not respond to expect %r', self, command,]) 123 124 def close(self): 125 if self.connection is not None: 126 self.writeCode_('raise SystemExit') 127 self.pool = None 128 self.netReprCenter = None 129 self.connection = None 130 self.commands = None 131