def delocalize(self, x): # This is what we call for sending things to a different thread. # It is only applied to leaf nodes (via rmap). # rmap copies but it should actually be possible to change # only the leaf nodes that need to change because while a call # is in progress nothing can happen to variables referenced # only in the suspended stack-frame. If variables are added to # self then it would be possible for a call to access them # from the original vat's thread at the same time that they are # being accessed in the other thread. if isinstance(x, Exception): return x typ = type(x) if typ in POD_TYPES: return x if typ is Proxy: return Proxy(x._node, x._path) if typ is not Ref: try: ref = x.ref except AttributeError: pass else: # Should we be checking in case ref is not a Ref? if type(ref) is Ref: x = ref typ = Ref else: print 'unexpected .ref attribute', repr(x), x.ref if typ is Ref: return Proxy(self.node_id, x._path) raise SerializationError('cannot delocalize type %s' % typ)
def testSlaveAndObserverChangesAreSaved(self): store = TestStore() data = Data({}) data.ref = store sync = Synchronous() saver = AutoSave(data, sync) data.change_obs._add(saver) data['name'] = 'Fred' self.assertEqual(store.count, 1) # Add observer data.obs._add(Proxy('A', 'obs')) self.assertEqual(store.count, 2) # Call slave update methods. data.add(['age'], 42) self.assertEqual(store.count, 3) data.change(['name'], 'Fred', 'Barney') self.assertEqual(store.count, 4) data.delete(['age'], 42) self.assertEqual(store.count, 5) # Remove observer data.obs._remove(Proxy('A', 'obs')) self.assertEqual(store.count, 6) self.assertEqual(len(data.obs.group), 0)
def makeProxy(vat, data): """Rehydrates an incoming Proxy.""" node, path = data.get('n', 'browser'), data['o'] if node == vat.node_id and path in vat.storage: return vat.storage[path] proxy = Proxy(node, path, vat) vat.refs.append(proxy) return proxy
def localize(self, x): if isinstance(x, Exception): return x typ = type(x) if typ in POD_TYPES: return x if typ is Proxy: if x._node == self.node_id: return Ref(self.storage, x._path) return Proxy(x._node, x._path, self) raise SerializationError('cannot localize type %s' % typ)
def custom(self, name, data): if name == 'ref': node = data['node'] if node == self.node_id: return Ref(self.vat().storage, data['path']) if node == '-': node = self.msg_data.get('from') return Proxy(node, data['path'], self.vat()) if name == 'exc': return decodeException(data) if name == 'inst' and self._safe_cls(data['CLS']): cls = importSymbol(data['CLS']) try: args = [data[key.lstrip('_')] for key in cls.serialize] except KeyError: raise SerializationError(name + ': ' + repr(data)) else: return cls(*args) raise SerializationError(name)
def testProxyEquality(self): va0 = RPCHandler(MockTransport('A'), {}) va1 = RPCHandler(MockTransport('A'), {}) vb0 = RPCHandler(MockTransport('B'), {}) p1 = Proxy('B', 'x', va0) p2 = Proxy('B', 'y', va1) p3 = Proxy('B', 'y', va0) p4 = Proxy('A', 'x', vb0) p5 = Proxy('A', 'y', vb0) p6 = Proxy('A', 'y', vb0) self.assertNotEqual(p1, p2) self.assertEqual(p2, p3) # only node and path are compared self.assertNotEqual(p1, p3) self.assertNotEqual(p1, p4) self.assertNotEqual(p3, p4) self.assertEqual(p5, p6)
def provide(self, addr, obj): self.storage[addr] = obj return Proxy(self.node_id, addr, self)
def makeProxy(self, path, node=None): return Proxy(node or self.node_id, path, self)
def proxy(name): return REPLProxy(Proxy(SERVER, name, rpc), thread)