class AbstractProtocol(object): immutable_primitives = (str, int, float, long, unicode, bool, types.NotImplementedType) mutable_primitives = (list, dict, types.FunctionType, types.FrameType, types.TracebackType, types.CodeType) exc_dir = dict((val, name) for name, val in exceptions.__dict__.iteritems()) letter_types = { 'l' : list, 'd' : dict, 'c' : types.CodeType, 't' : tuple, 'e' : Exception, 'ex': exceptions, # for instances 'i' : int, 'b' : bool, 'f' : float, 'u' : unicode, 'l' : long, 's' : str, 'ni' : types.NotImplementedType, 'n' : types.NoneType, 'lst' : list, 'fun' : types.FunctionType, 'cus' : object, 'meth' : types.MethodType, 'type' : type, 'tp' : None, 'fr' : types.FrameType, 'tb' : types.TracebackType, 'reg' : RemoteBase, 'get' : NonDataDescriptor, 'set' : DataDescriptor, } type_letters = dict([(value, key) for key, value in letter_types.items()]) assert len(type_letters) == len(letter_types) def __init__(self, exported_names={}): self.keeper = ObjKeeper(exported_names) #self.remote_objects = {} # a dictionary controller --> id #self.objs = [] # we just store everything, maybe later # # we'll need some kind of garbage collection def wrap(self, obj): """ Wrap an object as sth prepared for sending """ def is_element(x, iterable): try: return x in iterable except (TypeError, ValueError): return False tp = type(obj) ctrl = get_tproxy_controller(obj) if ctrl: return "tp", self.keeper.get_remote_object(ctrl) elif obj is None: return self.type_letters[tp] elif tp in self.immutable_primitives: # simple, immutable object, just copy return (self.type_letters[tp], obj) elif hasattr(obj, '__class__') and obj.__class__ in self.exc_dir: return (self.type_letters[Exception], (self.exc_dir[obj.__class__], \ self.wrap(obj.args))) elif is_element(obj, self.exc_dir): # weird hashing problems return (self.type_letters[exceptions], self.exc_dir[obj]) elif tp is tuple: # we just pack all of the items return ('t', tuple([self.wrap(elem) for elem in obj])) elif tp in self.mutable_primitives: id = self.keeper.register_object(obj) return (self.type_letters[tp], id) elif tp is type: try: return "reg", self.keeper.reverse_remote_types[obj] except KeyError: pass try: return self.type_letters[tp], self.type_letters[obj] except KeyError: id = self.register_type(obj) return (self.type_letters[tp], id) elif tp is types.MethodType: w_class = self.wrap(obj.im_class) w_func = self.wrap(obj.im_func) w_self = self.wrap(obj.im_self) return (self.type_letters[tp], (w_class, \ self.wrap(obj.im_func.func_name), w_func, w_self)) else: id = self.keeper.register_object(obj) w_tp = self.wrap(tp) return ("cus", (w_tp, id)) def unwrap(self, data): """ Unwrap an object """ if data == 'n': return None tp_letter, obj_data = data tp = self.letter_types[tp_letter] if tp is None: return self.keeper.get_object(obj_data) elif tp is RemoteBase: return self.keeper.exported_types_reverse[obj_data] elif tp in self.immutable_primitives: return obj_data # this is the object elif tp is tuple: return tuple([self.unwrap(i) for i in obj_data]) elif tp in self.mutable_primitives: id = obj_data ro = RemoteBuiltinObject(self, id) self.keeper.register_remote_object(ro.perform, id) p = proxy(tp, ro.perform) ro.obj = p return p elif tp is Exception: cls_name, w_args = obj_data return getattr(exceptions, cls_name)(self.unwrap(w_args)) elif tp is exceptions: cls_name = obj_data return getattr(exceptions, cls_name) elif tp is types.MethodType: w_class, w_name, w_func, w_self = obj_data tp = self.unwrap(w_class) name = self.unwrap(w_name) self_ = self.unwrap(w_self) if self_ is not None: if tp is None: setattr(self_, name, classmethod(self.unwrap(w_func))) return getattr(self_, name) return getattr(tp, name).__get__(self_, tp) func = self.unwrap(w_func) setattr(tp, name, func) return getattr(tp, name) elif tp is type: if isinstance(obj_data, str): return self.letter_types[obj_data] id = obj_data return self.get_type(obj_data) elif tp is DataDescriptor: return faker.unwrap_getset_descriptor(self, obj_data) elif tp is NonDataDescriptor: return faker.unwrap_get_descriptor(self, obj_data) elif tp is object: # we need to create a proper type w_tp, id = obj_data real_tp = self.unwrap(w_tp) ro = RemoteObject(self, id) self.keeper.register_remote_object(ro.perform, id) p = proxy(real_tp, ro.perform) ro.obj = p return p else: raise NotImplementedError("Cannot unwrap %s" % (data,)) def perform(self, *args, **kwargs): raise NotImplementedError("Abstract only protocol") # some simple wrappers def pack_args(self, args, kwargs): return self.pack_list(args), self.pack_dict(kwargs) def pack_list(self, lst): return [self.wrap(i) for i in lst] def pack_dict(self, d): return dict([(self.wrap(key), self.wrap(val)) for key, val in d.items()]) def unpack_args(self, args, kwargs): return self.unpack_list(args), self.unpack_dict(kwargs) def unpack_list(self, lst): return [self.unwrap(i) for i in lst] def unpack_dict(self, d): return dict([(self.unwrap(key), self.unwrap(val)) for key, val in d.items()]) def register_type(self, tp): return self.keeper.register_type(self, tp) def get_type(self, id): return self.keeper.get_type(id)
def __init__(self, exported_names={}): self.keeper = ObjKeeper(exported_names)