def register(self, cls, handler=None, base=False): """Register the a custom handler for a class :param cls: The custom object class to handle :param handler: The custom handler class (if None, a decorator wrapper is returned) :param base: Indicates whether the handler should be registered for all subclasses This function can be also used as a decorator by omitting the `handler` argument: @jsonpickle.handlers.register(Foo, base=True) class FooHandler(jsonpickle.handlers.BaseHandler): pass """ if handler is None: def _register(handler_cls): self.register(cls, handler=handler_cls, base=base) return handler_cls return _register if not util.is_type(cls): raise TypeError('{0!r} is not a class/type'.format(cls)) # store both the name and the actual type for the ugly cases like # _sre.SRE_Pattern that cannot be loaded back directly self._handlers[util.importable_name(cls)] = self._handlers[cls] = handler if base: # only store the actual type for subclass checking self._base_handlers[cls] = handler
def _flatten_function(self, obj): if self.unpicklable: data = {tags.FUNCTION: util.importable_name(obj)} else: data = None return data
def register(self, cls, handler=None, base=False): """Register the a custom handler for a class :param cls: The custom object class to handle :param handler: The custom handler class (if None, a decorator wrapper is returned) :param base: Indicates whether the handler should be registered for all subclasses This function can be also used as a decorator by omitting the `handler` argument: @jsonpickle.handlers.register(Foo, base=True) class FooHandler(jsonpickle.handlers.BaseHandler): pass """ if handler is None: def _register(handler_cls): self.register(cls, handler=handler_cls, base=base) return handler_cls return _register if not util.is_type(cls): raise TypeError('{0!r} is not a class/type'.format(cls)) # store both the name and the actual type for the ugly cases like # _sre.SRE_Pattern that cannot be loaded back directly self._handlers[util.importable_name( cls)] = self._handlers[cls] = handler if base: # only store the actual type for subclass checking self._base_handlers[cls] = handler
def _mktyperef(obj): """Return a typeref dictionary >>> _mktyperef(AssertionError) {'py/type': '__builtin__.AssertionError'} """ return {tags.TYPE: util.importable_name(obj)}
def from_json(self, desired_class, dct): ''' Method copied from: https://github.com/jsonpickle/jsonpickle/issues/148#issuecomment-362508753 ''' dct[tags.OBJECT] = util.importable_name(desired_class) obj = unpickler.Unpickler().restore(dct, classes=desired_class) return obj
def register(self, cls, handler): """Register the a custom handler for a class :param cls: The custom object class to handle :param handler: The custom handler class """ key = util.importable_name(cls) self._handlers[key] = handler
def register(self, cls, handler): """Register the a custom handler for a class :param cls: The custom object class to handle :param handler: The custom handler class """ class_name = util.importable_name(cls) self._handlers[class_name] = handler
def getClassVersionKey(cls): """ Gets the wallet class version key for use in a serialized representation of the wallet. :param cls: the wallet class :return: the class version key """ return 'classver/{}'.format(importable_name(cls))
def from_json(json): '''load from json string''' doc_dict = jsonpickle.decode(json) entities = [] for e_dict in doc_dict['entities']: e_dict[tags.OBJECT] = util.importable_name(Entity) e = unpickler.Unpickler().restore(e_dict, classes=[Entity]) entities.append(e) return entities
def entities_from_json(json): ''' read from entities json returns entities list ''' entities_dict = jsonpickle.decode(json) entities = [] for e_dict in entities_dict: e_dict[tags.OBJECT] = util.importable_name(Entity) e = unpickler.Unpickler().restore(e_dict, classes=[Entity]) entities.append(e) return entities
def unregister(self, cls): self._handlers.pop(cls, None) self._handlers.pop(util.importable_name(cls), None) self._base_handlers.pop(cls, None)
def unregister(self, cls): class_name = util.importable_name(cls) try: del self._handlers[class_name] except KeyError: pass
def _flatten_obj_instance(self, obj): """Recursively flatten an instance and return a json-friendly dict """ data = {} has_class = hasattr(obj, '__class__') has_dict = hasattr(obj, '__dict__') has_slots = not has_dict and hasattr(obj, '__slots__') has_getnewargs = hasattr(obj, '__getnewargs__') has_getnewargs_ex = hasattr(obj, '__getnewargs_ex__') has_getinitargs = hasattr(obj, '__getinitargs__') has_reduce, has_reduce_ex = util.has_reduce(obj) # Support objects with __getstate__(); this ensures that # both __setstate__() and __getstate__() are implemented has_getstate = hasattr(obj, '__getstate__') if has_class: cls = obj.__class__ else: cls = type(obj) # Check for a custom handler class_name = util.importable_name(cls) handler = handlers.get(class_name) if handler is not None: if self.unpicklable: data[tags.OBJECT] = class_name return handler(self).flatten(obj, data) reduce_val = None if has_class and not util.is_module(obj): if self.unpicklable: class_name = util.importable_name(cls) data[tags.OBJECT] = class_name # test for a reduce implementation, and redirect before doing anything else # if that is what reduce requests if has_reduce_ex: try: # we're implementing protocol 2 reduce_val = obj.__reduce_ex__(2) except TypeError: # A lot of builtin types have a reduce which just raises a TypeError # we ignore those pass if has_reduce and not reduce_val: try: reduce_val = obj.__reduce__() except TypeError: # A lot of builtin types have a reduce which just raises a TypeError # we ignore those pass if reduce_val: try: # At this stage, we only handle the case where __reduce__ returns a string # other reduce functionality is implemented further down if isinstance(reduce_val, (str, unicode)): varpath = iter(reduce_val.split('.')) # curmod will be transformed by the loop into the value to pickle curmod = sys.modules[next(varpath)] for modname in varpath: curmod = getattr(curmod, modname) # replace obj with value retrieved return self._flatten(curmod) except KeyError: # well, we can't do anything with that, so we ignore it pass if has_getnewargs_ex: data[tags.NEWARGSEX] = list( map(self._flatten, obj.__getnewargs_ex__())) if has_getnewargs and not has_getnewargs_ex: data[tags.NEWARGS] = self._flatten(obj.__getnewargs__()) if has_getinitargs: data[tags.INITARGS] = self._flatten(obj.__getinitargs__()) if has_getstate: try: state = obj.__getstate__() except TypeError: # Has getstate but it cannot be called, e.g. file descriptors # in Python3 self._pickle_warning(obj) return None else: return self._getstate(state, data) if util.is_module(obj): if self.unpicklable: data[tags.REPR] = '%s/%s' % (obj.__name__, obj.__name__) else: data = unicode(obj) return data if util.is_dictionary_subclass(obj): self._flatten_dict_obj(obj, data) return data if util.is_sequence_subclass(obj): return self._flatten_sequence_obj(obj, data) if util.is_noncomplex(obj): return [self._flatten(v) for v in obj] if util.is_iterator(obj): # force list in python 3 data[tags.ITERATOR] = list( map(self._flatten, islice(obj, self._max_iter))) return data if reduce_val and not isinstance(reduce_val, (str, unicode)): # at this point, reduce_val should be some kind of iterable # pad out to len 5 rv_as_list = list(reduce_val) insufficiency = 5 - len(rv_as_list) if insufficiency: rv_as_list += [None] * insufficiency if rv_as_list[0].__name__ == '__newobj__': rv_as_list[0] = tags.NEWOBJ data[tags.REDUCE] = list(map(self._flatten, rv_as_list)) # lift out iterators, so we don't have to iterator and uniterator their content # on unpickle if data[tags.REDUCE][3]: data[tags.REDUCE][3] = data[tags.REDUCE][3][tags.ITERATOR] if data[tags.REDUCE][4]: data[tags.REDUCE][4] = data[tags.REDUCE][4][tags.ITERATOR] return data if has_dict: # Support objects that subclasses list and set if util.is_sequence_subclass(obj): return self._flatten_sequence_obj(obj, data) # hack for zope persistent objects; this unghostifies the object getattr(obj, '_', None) return self._flatten_dict_obj(obj.__dict__, data) if has_slots: return self._flatten_newstyle_with_slots(obj, data) self._pickle_warning(obj) return None
def _flatten_obj_instance(self, obj): """Recursively flatten an instance and return a json-friendly dict """ data = {} has_class = hasattr(obj, '__class__') has_dict = hasattr(obj, '__dict__') has_slots = not has_dict and hasattr(obj, '__slots__') has_getnewargs = util.has_method(obj, '__getnewargs__') has_getnewargs_ex = util.has_method(obj, '__getnewargs_ex__') has_getinitargs = util.has_method(obj, '__getinitargs__') has_reduce, has_reduce_ex = util.has_reduce(obj) # Support objects with __getstate__(); this ensures that # both __setstate__() and __getstate__() are implemented has_getstate = hasattr(obj, '__getstate__') # not using has_method since __getstate__() is handled separately below if has_class: cls = obj.__class__ else: cls = type(obj) # Check for a custom handler class_name = util.importable_name(cls) handler = handlers.get(cls, handlers.get(class_name)) if handler is not None: if self.unpicklable: data[tags.OBJECT] = class_name return handler(self).flatten(obj, data) reduce_val = None if has_class and not util.is_module(obj): if self.unpicklable: class_name = util.importable_name(cls) data[tags.OBJECT] = class_name # test for a reduce implementation, and redirect before doing anything else # if that is what reduce requests if has_reduce_ex: try: # we're implementing protocol 2 reduce_val = obj.__reduce_ex__(2) except TypeError: # A lot of builtin types have a reduce which just raises a TypeError # we ignore those pass if has_reduce and not reduce_val: try: reduce_val = obj.__reduce__() except TypeError: # A lot of builtin types have a reduce which just raises a TypeError # we ignore those pass if reduce_val: try: # At this stage, we only handle the case where __reduce__ returns a string # other reduce functionality is implemented further down if isinstance(reduce_val, (str, unicode)): varpath = iter(reduce_val.split('.')) # curmod will be transformed by the loop into the value to pickle curmod = sys.modules[next(varpath)] for modname in varpath: curmod = getattr(curmod, modname) # replace obj with value retrieved return self._flatten(curmod) except KeyError: # well, we can't do anything with that, so we ignore it pass if has_getnewargs_ex: data[tags.NEWARGSEX] = list(map(self._flatten, obj.__getnewargs_ex__())) if has_getnewargs and not has_getnewargs_ex: data[tags.NEWARGS] = self._flatten(obj.__getnewargs__()) if has_getinitargs: data[tags.INITARGS] = self._flatten(obj.__getinitargs__()) if has_getstate: try: state = obj.__getstate__() except TypeError: # Has getstate but it cannot be called, e.g. file descriptors # in Python3 self._pickle_warning(obj) return None else: return self._getstate(state, data) if util.is_module(obj): if self.unpicklable: data[tags.REPR] = '%s/%s' % (obj.__name__, obj.__name__) else: data = unicode(obj) return data if util.is_dictionary_subclass(obj): self._flatten_dict_obj(obj, data) return data if util.is_sequence_subclass(obj): return self._flatten_sequence_obj(obj, data) if util.is_noncomplex(obj): return [self._flatten(v) for v in obj] if util.is_iterator(obj): # force list in python 3 data[tags.ITERATOR] = list(map(self._flatten, islice(obj, self._max_iter))) return data if reduce_val and not isinstance(reduce_val, (str, unicode)): # at this point, reduce_val should be some kind of iterable # pad out to len 5 rv_as_list = list(reduce_val) insufficiency = 5 - len(rv_as_list) if insufficiency: rv_as_list += [None] * insufficiency if rv_as_list[0].__name__ == '__newobj__': rv_as_list[0] = tags.NEWOBJ data[tags.REDUCE] = list(map(self._flatten, rv_as_list)) # lift out iterators, so we don't have to iterator and uniterator their content # on unpickle if data[tags.REDUCE][3]: data[tags.REDUCE][3] = data[tags.REDUCE][3][tags.ITERATOR] if data[tags.REDUCE][4]: data[tags.REDUCE][4] = data[tags.REDUCE][4][tags.ITERATOR] return data if has_dict: # Support objects that subclasses list and set if util.is_sequence_subclass(obj): return self._flatten_sequence_obj(obj, data) # hack for zope persistent objects; this unghostifies the object getattr(obj, '_', None) return self._flatten_dict_obj(obj.__dict__, data) if has_slots: return self._flatten_newstyle_with_slots(obj, data) # catchall return for data created above without a return # (e.g. __getnewargs__ is not supposed to be the end of the story) if data: return data self._pickle_warning(obj) return None