Passed
Pull Request — master (#17)
by Ramon
50s
created

default_object_serializer()   A

Complexity

Conditions 1

Size

Total Lines 36
Code Lines 17

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
eloc 17
dl 0
loc 36
rs 9.55
c 0
b 0
f 0
cc 1
nop 7
1
from typing import Optional, Callable
2
from jsons.classes import JsonSerializable
3
from jsons.serializers.default_dict import default_dict_serializer
4
5
6
def default_object_serializer(
7
        obj: object,
8
        key_transformer: Optional[Callable[[str], str]] = None,
9
        strip_nulls: bool = False,
10
        strip_privates: bool = False,
11
        strip_properties: bool = False,
12
        strip_class_variables: bool = False,
13
        **kwargs) -> dict:
14
    """
15
    Serialize the given ``obj`` to a dict. All values within ``obj`` are also
16
    serialized. If ``key_transformer`` is given, it will be used to transform
17
    the casing (e.g. snake_case) to a different format (e.g. camelCase).
18
    :param obj: the object that is to be serialized.
19
    :param key_transformer: a function that will be applied to all keys in the
20
    resulting dict.
21
    :param strip_nulls: if ``True`` the resulting dict will not contain null
22
    values.
23
    :param strip_privates: if ``True`` the resulting dict will not contain
24
    private attributes (i.e. attributes that start with an underscore).
25
    :param strip_properties: if ``True`` the resulting dict will not contain
26
    values from @properties.
27
    :param strip_class_variables: if ``True`` the resulting dict will not
28
    contain values from class variables.
29
    :param kwargs: any keyword arguments that are to be passed to the
30
    serializer functions.
31
    :return: a Python dict holding the values of ``obj``.
32
    """
33
    obj_dict = _get_dict_from_obj(obj, strip_privates, strip_properties,
34
                                  strip_class_variables, **kwargs)
35
    return default_dict_serializer(obj_dict,
36
                                   key_transformer=key_transformer,
37
                                   strip_nulls=strip_nulls,
38
                                   strip_privates=strip_privates,
39
                                   strip_properties=strip_properties,
40
                                   strip_class_variables=strip_class_variables,
41
                                   **kwargs)
42
43
44
def _get_dict_from_obj(obj,
45
                       strip_privates,
46
                       strip_properties,
47
                       strip_class_variables,
48
                       cls=None, *_, **__):
49
    excluded_elems = dir(JsonSerializable)
50
    props, other_cls_vars = _get_class_props(obj.__class__)
51
    return {attr: obj.__getattribute__(attr) for attr in dir(obj)
52
            if not attr.startswith('__')
53
            and not (strip_privates and attr.startswith('_'))
54
            and not (strip_properties and attr in props)
55
            and not (strip_class_variables and attr in other_cls_vars)
56
            and attr != 'json'
57
            and not isinstance(obj.__getattribute__(attr), Callable)
58
            and (not cls or attr in cls.__slots__)
59
            and attr not in excluded_elems}
60
61
62
def _get_class_props(cls):
63
    props = []
64
    other_cls_vars = []
65
    for n, v in _get_complete_class_dict(cls).items():
66
        props.append(n) if type(v) is property else other_cls_vars.append(n)
67
    return props, other_cls_vars
68
69
70
def _get_complete_class_dict(cls):
71
    cls_dict = {}
72
    # Loop reversed so values of sub-classes override those of super-classes.
73
    for cls_or_elder in reversed(cls.mro()):
74
        cls_dict.update(cls_or_elder.__dict__)
75
    return cls_dict
76