Passed
Pull Request — master (#127)
by Ramon
01:37
created

_load_hashed_keys()   A

Complexity

Conditions 4

Size

Total Lines 27
Code Lines 17

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
eloc 17
dl 0
loc 27
rs 9.55
c 0
b 0
f 0
cc 4
nop 4
1
from typing import Optional, Callable
2
from typish import get_args
3
4
from jsons.exceptions import DeserializationError
5
from jsons._load_impl import load
6
7
8
def default_dict_deserializer(
9
        obj: dict,
10
        cls: type,
11
        *,
12
        key_transformer: Optional[Callable[[str], str]] = None,
13
        **kwargs) -> dict:
14
    """
15
    Deserialize a dict by deserializing all instances of that dict.
16
    :param obj: the dict that needs deserializing.
17
    :param key_transformer: a function that transforms the keys to a different
18
    style (e.g. PascalCase).
19
    :param cls: not used.
20
    :param kwargs: any keyword arguments.
21
    :return: a deserialized dict instance.
22
    """
23
    key_tfr = key_transformer or (lambda key: key)
24
    cls_args = get_args(cls)
25
    kwargs_ = {**kwargs, 'key_transformer': key_transformer}
26
27
    obj_ = _load_hashed_keys(obj, cls, cls_args, key_transformer=key_transformer, **kwargs)
28
29
    if len(cls_args) == 2:
30
        cls_k, cls_v = cls_args
31
        kwargs_k = {**kwargs_, 'cls': cls_k}
32
        kwargs_v = {**kwargs_, 'cls': cls_v}
33
        res = {load(key_tfr(k), **kwargs_k): load(obj_[k], **kwargs_v)
34
               for k in obj_}
35
    else:
36
        res = {key_tfr(key): load(obj_[key], **kwargs_)
37
               for key in obj_}
38
    return res
39
40
41
def _load_hashed_keys(obj: dict, cls: type, cls_args: tuple, **kwargs) -> dict:
42
    # Load any hashed keys and return a copy of the given obj if any hashed
43
    # keys are unpacked.
44
    result = obj
45
46
    stored_keys = list(obj.get('-keys', []))
47
    if stored_keys:
48
        # Apparently, there are stored hashed keys, we need to unpack them.
49
        if len(cls_args) != 2:
50
            raise DeserializationError('A detailed type is needed for cls of '
51
                                       'the form Dict[<type>, <type>] to '
52
                                       'deserialize a dict with hashed keys.',
53
                                       obj, cls)
54
        result = {**obj}
55
        key_type = cls_args[0]
56
        for key in stored_keys:
57
            # Get the original (unhashed) key and load it.
58
            original_key = result['-keys'][key]
59
            loaded_key = load(original_key, cls=key_type, **kwargs)
60
61
            # Replace the hashed key by the loaded key entirely.
62
            result[loaded_key] = result[key]
63
            del result['-keys'][key]
64
            del result[key]
65
66
        del result['-keys']
67
    return result
68