benedict.dicts.keypath.keypath_util.check_keys()   B
last analyzed

Complexity

Conditions 6

Size

Total Lines 14
Code Lines 8

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
eloc 8
dl 0
loc 14
rs 8.6666
c 0
b 0
f 0
cc 6
nop 2
1
import re
2
3
from benedict.core import traverse
4
from benedict.utils import type_util
5
6
KEY_INDEX_RE = r"(?:\[[\'\"]*(\-?[\d]+)[\'\"]*\]){1}$"
7
8
9
def check_keys(d, separator):
10
    """
11
    Check if dict keys contain keypath separator.
12
    """
13
    if not type_util.is_dict(d) or not separator:
14
        return
15
16
    def check_key(parent, key, value):
17
        if key and type_util.is_string(key) and separator in key:
18
            raise ValueError(
19
                f"Key should not contain keypath separator '{separator}', found: '{key}'."
20
            )
21
22
    traverse(d, check_key)
23
24
25
def parse_keys(keypath, separator):
26
    """
27
    Parse keys from keylist or keypath using the given separator.
28
    """
29
    if type_util.is_list_or_tuple(keypath):
30
        keys = []
31
        for key in keypath:
32
            keys += parse_keys(key, separator)
33
        return keys
34
    return _split_keys_and_indexes(keypath, separator)
35
36
37
def _split_key_indexes(key):
38
    """
39
    Splits key indexes:
40
    eg. 'item[0][1]' -> ['item', 0, 1].
41
    """
42
    if "[" in key and key.endswith("]"):
43
        keys = []
44
        while True:
45
            matches = re.findall(KEY_INDEX_RE, key)
46
            if matches:
47
                key = re.sub(KEY_INDEX_RE, "", key)
48
                index = int(matches[0])
49
                keys.insert(0, index)
50
                # keys.insert(0, { keylist_util.INDEX_KEY:index })
51
                continue
52
            keys.insert(0, key)
53
            break
54
        return keys
55
    return [key]
56
57
58
def _split_keys(keypath, separator):
59
    """
60
    Splits keys using the given separator:
61
    eg. 'item.subitem[1]' -> ['item', 'subitem[1]'].
62
    """
63
    if separator:
64
        return keypath.split(separator)
65
    return [keypath]
66
67
68
def _split_keys_and_indexes(keypath, separator):
69
    """
70
    Splits keys and indexes using the given separator:
71
    eg. 'item[0].subitem[1]' -> ['item', 0, 'subitem', 1].
72
    """
73
    if type_util.is_string(keypath):
74
        keys1 = _split_keys(keypath, separator)
75
        keys2 = []
76
        for key in keys1:
77
            keys2 += _split_key_indexes(key)
78
        return keys2
79
    return [keypath]
80