Passed
Pull Request — master (#114)
by
unknown
05:50 queued 04:41
created

KeylistDict._pop_by_keys()   F

Complexity

Conditions 14

Size

Total Lines 28
Code Lines 26

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
cc 14
eloc 26
nop 3
dl 0
loc 28
rs 3.6
c 0
b 0
f 0

How to fix   Complexity   

Complexity

Complex classes like benedict.dicts.keylist.keylist_dict.KeylistDict._pop_by_keys() 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 benedict.dicts.base import BaseDict
4
from benedict.dicts.keylist import keylist_util
5
from benedict.dicts.keylist.keylist_util import generator_to_list
6
from benedict.utils import type_util
7
8
9
class KeylistDict(BaseDict):
10
    def __init__(self, *args, **kwargs):
11
        super(KeylistDict, self).__init__(*args, **kwargs)
12
13
    def __contains__(self, key):
14
        if type_util.is_list_or_tuple(key):
15
            return self._contains_by_keys(key)
16
        return super(KeylistDict, self).__contains__(key)
17
18
    def _contains_by_keys(self, keys):
19
        parent, _, val = keylist_util.get_item(self, keys)
20
        if type_util.is_dict_or_list_or_tuple(parent):
21
            return True
22
        elif type_util.is_generator(val):
23
            return type_util.is_generator_empty(val)
24
        return False
25
26
    def __delitem__(self, key):
27
        if type_util.is_list_or_tuple(key):
28
            self._delitem_by_keys(key)
29
            return
30
        super(KeylistDict, self).__delitem__(key)
31
32
    def _delitem_by_keys(self, keys):
33
        parent, key, _ = keylist_util.get_item(self, keys)
34
        if type_util.is_dict_or_list(parent) and type_util.is_wildcard(key):
35
            parent.clear()
36
            return
37
        elif type_util.is_dict_or_list(parent):
38
            del parent[key]
39
            return
40
        elif type_util.is_tuple(parent):
41
            # raise the standard TypeError
42
            del parent[key]
43
        raise KeyError(f"Invalid keys: '{keys}'")
44
45
    def __getitem__(self, key):
46
        if type_util.is_list_or_tuple(key):
47
            return self._getitem_by_keys(key)
48
        return super(KeylistDict, self).__getitem__(key)
49
50
    def _getitem_by_keys(self, keys):
51
        parent, key, val = keylist_util.get_item(self, keys)
52
        if type_util.is_generator(val):
53
            return generator_to_list(val)
54
        elif type_util.is_list(parent) and type_util.is_wildcard(key):
55
            return parent
56
        elif type_util.is_dict_or_list_or_tuple(parent):
57
            return parent[key]
58
        raise KeyError(f"Invalid keys: '{keys}'")
59
60
    def __setitem__(self, key, value):
61
        if type_util.is_list_or_tuple(key):
62
            self._setitem_by_keys(key, value)
63
            return
64
        super(KeylistDict, self).__setitem__(key, value)
65
66
    def _setitem_by_keys(self, keys, value):
67
        keylist_util.set_item(self, keys, value)
68
69
    def get(self, key, default=None):
70
        if type_util.is_list_or_tuple(key):
71
            return self._get_by_keys(key, default)
72
        return super(KeylistDict, self).get(key, default)
73
74
    def _get_by_keys(self, keys, default=None):
75
        parent, key, value = keylist_util.get_item(self, keys)
76
        if type_util.is_generator(value) and type_util.is_generator(parent):
77
            data = generator_to_list(value)
78
            if type_util.is_integer(key):
79
                return data[key]
80
            return data
81
        if type_util.is_list_of_list(parent) and type_util.is_wildcard(key):
82
            return value
83
        elif type_util.is_list(parent) and type_util.is_wildcard(key):
84
            return parent
85
        elif type_util.is_wildcard(keys[-2]):
86
            if type_util.is_list_of_dicts(parent):
87
                return [item.get(key) for item in parent]
88
            elif type_util.is_list_of_list(parent):
89
                return value
90
        elif type_util.is_dict(parent):
91
            return parent.get(key, default)
92
        elif type_util.is_list_or_tuple(parent):
93
            return parent[key]
94
        return default
95
96
    def pop(self, key, *args):
97
        if type_util.is_list_or_tuple(key):
98
            return self._pop_by_keys(key, *args)
99
        return super(KeylistDict, self).pop(key, *args)
100
101
    def _pop_by_keys(self, keys, *args):
102
        parent, key, val = keylist_util.get_item(self, keys)
103
        if type_util.is_dict(parent):
104
            return parent.pop(key, *args)
105
        elif type_util.is_generator(val) and type_util.is_generator(parent):
106
            cleaned_list = []
107
            for item in parent:
108
                if type_util.is_list_or_tuple(item):
109
                    if type_util.is_wildcard(key):
110
                        cleaned_list.extend(item.pop(0) for _ in range(len(item)))
111
                elif type_util.is_dict(item):
112
                    cleaned_list.append(item)
113
            return cleaned_list
114
        elif type_util.is_wildcard(key):
115
            data = [parent.pop(0) for _ in range(len(parent))]
116
            return data
117
        elif type_util.is_list_of_dicts(parent) and type_util.any_wildcard_in_list(
118
            keys
119
        ):
120
            return [_item.pop(key) for _item in parent if key in _item]
121
        elif type_util.is_list(parent):
122
            return parent.pop(key)
123
        elif type_util.is_tuple(parent):
124
            # raise the standard TypeError
125
            del parent[key]
126
        if args:
127
            return args[0]
128
        raise KeyError(f"Invalid keys: '{keys}'")
129
130
    def set(self, key, value):
131
        self[key] = value
132
133
    def setdefault(self, key, default=None):
134
        if key not in self:
135
            self[key] = default
136
            return default
137
        return self[key]
138