def _restore(self, obj): if has_tag(obj, tags.ID): restore = self._restore_id elif has_tag(obj, tags.REF): # Backwards compatibility restore = self._restore_ref elif has_tag(obj, tags.ITERATOR): restore = self._restore_iterator elif has_tag(obj, tags.TYPE): restore = self._restore_type elif has_tag(obj, tags.REPR): # Backwards compatibility restore = self._restore_repr elif has_tag(obj, tags.REDUCE): restore = self._restore_reduce elif has_tag(obj, tags.OBJECT): restore = self._restore_object elif has_tag(obj, tags.FUNCTION): restore = self._restore_function elif util.is_list(obj): restore = self._restore_list elif has_tag(obj, tags.TUPLE): restore = self._restore_tuple elif has_tag(obj, tags.SET): restore = self._restore_set elif util.is_dictionary(obj): restore = self._restore_dict else: restore = lambda x: x return restore(obj)
def _restore(self, obj): if has_tag(obj, tags.ID): restore = self._restore_id elif has_tag(obj, tags.REF): # Backwards compatibility restore = self._restore_ref elif has_tag(obj, tags.TYPE): restore = self._restore_type elif has_tag(obj, tags.REPR): # Backwards compatibility restore = self._restore_repr elif has_tag(obj, tags.OBJECT): restore = self._restore_object elif util.is_list(obj): restore = self._restore_list elif has_tag(obj, tags.TUPLE): restore = self._restore_tuple elif has_tag(obj, tags.SET): restore = self._restore_set elif util.is_dictionary(obj): restore = self._restore_dict else: restore = lambda x: x try: return restore(obj) except IndexError as e: raise e # for testing
def _restore(self, obj): if has_tag(obj, tags.B64): restore = self._restore_base64 elif has_tag(obj, tags.BYTES): # Backwards compatibility restore = self._restore_quopri elif has_tag(obj, tags.ID): restore = self._restore_id elif has_tag(obj, tags.REF): # Backwards compatibility restore = self._restore_ref elif has_tag(obj, tags.ITERATOR): restore = self._restore_iterator elif has_tag(obj, tags.TYPE): restore = self._restore_type elif has_tag(obj, tags.REPR): # Backwards compatibility restore = self._restore_repr elif has_tag(obj, tags.REDUCE): restore = self._restore_reduce elif has_tag(obj, tags.OBJECT): restore = self._restore_object elif has_tag(obj, tags.FUNCTION): restore = self._restore_function elif util.is_list(obj): restore = self._restore_list elif has_tag(obj, tags.TUPLE): restore = self._restore_tuple elif has_tag(obj, tags.SET): restore = self._restore_set elif util.is_dictionary(obj): restore = self._restore_dict else: restore = lambda x: x return restore(obj)
def _restore(self, obj, cls=None): restore = None # Try and restore from an explicit class if cls is not None: if util.is_type(cls): restore = self._restore_object_from_cls elif util.is_list(cls): restore = self._restore_list_from_cls elif util.is_dictionary(cls): restore = self._restore_dict_from_cls if restore is not None: return restore(obj, cls) # Try and restore from present tags if has_tag(obj, tags.B64): restore = self._restore_base64 elif has_tag(obj, tags.BYTES): # Backwards compatibility restore = self._restore_quopri elif has_tag(obj, tags.ID): restore = self._restore_id elif has_tag(obj, tags.REF): # Backwards compatibility restore = self._restore_ref elif has_tag(obj, tags.ITERATOR): restore = self._restore_iterator elif has_tag(obj, tags.TYPE): restore = self._restore_type elif has_tag(obj, tags.REPR): # Backwards compatibility restore = self._restore_repr elif has_tag(obj, tags.REDUCE): restore = self._restore_reduce elif has_tag(obj, tags.OBJECT): restore = self._restore_object_given_tag elif has_tag(obj, tags.FUNCTION): restore = self._restore_function elif util.is_list(obj): restore = self._restore_list_given_tag elif has_tag(obj, tags.TUPLE): restore = self._restore_tuple elif has_tag(obj, tags.SET): restore = self._restore_set elif util.is_dictionary(obj): restore = self._restore_dict_given_tag else: restore = lambda x: x return restore(obj)
def _get_flattener(self, obj): if PY2 and isinstance(obj, file): return self._flatten_file if util.is_primitive(obj): return lambda obj: obj if util.is_bytes(obj): return self._flatten_bytestring list_recurse = self._list_recurse if util.is_list(obj): if self._mkref(obj): return list_recurse else: self._push() return self._getref # We handle tuples and sets by encoding them in a "(tuple|set)dict" if util.is_tuple(obj): if not self.unpicklable: return list_recurse return lambda obj: {tags.TUPLE: [self._flatten(v) for v in obj]} if util.is_set(obj): if not self.unpicklable: return list_recurse return lambda obj: {tags.SET: [self._flatten(v) for v in obj]} if util.is_dictionary(obj): return self._flatten_dict_obj if util.is_type(obj): return _mktyperef if util.is_object(obj): return self._ref_obj_instance if util.is_module_function(obj): return self._flatten_function # instance methods, lambdas, old style classes... self._pickle_warning(obj) return None
def _get_flattener(self, obj): if util.is_primitive(obj): return lambda obj: obj list_recurse = self._list_recurse if util.is_list(obj): if self._mkref(obj): return list_recurse else: self._push() return self._getref # We handle tuples and sets by encoding them in a "(tuple|set)dict" if util.is_tuple(obj): if not self.unpicklable: return list_recurse return lambda obj: {tags.TUPLE: [self._flatten(v) for v in obj]} if util.is_set(obj): if not self.unpicklable: return list_recurse return lambda obj: {tags.SET: [self._flatten(v) for v in obj]} if util.is_dictionary(obj): return self._flatten_dict_obj if util.is_type(obj): return _mktyperef if util.is_object(obj): return self._ref_obj_instance # else, what else? (methods, functions, old style classes...) return None
def test_is_list_other(self): self.assertFalse(is_list(1)) self.assertFalse(is_set(1)) self.assertFalse(is_tuple(1))
def test_is_list_dict(self): self.assertFalse(is_list({'key':'value'})) self.assertFalse(is_set({'key':'value'})) self.assertFalse(is_tuple({'key':'value'}))
def test_is_list_list(self): self.assertTrue(is_list([1, 2]))
def flatten(self, obj): """Takes an object and returns a JSON-safe representation of it. Simply returns any of the basic builtin datatypes >>> p = Pickler() >>> p.flatten('hello world') 'hello world' >>> p.flatten(u'hello world') u'hello world' >>> p.flatten(49) 49 >>> p.flatten(350.0) 350.0 >>> p.flatten(True) True >>> p.flatten(False) False >>> r = p.flatten(None) >>> r is None True >>> p.flatten(False) False >>> p.flatten([1, 2, 3, 4]) [1, 2, 3, 4] >>> p.flatten((1,2,))[tags.TUPLE] [1, 2] >>> p.flatten({'key': 'value'}) {'key': 'value'} """ self._push() if self._depth == self._max_depth: return self._pop(repr(obj)) if util.is_primitive(obj): return self._pop(obj) if util.is_list(obj): return self._pop([self.flatten(v) for v in obj]) # We handle tuples and sets by encoding them in a "(tuple|set)dict" if util.is_tuple(obj): return self._pop({tags.TUPLE: [self.flatten(v) for v in obj]}) if util.is_set(obj): return self._pop({tags.SET: [self.flatten(v) for v in obj]}) if util.is_dictionary(obj): return self._pop(self._flatten_dict_obj(obj, obj.__class__())) if util.is_type(obj): return self._pop(_mktyperef(obj)) if util.is_object(obj): data = {} has_class = hasattr(obj, '__class__') has_dict = hasattr(obj, '__dict__') if self._mkref(obj): if has_class and not util.is_repr(obj): module, name = _getclassdetail(obj) if self.unpicklable is True: data[tags.OBJECT] = '%s.%s' % (module, name) if util.is_repr(obj): if self.unpicklable is True: data[tags.REPR] = '%s/%s' % (obj.__class__.__module__, repr(obj)) else: data = unicode(obj) return self._pop(data) if util.is_dictionary_subclass(obj): return self._pop(self._flatten_dict_obj(obj, data)) if util.is_noncomplex(obj): return self._pop([self.flatten(v) for v in obj]) if has_dict: return self._pop(self._flatten_dict_obj( obj.__dict__, data)) else: # We've seen this object before so place an object # reference tag in the data. This avoids infinite recursion # when processing cyclical objects. return self._pop(self._getref(obj)) return self._pop(data)
def restore(self, obj): """Restores a flattened object to its original python state. Simply returns any of the basic builtin types >>> u = Unpickler() >>> u.restore('hello world') 'hello world' >>> u.restore({'key': 'value'}) {'key': 'value'} """ self._push() if has_tag(obj, tags.REF): return self._pop(self._namedict.get(obj[tags.REF])) if has_tag(obj, tags.TYPE): typeref = loadclass(obj[tags.TYPE]) if not typeref: return self._pop(obj) return self._pop(typeref) if has_tag(obj, tags.REPR): return self._pop(loadrepr(obj[tags.REPR])) if has_tag(obj, tags.OBJECT): cls = loadclass(obj[tags.OBJECT]) if not cls: return self._pop(obj) try: instance = object.__new__(cls) except TypeError: # old-style classes try: instance = cls() except TypeError: # fail gracefully if the constructor requires arguments self._mkref(obj) return self._pop(obj) # keep a obj->name mapping for use in the _isobjref() case self._mkref(instance) for k, v in obj.iteritems(): # ignore the reserved attribute if k in tags.RESERVED: continue self._namestack.append(k) # step into the namespace value = self.restore(v) if (util.is_noncomplex(instance) or util.is_dictionary_subclass(instance)): instance[k] = value else: instance.__dict__[k] = value # step out self._namestack.pop() return self._pop(instance) if util.is_list(obj): return self._pop([self.restore(v) for v in obj]) if has_tag(obj, tags.TUPLE): return self._pop(tuple([self.restore(v) for v in obj[tags.TUPLE]])) if has_tag(obj, tags.SET): return self._pop(set([self.restore(v) for v in obj[tags.SET]])) if util.is_dictionary(obj): data = {} for k, v in obj.iteritems(): self._namestack.append(k) data[k] = self.restore(v) self._namestack.pop() return self._pop(data) return self._pop(obj)
def restore(self, obj): """Restores a flattened object to its original python state. Simply returns any of the basic builtin types >>> u = Unpickler() >>> u.restore('hello world') 'hello world' >>> u.restore({'key': 'value'}) {'key': 'value'} """ self._push() if has_tag(obj, tags.ID): return self._pop(self._objs[obj[tags.ID]]) # Backwards compatibility if has_tag(obj, tags.REF): return self._pop(self._namedict.get(obj[tags.REF])) if has_tag(obj, tags.TYPE): typeref = loadclass(obj[tags.TYPE]) if not typeref: return self._pop(obj) return self._pop(typeref) # Backwards compatibility if has_tag(obj, tags.REPR): obj = loadrepr(obj[tags.REPR]) return self._pop(self._mkref(obj)) if has_tag(obj, tags.OBJECT): cls = loadclass(obj[tags.OBJECT]) if not cls: return self._pop(self._mkref(obj)) # check custom handlers HandlerClass = handlers.registry.get(cls) if HandlerClass: handler = HandlerClass(self) instance = handler.restore(obj) return self._pop(self._mkref(instance)) factory = loadfactory(obj) args = getargs(obj) if args: args = self.restore(args) try: if hasattr(cls, '__new__'): # new style classes if factory: instance = cls.__new__(cls, factory, *args) instance.default_factory = factory else: instance = cls.__new__(cls, *args) else: instance = object.__new__(cls) except TypeError: # old-style classes try: instance = cls() except TypeError: # fail gracefully if the constructor requires arguments return self._pop(self._mkref(obj)) # Add to the instance table to allow being referenced by a # downstream object self._mkref(instance) if hasattr(instance, '__setstate__') and has_tag(obj, tags.STATE): state = self.restore(obj[tags.STATE]) instance.__setstate__(state) return self._pop(instance) for k, v in sorted(obj.items(), key=operator.itemgetter(0)): # ignore the reserved attribute if k in tags.RESERVED: continue self._namestack.append(k) # step into the namespace value = self.restore(v) if (util.is_noncomplex(instance) or util.is_dictionary_subclass(instance)): instance[k] = value else: setattr(instance, k, value) # step out self._namestack.pop() # Handle list and set subclasses if has_tag(obj, tags.SEQ): if hasattr(instance, 'append'): for v in obj[tags.SEQ]: instance.append(self.restore(v)) if hasattr(instance, 'add'): for v in obj[tags.SEQ]: instance.add(self.restore(v)) return self._pop(instance) if util.is_list(obj): parent = [] self._mkref(parent) children = [self.restore(v) for v in obj] parent.extend(children) return self._pop(parent) if has_tag(obj, tags.TUPLE): return self._pop(tuple([self.restore(v) for v in obj[tags.TUPLE]])) if has_tag(obj, tags.SET): return self._pop(set([self.restore(v) for v in obj[tags.SET]])) if util.is_dictionary(obj): data = {} for k, v in sorted(obj.items(), key=operator.itemgetter(0)): self._namestack.append(k) data[k] = self.restore(v) self._namestack.pop() return self._pop(data) return self._pop(obj)
def restore(self, obj): """Restores a flattened object to its original python state. Simply returns any of the basic builtin types >>> u = Unpickler() >>> u.restore('hello world') 'hello world' >>> u.restore({'key': 'value'}) {'key': 'value'} """ self._push() if has_tag(obj, tags.ID): return self._pop(self._objs[obj[tags.ID]]) if has_tag(obj, tags.REF): return self._pop(self._namedict.get(obj[tags.REF])) if has_tag(obj, tags.TYPE): typeref = loadclass(obj[tags.TYPE]) if not typeref: return self._pop(obj) return self._pop(typeref) if has_tag(obj, tags.REPR): return self._pop(loadrepr(obj[tags.REPR])) if has_tag(obj, tags.OBJECT): cls = loadclass(obj[tags.OBJECT]) if not cls: return self._pop(obj) # check custom handlers HandlerClass = handlers.registry.get(cls) if HandlerClass: handler = HandlerClass(self) return self._pop(handler.restore(obj)) try: if hasattr(cls, '__new__'): instance = cls.__new__(cls) else: instance = object.__new__(cls) except TypeError: # old-style classes try: instance = cls() except TypeError: # fail gracefully if the constructor requires arguments self._mkref(obj) return self._pop(obj) # keep a obj->name mapping for use in the _isobjref() case self._mkref(instance) if hasattr(instance, '__setstate__') and has_tag(obj, tags.STATE): state = self.restore(obj[tags.STATE]) instance.__setstate__(state) return self._pop(instance) for k, v in sorted(obj.iteritems(), key=operator.itemgetter(0)): # ignore the reserved attribute if k in tags.RESERVED: continue self._namestack.append(k) # step into the namespace value = self.restore(v) if (util.is_noncomplex(instance) or util.is_dictionary_subclass(instance)): instance[k] = value else: setattr(instance, k, value) # step out self._namestack.pop() # Handle list and set subclasses if has_tag(obj, tags.SEQ): if hasattr(instance, 'append'): for v in obj[tags.SEQ]: instance.append(self.restore(v)) if hasattr(instance, 'add'): for v in obj[tags.SEQ]: instance.add(self.restore(v)) return self._pop(instance) if util.is_list(obj): return self._pop([self.restore(v) for v in obj]) if has_tag(obj, tags.TUPLE): return self._pop(tuple([self.restore(v) for v in obj[tags.TUPLE]])) if has_tag(obj, tags.SET): return self._pop(set([self.restore(v) for v in obj[tags.SET]])) if util.is_dictionary(obj): data = {} for k, v in sorted(obj.iteritems(), key=operator.itemgetter(0)): self._namestack.append(k) data[k] = self.restore(v) self._namestack.pop() return self._pop(data) return self._pop(obj)
def test_is_list_other(self): self.assertFalse(util.is_list(1)) self.assertFalse(util.is_set(1)) self.assertFalse(util.is_tuple(1))
def test_is_list_dict(self): self.assertFalse(util.is_list({'key': 'value'})) self.assertFalse(util.is_set({'key': 'value'})) self.assertFalse(util.is_tuple({'key': 'value'}))
def test_is_list_list(self): self.assertTrue(util.is_list([1, 2]))
def test_is_list_dict(self): self.assertFalse(is_list({"key": "value"})) self.assertFalse(is_set({"key": "value"})) self.assertFalse(is_tuple({"key": "value"}))
def flatten(self, obj): """Takes an object and returns a JSON-safe representation of it. Simply returns any of the basic builtin datatypes >>> p = Pickler() >>> p.flatten('hello world') 'hello world' >>> p.flatten(u'hello world') u'hello world' >>> p.flatten(49) 49 >>> p.flatten(350.0) 350.0 >>> p.flatten(True) True >>> p.flatten(False) False >>> r = p.flatten(None) >>> r is None True >>> p.flatten(False) False >>> p.flatten([1, 2, 3, 4]) [1, 2, 3, 4] >>> p.flatten((1,2,))[tags.TUPLE] [1, 2] >>> p.flatten({'key': 'value'}) {'key': 'value'} """ self._push() if self._depth == self._max_depth: return self._pop(repr(obj)) if util.is_primitive(obj): return self._pop(obj) if util.is_list(obj): if self._mkref(obj): return self._pop([self.flatten(v) for v in obj]) else: return self._getref(obj) # We handle tuples and sets by encoding them in a "(tuple|set)dict" if util.is_tuple(obj): if self.unpicklable: return self._pop({tags.TUPLE: [self.flatten(v) for v in obj]}) else: return self._pop([self.flatten(v) for v in obj]) if util.is_set(obj): if self.unpicklable: return self._pop({tags.SET: [self.flatten(v) for v in obj]}) else: return self._pop([self.flatten(v) for v in obj]) if util.is_dictionary(obj): return self._pop(self._flatten_dict_obj(obj, obj.__class__())) if util.is_type(obj): return self._pop(_mktyperef(obj)) if util.is_object(obj): if self._mkref(obj): # We've never seen this object so return its # json representation. return self._pop(self._flatten_obj_instance(obj)) else: # We've seen this object before so place an object # reference tag in the data. This avoids infinite recursion # when processing cyclical objects. return self._pop(self._getref(obj)) # else, what else? (methods, functions, old style classes...) return None
def flatten(self, obj): """Takes an object and returns a JSON-safe representation of it. Simply returns any of the basic builtin datatypes >>> p = Pickler() >>> p.flatten('hello world') 'hello world' >>> p.flatten(u'hello world') u'hello world' >>> p.flatten(49) 49 >>> p.flatten(350.0) 350.0 >>> p.flatten(True) True >>> p.flatten(False) False >>> r = p.flatten(None) >>> r is None True >>> p.flatten(False) False >>> p.flatten([1, 2, 3, 4]) [1, 2, 3, 4] >>> p.flatten((1,2,))[tags.TUPLE] [1, 2] >>> p.flatten({'key': 'value'}) {'key': 'value'} """ self._push() if self._depth == self._max_depth: return self._pop(repr(obj)) if util.is_primitive(obj): return self._pop(obj) if util.is_list(obj): return self._pop([ self.flatten(v) for v in obj ]) # We handle tuples and sets by encoding them in a "(tuple|set)dict" if util.is_tuple(obj): return self._pop({tags.TUPLE: [ self.flatten(v) for v in obj ]}) if util.is_set(obj): return self._pop({tags.SET: [ self.flatten(v) for v in obj ]}) if util.is_dictionary(obj): return self._pop(self._flatten_dict_obj(obj, obj.__class__())) if util.is_type(obj): return self._pop(_mktyperef(obj)) if util.is_object(obj): data = {} has_class = hasattr(obj, '__class__') has_dict = hasattr(obj, '__dict__') if self._mkref(obj): if has_class and not util.is_repr(obj): module, name = _getclassdetail(obj) if self.unpicklable is True: data[tags.OBJECT] = '%s.%s' % (module, name) if util.is_repr(obj): if self.unpicklable is True: data[tags.REPR] = '%s/%s' % (obj.__class__.__module__, repr(obj)) else: data = unicode(obj) return self._pop(data) if util.is_dictionary_subclass(obj): return self._pop(self._flatten_dict_obj(obj, data)) if util.is_noncomplex(obj): return self._pop([self.flatten(v) for v in obj]) if has_dict: return self._pop(self._flatten_dict_obj(obj.__dict__, data)) else: # We've seen this object before so place an object # reference tag in the data. This avoids infinite recursion # when processing cyclical objects. return self._pop(self._getref(obj)) return self._pop(data)
def restore(self, obj): """Restores a flattened object to its original python state. Simply returns any of the basic builtin types >>> u = Unpickler() >>> u.restore('hello world') 'hello world' >>> u.restore({'key': 'value'}) {'key': 'value'} """ self._push() if has_tag(obj, tags.REF): return self._pop(self._namedict.get(obj[tags.REF])) if has_tag(obj, tags.TYPE): typeref = loadclass(obj[tags.TYPE]) if not typeref: return self._pop(obj) return self._pop(typeref) if has_tag(obj, tags.REPR): return self._pop(loadrepr(obj[tags.REPR])) if has_tag(obj, tags.OBJECT): cls = loadclass(obj[tags.OBJECT]) if not cls: return self._pop(obj) try: instance = object.__new__(cls) except TypeError: # old-style classes try: instance = cls() except TypeError: # fail gracefully if the constructor requires arguments self._mkref(obj) return self._pop(obj) # keep a obj->name mapping for use in the _isobjref() case self._mkref(instance) for k, v in obj.iteritems(): # ignore the reserved attribute if k in tags.RESERVED: continue self._namestack.append(k) # step into the namespace value = self.restore(v) if util.is_noncomplex(instance) or util.is_dictionary_subclass(instance): instance[k] = value else: instance.__dict__[k] = value # step out self._namestack.pop() return self._pop(instance) if util.is_list(obj): return self._pop([self.restore(v) for v in obj]) if has_tag(obj, tags.TUPLE): return self._pop(tuple([self.restore(v) for v in obj[tags.TUPLE]])) if has_tag(obj, tags.SET): return self._pop(set([self.restore(v) for v in obj[tags.SET]])) if util.is_dictionary(obj): data = {} for k, v in obj.iteritems(): self._namestack.append(k) data[k] = self.restore(v) self._namestack.pop() return self._pop(data) return self._pop(obj)
def flatten(self, obj): """Takes an object and returns a JSON-safe representation of it. Simply returns any of the basic builtin datatypes >>> p = Pickler() >>> p.flatten('hello world') 'hello world' >>> p.flatten(u'hello world') u'hello world' >>> p.flatten(49) 49 >>> p.flatten(350.0) 350.0 >>> p.flatten(True) True >>> p.flatten(False) False >>> r = p.flatten(None) >>> r is None True >>> p.flatten(False) False >>> p.flatten([1, 2, 3, 4]) [1, 2, 3, 4] >>> p.flatten((1,2,))[tags.TUPLE] [1, 2] >>> p.flatten({'key': 'value'}) {'key': 'value'} """ self._push() if self._depth == self._max_depth: return self._pop(repr(obj)) if util.is_primitive(obj): return self._pop(obj) if util.is_list(obj): return self._pop([ self.flatten(v) for v in obj ]) # We handle tuples and sets by encoding them in a "(tuple|set)dict" if util.is_tuple(obj): return self._pop({tags.TUPLE: [ self.flatten(v) for v in obj ]}) if util.is_set(obj): return self._pop({tags.SET: [ self.flatten(v) for v in obj ]}) if util.is_dictionary(obj): return self._pop(self._flatten_dict_obj(obj, obj.__class__())) if util.is_type(obj): return self._pop(_mktyperef(obj)) if util.is_object(obj): if self._mkref(obj): # We've never seen this object so return its # json representation. return self._pop(self._flatten_obj_instance(obj)) else: # We've seen this object before so place an object # reference tag in the data. This avoids infinite recursion # when processing cyclical objects. return self._pop(self._getref(obj)) return self._pop(data)
def restore(self, obj): """Restores a flattened object to its original python state. Simply returns any of the basic builtin types >>> u = Unpickler() >>> u.restore('hello world') 'hello world' >>> u.restore({'key': 'value'}) {'key': 'value'} """ self._push() if has_tag(obj, tags.ID): return self._pop(self._objs[obj[tags.ID]]) # Backwards compatibility if has_tag(obj, tags.REF): return self._pop(self._namedict.get(obj[tags.REF])) if has_tag(obj, tags.TYPE): typeref = loadclass(obj[tags.TYPE]) if not typeref: return self._pop(obj) return self._pop(typeref) # Backwards compatibility if has_tag(obj, tags.REPR): obj = loadrepr(obj[tags.REPR]) return self._pop(self._mkref(obj)) if has_tag(obj, tags.OBJECT): cls = loadclass(obj[tags.OBJECT]) if not cls: return self._pop(self._mkref(obj)) # check custom handlers HandlerClass = handlers.BaseHandler._registry.get(cls) if HandlerClass: handler = HandlerClass(self) instance = handler.restore(obj) return self._pop(self._mkref(instance)) factory = loadfactory(obj) args = getargs(obj) if args: args = self.restore(args) try: if hasattr(cls, '__new__'): # new style classes if factory: instance = cls.__new__(cls, factory, *args) instance.default_factory = factory else: instance = cls.__new__(cls, *args) else: instance = object.__new__(cls) except TypeError: # old-style classes try: instance = cls() except TypeError: # fail gracefully if the constructor requires arguments return self._pop(self._mkref(obj)) # Add to the instance table to allow being referenced by a # downstream object self._mkref(instance) if isinstance(instance, tuple): return self._pop(instance) if hasattr(instance, '__setstate__') and has_tag(obj, tags.STATE): state = self.restore(obj[tags.STATE]) instance.__setstate__(state) return self._pop(instance) for k, v in sorted(obj.items(), key=operator.itemgetter(0)): # ignore the reserved attribute if k in tags.RESERVED: continue self._namestack.append(k) # step into the namespace value = self.restore(v) if (util.is_noncomplex(instance) or util.is_dictionary_subclass(instance)): instance[k] = value else: setattr(instance, k, value) # step out self._namestack.pop() # Handle list and set subclasses if has_tag(obj, tags.SEQ): if hasattr(instance, 'append'): for v in obj[tags.SEQ]: instance.append(self.restore(v)) if hasattr(instance, 'add'): for v in obj[tags.SEQ]: instance.add(self.restore(v)) return self._pop(instance) if util.is_list(obj): parent = [] self._mkref(parent) children = [self.restore(v) for v in obj] parent.extend(children) return self._pop(parent) if has_tag(obj, tags.TUPLE): return self._pop(tuple([self.restore(v) for v in obj[tags.TUPLE]])) if has_tag(obj, tags.SET): return self._pop(set([self.restore(v) for v in obj[tags.SET]])) if util.is_dictionary(obj): data = {} for k, v in sorted(obj.items(), key=operator.itemgetter(0)): self._namestack.append(k) data[k] = self.restore(v) self._namestack.pop() return self._pop(data) return self._pop(obj)