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

_split_key_indexes()   B

Complexity

Conditions 6

Size

Total Lines 24
Code Lines 20

Duplication

Lines 0
Ratio 0 %

Importance

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