Passed
Pull Request — master (#77)
by Ramon
57s
created

jsons.serializers.default_iterable   A

Complexity

Total Complexity 9

Size/Duplication

Total Lines 73
Duplicated Lines 0 %

Importance

Changes 0
Metric Value
wmc 9
eloc 45
dl 0
loc 73
rs 10
c 0
b 0
f 0

3 Functions

Rating   Name   Duplication   Size   Complexity  
A default_iterable_serializer() 0 37 3
A _get_subclasses() 0 16 5
A f() 0 4 1
1
from collections.abc import Iterable
2
from multiprocessing import Process
3
from typing import Tuple
4
5
from typish import get_args
6
7
from jsons._dump_impl import dump
8
from jsons._multitasking import multi_task
9
from jsons.exceptions import SerializationError
10
11
12
def default_iterable_serializer(
13
        obj: Iterable,
14
        cls: type = None,
15
        *,
16
        strict: bool = False,
17
        tasks: int = 1,
18
        task_type: type = Process,
19
        **kwargs) -> list:
20
    """
21
    Serialize the given ``obj`` to a list of serialized objects.
22
    :param obj: the iterable that is to be serialized.
23
    :param cls: the (subscripted) type of the iterable.
24
    :param strict: a bool to determine if the serializer should be strict
25
    (i.e. only dumping stuff that is known to ``cls``).
26
    :param tasks: the allowed number of tasks (threads or processes).
27
    :param task_type: the type that is used for multitasking.
28
    :param kwargs: any keyword arguments that may be given to the serialization
29
    process.
30
    :return: a list of which all elements are serialized.
31
    """
32
    # The meta kwarg store_cls is filtered out, because an iterable should have
33
    # its own -meta attribute.
34
    kwargs_ = {**kwargs, 'strict': strict}
35
    kwargs_.pop('_store_cls', None)
36
    if strict:
37
        subclasses = _get_subclasses(obj, cls)
38
    else:
39
        subclasses = _get_subclasses(obj, None)
40
41
    if tasks < 2:
42
        result = [dump(elem, cls=subclasses[i], **kwargs_)
43
                  for i, elem in enumerate(obj)]
44
    else:
45
        zipped_objs = list(zip(obj, subclasses))
46
        result = multi_task(f, zipped_objs, tasks, task_type, **kwargs_)
47
48
    return result
49
50
51
def _get_subclasses(obj: Iterable, cls: type = None) -> Tuple[type, ...]:
52
    subclasses = (None,) * len(obj)
53
    if cls:
54
        args = get_args(cls)
55
        if len(args) == 1:
56
            # E.g. List[int]
57
            subclasses = args * len(obj)
58
        elif len(args) > 1:
59
            # E.g. Tuple[int, str, str]
60
            subclasses = args
61
    if len(subclasses) != len(obj):
62
        msg = ('Not enough generic types ({}) in {}, expected {} to match '
63
               'the iterable of length {}'
64
               .format(len(subclasses), cls, len(obj), len(obj)))
65
        raise SerializationError(msg)
66
    return subclasses
67
68
69
def f(obj_cls_tuple: Tuple[object, type], *args, **kwargs):
70
    kwargs_ = {**kwargs}
71
    kwargs_['tasks'] = 1
72
    return dump(*obj_cls_tuple, *args, **kwargs_)
73