Passed
Push — master ( db2481...3bd527 )
by Fabio
03:28
created

benedict.dicts.keypath.keypath_util   A

Complexity

Total Complexity 19

Size/Duplication

Total Lines 82
Duplicated Lines 0 %

Importance

Changes 0
Metric Value
wmc 19
eloc 47
dl 0
loc 82
rs 10
c 0
b 0
f 0

5 Functions

Rating   Name   Duplication   Size   Complexity  
A _split_keys() 0 8 2
A _split_key_indexes() 0 19 5
A parse_keys() 0 10 3
B check_keys() 0 13 6
A _split_keys_and_indexes() 0 12 3
1
# -*- coding: utf-8 -*-
2
3
from benedict.core import traverse
4
from benedict.utils import type_util
5
6
import re
7
8
9
KEY_INDEX_RE = r'(?:\[[\'\"]*(\-?[\d]+)[\'\"]*\]){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
                'keys should not contain keypath separator '
23
                '\'{}\', found: \'{}\'.'.format(separator, key))
24
    traverse(d, check_key)
25
26
27
def parse_keys(keypath, separator):
28
    """
29
    Parse keys from keylist or keypath using the given separator.
30
    """
31
    if type_util.is_list_or_tuple(keypath):
32
        keys = []
33
        for key in keypath:
34
            keys += parse_keys(key, separator)
35
        return keys
36
    return _split_keys_and_indexes(keypath, separator)
37
38
39
def _split_key_indexes(key):
40
    """
41
    Splits key indexes:
42
    eg. 'item[0][1]' -> ['item', 0, 1].
43
    """
44
    if '[' in key and key.endswith(']'):
45
        keys = []
46
        while True:
47
            matches = re.findall(KEY_INDEX_RE, key)
48
            if matches:
49
                key = re.sub(KEY_INDEX_RE, '', key)
50
                index = int(matches[0])
51
                keys.insert(0, index)
52
                # keys.insert(0, { keylist_util.INDEX_KEY:index })
53
                continue
54
            keys.insert(0, key)
55
            break
56
        return keys
57
    return [key]
58
59
60
def _split_keys(keypath, separator):
61
    """
62
    Splits keys using the given separator:
63
    eg. 'item.subitem[1]' -> ['item', 'subitem[1]'].
64
    """
65
    if separator:
66
        return keypath.split(separator)
67
    return [keypath]
68
69
70
def _split_keys_and_indexes(keypath, separator):
71
    """
72
    Splits keys and indexes using the given separator:
73
    eg. 'item[0].subitem[1]' -> ['item', 0, 'subitem', 1].
74
    """
75
    if type_util.is_string(keypath):
76
        keys1 = _split_keys(keypath, separator)
77
        keys2 = []
78
        for key in keys1:
79
            keys2 += _split_key_indexes(key)
80
        return keys2
81
    return [keypath]
82