示例#1
0
def default_list_deserializer(obj: list,
                              cls: type = None,
                              *,
                              warn_on_fail: bool = False,
                              tasks: int = 1,
                              task_type: type = Process,
                              fork_inst: Type[StateHolder] = StateHolder,
                              **kwargs) -> list:
    """
    Deserialize a list by deserializing all items of that list.
    :param obj: the list that needs deserializing.
    :param cls: the type optionally with a generic (e.g. List[str]).
    :param warn_on_fail: if ``True``, will warn upon any failure and continue.
    :param tasks: the allowed number of tasks (threads or processes).
    :param task_type: the type that is used for multitasking.
    :param fork_inst: if given, it uses this fork of ``JsonSerializable``.
    :param kwargs: any keyword arguments.
    :return: a deserialized list instance.
    """
    cls_ = None
    kwargs_ = {**kwargs}
    cls_args = get_args(cls)
    if cls_args:
        cls_ = cls_args[0]
        # Mark the cls as 'inferred' so that later it is known where cls came
        # from and the precedence of classes can be determined.
        kwargs_['_inferred_cls'] = True

    if tasks == 1:
        result = _do_load(obj, cls_, warn_on_fail, fork_inst, kwargs_)
    elif tasks > 1:
        result = multi_task(load, obj, tasks, task_type, cls_, **kwargs_)
    else:
        raise JsonsError('Invalid number of tasks: {}'.format(tasks))
    return result
示例#2
0
def default_dict_deserializer(obj: dict,
                              cls: type,
                              *,
                              key_transformer: Optional[Callable[[str],
                                                                 str]] = None,
                              **kwargs) -> dict:
    """
    Deserialize a dict by deserializing all instances of that dict.
    :param obj: the dict that needs deserializing.
    :param key_transformer: a function that transforms the keys to a different
    style (e.g. PascalCase).
    :param cls: not used.
    :param kwargs: any keyword arguments.
    :return: a deserialized dict instance.
    """
    key_tfr = key_transformer or (lambda key: key)
    cls_args = get_args(cls)
    kwargs_ = {**kwargs, 'key_transformer': key_transformer}
    if len(cls_args) == 2:
        cls_k, cls_v = cls_args
        kwargs_k = {**kwargs_, 'cls': cls_k}
        kwargs_v = {**kwargs_, 'cls': cls_v}
        res = {
            load(key_tfr(k), **kwargs_k): load(obj[k], **kwargs_v)
            for k in obj
        }
    else:
        res = {key_tfr(key): load(obj[key], **kwargs_) for key in obj}
    return res
示例#3
0
def default_list_deserializer(obj: list,
                              cls: type = None,
                              *,
                              tasks: int = 1,
                              task_type: type = Process,
                              **kwargs) -> list:
    """
    Deserialize a list by deserializing all items of that list.
    :param obj: the list that needs deserializing.
    :param cls: the type optionally with a generic (e.g. List[str]).
    :param tasks: the allowed number of tasks (threads or processes).
    :param task_type: the type that is used for multitasking.
    :param kwargs: any keyword arguments.
    :return: a deserialized list instance.
    """
    cls_ = None
    kwargs_ = {**kwargs}
    cls_args = get_args(cls)
    if cls_args:
        cls_ = cls_args[0]
        # Mark the cls as 'inferred' so that later it is known where cls came
        # from and the precedence of classes can be determined.
        kwargs_['_inferred_cls'] = True

    if tasks == 1:
        result = [load(elem, cls=cls_, tasks=1, **kwargs_) for elem in obj]
    elif tasks > 1:
        result = multi_task(load, obj, tasks, task_type, cls_, **kwargs_)
    else:
        raise JsonsError('Invalid number of tasks: {}'.format(tasks))
    return result
示例#4
0
def default_dict_deserializer(obj: dict,
                              cls: type,
                              *,
                              key_transformer: Optional[Callable[[str],
                                                                 str]] = None,
                              **kwargs) -> dict:
    """
    Deserialize a dict by deserializing all instances of that dict.
    :param obj: the dict that needs deserializing.
    :param key_transformer: a function that transforms the keys to a different
    style (e.g. PascalCase).
    :param cls: not used.
    :param kwargs: any keyword arguments.
    :return: a deserialized dict instance.
    """
    cls_args = get_args(cls)

    obj_, keys_were_hashed = _load_hashed_keys(obj,
                                               cls,
                                               cls_args,
                                               key_transformer=key_transformer,
                                               **kwargs)

    return _deserialize(obj_, cls_args, key_transformer, keys_were_hashed,
                        kwargs)
示例#5
0
def default_tuple_deserializer(obj: list,
                               cls: type = None,
                               *,
                               key_transformer: Optional[Callable[[str],
                                                                  str]] = None,
                               **kwargs) -> object:
    """
    Deserialize a (JSON) list into a tuple by deserializing all items of that
    list.
    :param obj: the tuple that needs deserializing.
    :param cls: the type optionally with a generic (e.g. Tuple[str, int]).
    :param kwargs: any keyword arguments.
    :return: a deserialized tuple instance.
    """
    if hasattr(cls, '_fields'):
        return default_namedtuple_deserializer(obj,
                                               cls,
                                               key_transformer=key_transformer,
                                               **kwargs)
    cls_args = get_args(cls)
    if cls_args:
        tuple_types = getattr(cls, '__tuple_params__', cls_args)
        if tuple_with_ellipsis(cls):
            tuple_types = [tuple_types[0]] * len(obj)
        list_ = [
            load(value, tuple_types[i], **kwargs)
            for i, value in enumerate(obj)
        ]
    else:
        list_ = [load(value, **kwargs) for i, value in enumerate(obj)]
    return tuple(list_)
