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