def record(self, data): cls = data.__class__ if self.auto_proxy is not None: path = self.auto_proxy(data) if path is not None: return self._autoProxy(path, data) ref = getattr(data, 'ref', None) if type(ref) is Ref: data = ref if hasattr(data, '_ext_encoding'): return data._ext_encoding() serialize = getattr(cls, 'serialize', None) if type(serialize) is tuple: name = cls.__name__ value = [] for key in serialize: if key.startswith('#'): raise SerializationError('local resources used: ' + cls.__name__) value.append(getattr(data, key, None)) return name, value raise SerializationError('cannot serialize: ' + cls.__name__)
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 record(self, inst): t = type(inst) if isinstance(inst, Exception): return 'exc', encodeException(inst) ref = getattr(inst, 'ref', None) if type(ref) is Ref: t, inst = Ref, ref if t is Ref and not inst._facet: # TODO: make a slot property for storing facet ref slots. return 'ref', {'path': inst._path, 'node': self.node_id} if t is Proxy: return 'ref', {'path': inst._path, 'node': inst._node} # Serialize instances without any capability members. s_attrs = getattr(t, 'serialize', None) if type(s_attrs) is tuple and not [ a for a in s_attrs if a.startswith('_') ]: data = dict([(key.lstrip('_'), getattr(inst, key)) for key in s_attrs]) cls = inst.__class__ data['CLS'] = '%s.%s' % (cls.__module__, cls.__name__) return 'inst', data raise SerializationError(str(t))
def custom(self, name, value): # FIXME: have we set up the full serializability code # below only to use hooks here instead for stuff like QTerm? if name in self.hooks: return self.hooks[name](self.rpc(), value) if not self._safe_cls(name): raise SerializationError('Unsafe type: ' + name) cls = importSymbol(name) try: args = [value[key] for key in cls.serialize] except KeyError: raise SerializationError(name + ': ' + repr(data)) else: return cls(*args)
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 record(self, inst): cls = type(inst) # Replace any instance having a slot somewhere with its Ref. ref = getattr(inst, 'ref', None) if type(ref) is Ref and ref._path != self.path: cls, inst = Ref, ref if cls is Ref: data = {'path': inst._path} if inst._facet: data['facet'] = inst._facet return 'ref', data if type(getattr(cls, 'serialize', None)) is tuple: data = getDict(inst) data['CLS'] = '%s.%s' % (cls.__module__, cls.__name__) version = getattr(cls, '_version', None) if version: data['$version'] = version if hasattr(cls, '_save'): inst._save = self.save return 'inst', data raise SerializationError(str(cls))
def custom(self, name, data): storage = self.storage() if name == 'ref': return Ref(storage, data['path'], data.get('facet')) if name == 'inst': cls = importSymbol(storage.map_class(data['CLS'])) data['#vat'] = storage data.update(storage.resources) # Check for version change. data_version = data.get('$version', 0) cls_version = getattr(cls, '_version', 0) if cls_version != data_version: cls._upgrade(data, data_version) args = [data.get(key.lstrip('_')) for key in cls.serialize] inst = cls(*args) if cls_version != data_version: # Ensure new nested serializables get correct _save hook. encodes(inst, self) if hasattr(cls, '_save'): inst._save = self.save return inst raise SerializationError(name)