def default_defaultdict_deserializer(obj: dict,
                                     cls: type,
                                     *,
                                     key_transformer: Optional[Callable[
                                         [str], str]] = None,
                                     **kwargs) -> dict:
    """
    Deserialize a defaultdict.
    :param obj: the dict that needs deserializing.
    :param key_transformer: a function that transforms the keys to a different
    style (e.g. PascalCase).
    :param cls: not used.
    :param kwargs: any keyword arguments.
    :return: a deserialized defaultdict instance.
    """
    args = get_args(cls)
    default_factory = None
    cls_ = Dict
    if args:
        key, value = get_args(cls)
        cls_ = Dict[key, value]
        default_factory = value
    loaded = load(obj, cls_, key_transformer=key_transformer, **kwargs)
    return defaultdict(default_factory, loaded)
示例#7
0
def _get_subclasses(obj: Iterable, cls: type = None) -> Tuple[type, ...]:
    subclasses = (None, ) * len(obj)
    if cls:
        args = get_args(cls)
        if len(args) == 1:
            # E.g. List[int]
            subclasses = args * len(obj)
        elif len(args) > 1:
            # E.g. Tuple[int, str, str]
            subclasses = args
    if len(subclasses) != len(obj):
        msg = ('Not enough generic types ({}) in {}, expected {} to match '
               'the iterable of length {}'.format(len(subclasses), cls,
                                                  len(obj), len(obj)))
        raise SerializationError(msg)
    return subclasses
def is_optional_type(cls: type) -> bool:
    """
    Return True if the given class is an optional type. A type is considered to
    be optional if it allows ``None`` as value.

    Example:

    is_optional_type(Optional[str])  # True
    is_optional_type(Union[str, int, None])  # True
    is_optional_type(str)  # False
    is_optional_type(Union[str, int])  # False

    :param cls: a type.
    :return: True if cls is an optional type.
    """
    origin = get_origin(cls)
    args = get_args(cls)
    return origin == typing.Union and NoneType in args
示例#9
0
def default_tuple_serializer(obj: tuple,
                             cls: Optional[type] = None,
                             **kwargs) -> Union[list, dict]:
    """
    Serialize the given ``obj`` to a list of serialized objects.
    :param obj: the tuple that is to be serialized.
    :param cls: the type of the ``obj``.
    :param kwargs: any keyword arguments that may be given to the serialization
    process.
    :return: a list of which all elements are serialized.
    """
    if hasattr(obj, '_fields'):
        return default_namedtuple_serializer(obj, **kwargs)

    cls_ = cls
    if cls and tuple_with_ellipsis(cls):
        cls_ = Tuple[(get_args(cls)[0], ) * len(obj)]

    return default_iterable_serializer(obj, cls_, **kwargs)
示例#10
0
def default_mapping_deserializer(obj: dict, cls: type, **kwargs) -> Mapping:
    """
    Deserialize a (JSON) dict into a mapping by deserializing all items of that
    dict.
    :param obj: the dict that needs deserializing.
    :param cls: the type, optionally with a generic (e.g. Set[str]).
    :param kwargs: any keyword arguments.
    :return: a deserialized set instance.
    """
    cls_ = Mapping
    cls_args = get_args(cls)
    if cls_args:
        cls_ = MappingType[cls_args]
    dict_ = default_dict_deserializer(obj, cls_, **kwargs)
    result = dict_
    # Strip any generics from cls to allow for an instance check.
    if not isinstance(result, get_origin(cls)):
        result = cls(dict_)
    return result
示例#11
0
def default_list_serializer(obj: list,
                            cls: type = None,
                            *,
                            strict: bool = False,
                            fork_inst: Optional[type] = StateHolder,
                            **kwargs) -> list:
    """
    Serialize the given ``obj`` to a list of serialized objects.
    :param obj: the list that is to be serialized.
    :param cls: the (subscripted) type of the list.
    :param strict: a bool to determine if the serializer should be strict
    (i.e. only dumping stuff that is known to ``cls``).
    :param fork_inst: if given, it uses this fork of ``JsonSerializable``.
    :param kwargs: any keyword arguments that may be given to the serialization
    process.
    :return: a list of which all elements are serialized.
    """
    if not obj:
        return []

    kwargs_ = {**kwargs, 'strict': strict}

    # The meta kwarg store_cls is filtered out, because an iterable should have
    # its own -meta attribute.
    kwargs_.pop('_store_cls', None)

    inner_type = None
    serializer = dump

    cls_args = get_args(cls)
    if cls_args:
        inner_type = cls_args[0]
        serializer = get_serializer(inner_type, fork_inst)
    elif strict:
        inner_type = type(obj[0])
        serializer = get_serializer(inner_type, fork_inst)

    return [
        serializer(elem, cls=inner_type, fork_inst=fork_inst, **kwargs_)
        for elem in obj
    ]