@@ -0,0 +1,1958 @@
+import time%0A%0Aclass TimeoutError(Exception):%0A    pass%0A%0Aclass RemoteError(Exception):%0A    pass%0A%0Aclass RemoteFunction:%0A    def __init__(self, sender, seq, name, timeout=5, timeoutCb = None):%0A        self.sender = sender%0A        self.seq = seq%0A        self.name = name%0A        self.timeout = timeout%0A        self.timeoutCb = timeoutCb%0A        self.result = None%0A%0A    def __call__(self, *args, **kwargs):%0A        obj = %7B%0A            %22seq%22: self.seq,%0A            %22op%22: self.name,%0A            %22args%22: args,%0A            %22kwargs%22: kwargs%0A        %7D%0A%0A        self.sender.send(obj)%0A%0A        start = time.time()%0A        while True:%0A            if self.result:%0A                if %22error%22 in self.result:%0A                    raise RemoteError(self.result%5B%22error%22%5D)%0A                else:%0A                    return self.result%5B%22result%22%5D%0A            if time.time() - start %3E= self.timeout:%0A                if self.timeoutCb:%0A                    self.timeoutCb(self.seq)%0A                raise TimeoutError%0A            time.sleep(.005)%0A%0Aclass RemoteFunctionCaller:%0A    def __init__(self, sender, timeout=5):%0A        self.sender = sender%0A        self.sender.listeners.append(self.dataReceived)%0A%0A        self.timeout = timeout%0A        self.seqnum = 0%0A        self.calls = %7B%7D%0A%0A    def functionTimeout(self, seq):%0A        if seq in self.calls:%0A            del self.calls%5Bseq%5D%0A%0A    def __getattr__(self, name):%0A        # Need to lock on seqnum if used by multiple threads%0A        self.seqnum += 1%0A        rf = RemoteFunction(self.sender, self.seqnum, name,%0A                            timeout=self.timeout, timeoutCb=self.functionTimeout)%0A        self.calls%5Bself.seqnum%5D = rf%0A        return rf%0A%0A    def dataReceived(self, data):%0A        print(%22Got data%22, data)%0A        if %22seq%22 in data:%0A            if data%5B%22seq%22%5D in self.calls:%0A                self.calls%5Bdata%5B%22seq%22%5D%5D.result = data%0A                self.calls.remove(data%5B%22seq%22%5D)%0A%0A    def destroy(self):%0A        self.sender.close()%0A

Add class for transparently calling functions over a socket