Passed
Push — master ( 3318af...ce1cbc )
by Fabio
01:13
created

benedict.utils.keypath_util._split_keys()   A

Complexity

Conditions 2

Size

Total Lines 8
Code Lines 4

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
cc 2
eloc 4
nop 2
dl 0
loc 8
rs 10
c 0
b 0
f 0
1
# -*- coding: utf-8 -*-
2
3
from benedict.utils import dict_util
4
5
from six import string_types
6
7
import re
8
9
10
KEY_INDEX_RE = r'(?:\[[\'\"]*(\-?[\d]+)[\'\"]*\]){1}$'
11
12
13
def check_keys(d, separator):
14
    """
15
    Check if dict keys contain keypath separator.
16
    """
17
    if not isinstance(d, dict) or not separator:
18
        return
19
20
    def check_key(parent, key, value):
21
        if key and isinstance(key, string_types) and separator in key:
22
            raise ValueError(
23
                'keys should not contain keypath separator '
24
                '\'{}\', found: \'{}\'.'.format(separator, key))
25
    dict_util.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 isinstance(keypath, (list, tuple, )):
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
            matches = re.findall(KEY_INDEX_RE, key)
49
            if matches:
50
                key = re.sub(KEY_INDEX_RE, '', key)
51
                index = int(matches[0])
52
                keys.insert(0, index)
53
                # keys.insert(0, { keylist_util.INDEX_KEY:index })
54
                continue
55
            keys.insert(0, key)
56
            break
57
        return keys
58
    return [key]
59
60
61
def _split_keys(keypath, separator):
62
    """
63
    Splits keys using the given separator:
64
    eg. 'item.subitem[1]' -> ['item', 'subitem[1]'].
65
    """
66
    if separator:
67
        return keypath.split(separator)
68
    return [keypath]
69
70
71
def _split_keys_and_indexes(keypath, separator):
72
    """
73
    Splits keys and indexes using the given separator:
74
    eg. 'item[0].subitem[1]' -> ['item', 0, 'subitem', 1].
75
    """
76
    if isinstance(keypath, string_types):
77
        keys1 = _split_keys(keypath, separator)
78
        keys2 = []
79
        for key in keys1:
80
            keys2 += _split_key_indexes(key)
81
        return keys2
82
    return [keypath]
83