Passed
Push — master ( f980db...1c4121 )
by Fabio
01:20
created

benedict.utils.dict_util   B

Complexity

Total Complexity 45

Size/Duplication

Total Lines 124
Duplicated Lines 0 %

Importance

Changes 0
Metric Value
wmc 45
eloc 91
dl 0
loc 124
rs 8.8
c 0
b 0
f 0

14 Functions

Rating   Name   Duplication   Size   Complexity  
C clean() 0 10 10
A flatten() 0 11 4
A clone() 0 2 1
A dump() 0 6 2
A filter() 0 10 4
A remove() 0 6 3
A move() 0 2 1
A invert() 0 9 4
A swap() 0 2 1
A merge() 0 10 5
A subset() 0 8 3
A items_sorted_by_values() 0 2 2
A unique() 0 9 3
A items_sorted_by_keys() 0 2 2

How to fix   Complexity   

Complexity

Complex classes like benedict.utils.dict_util often do a lot of different things. To break such a class down, we need to identify a cohesive component within that class. A common approach to find such a component is to look for fields/methods that share the same prefixes, or suffixes.

Once you have determined the fields that belong together, you can apply the Extract Class refactoring. If the component makes sense as a sub-class, Extract Subclass is also a candidate, and is often faster.

1
# -*- coding: utf-8 -*-
2
3
from six import string_types
4
5
import copy
6
import json
7
8
9
def clean(d, strings=True, dicts=True, lists=True):
10
    keys = list(d.keys())
11
    for key in keys:
12
        value = d.get(key, None)
13
        if not value:
14
            if value is None or \
15
                    strings and isinstance(value, string_types) or \
16
                    dicts and isinstance(value, dict) or \
17
                    lists and isinstance(value, (list, tuple, )):
18
                del d[key]
19
20
21
def clone(d):
22
    return copy.deepcopy(d)
23
24
25
def dump(data):
26
    def encoder(obj):
27
        json_types = (bool, dict, float, int, list, tuple, ) + string_types
28
        if not isinstance(obj, json_types):
29
            return str(obj)
30
    return json.dumps(data, indent=4, sort_keys=True, default=encoder)
31
32
33
def flatten(d, separator='_', base=''):
34
    new_dict = d.__class__()
35
    keys = sorted(d.keys())
36
    for key in keys:
37
        value = d.get(key)
38
        keypath = '{}{}{}'.format(base, separator, key) if base and separator else key
39
        if isinstance(value, dict):
40
            new_dict.update(flatten(value, separator, keypath))
41
        else:
42
            new_dict[keypath] = value
43
    return new_dict
44
45
46
def filter(d, predicate):
47
    if not callable(predicate):
48
        raise ValueError('predicate argument must be a callable.')
49
    new_dict = d.__class__()
50
    keys = d.keys()
51
    for key in keys:
52
        value = d.get(key, None)
53
        if predicate(key, value):
54
            new_dict[key] = value
55
    return new_dict
56
57
58
def invert(d, flat=False):
59
    new_dict = d.__class__()
60
    if flat:
61
        for key, value in d.items():
62
            new_dict.setdefault(value, key)
63
    else:
64
        for key, value in d.items():
65
            new_dict.setdefault(value, []).append(key)
66
    return new_dict
67
68
69
def items_sorted_by_keys(d, reverse=False):
70
    return sorted(d.items(), key=lambda item: item[0], reverse=reverse)
71
72
73
def items_sorted_by_values(d, reverse=False):
74
    return sorted(d.items(), key=lambda item: item[1], reverse=reverse)
75
76
77
def merge(d, other, *args):
78
    others = [other] + list(args)
79
    for other in others:
80
        for key, value in other.items():
81
            src = d.get(key, None)
82
            if isinstance(src, dict) and isinstance(value, dict):
83
                merge(src, value)
84
            else:
85
                d[key] = value
86
    return d
87
88
89
def move(d, key_src, key_dest):
90
    d[key_dest] = d.pop(key_src)
91
92
93
def remove(d, keys, *args):
94
    if isinstance(keys, string_types):
95
        keys = [keys]
96
    keys += args
97
    for key in keys:
98
        d.pop(key, None)
99
100
101
def subset(d, keys, *args):
102
    new_dict = d.__class__()
103
    if isinstance(keys, string_types):
104
        keys = [keys]
105
    keys += args
106
    for key in keys:
107
        new_dict[key] = d.get(key, None)
108
    return new_dict
109
110
111
def swap(d, key1, key2):
112
    d[key1], d[key2] = d[key2], d[key1]
113
114
115
def unique(d):
116
    values = []
117
    keys = sorted(d.keys())
118
    for key in keys:
119
        value = d.get(key, None)
120
        if value in values:
121
            d.pop(key, None)
122
            continue
123
        values.append(value)
124