-
Notifications
You must be signed in to change notification settings - Fork 0
/
utils.py
177 lines (130 loc) · 4.33 KB
/
utils.py
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
import re
import os
import json
class ReSearcher():
"""
Helper to enable evaluation
and regex formatting in a single line
"""
match = None
def __call__(self, pattern, string):
self.match = re.search(pattern, string)
return self.match
def __getattr__(self, name):
return getattr(self.match, name)
class Tree(dict):
""" Autovivificious dictionary """
def __missing__(self, key):
value = self[key] = type(self)()
return value
def __str__(self):
""" Serialize dictionary to JSON formatted string with indents """
return json.dumps(self, indent=4)
def get_value(key, item):
"""
key + value = interface item
function returns value for given key and item
"""
if key.strip() == item.strip():
return key
else:
item = item.lstrip()
result = re.search('^('+key+')(.*)', item)
value = format(result.group(2)).lstrip()
return value
def get_key(item, key_length):
"""
key + value = item
number of words of key = key_length
function returns key
"""
word = item.strip().split()
if key_length == 0: # fix
return item
elif len(word) == key_length:
return item
else:
return ' '.join(word[0:key_length])
def splitrange(raw_range):
"""
'1,2,4-6' returns ['1','2','4','5','6']
'none' returns ['None']
"""
m = re.search(r'^(\d+)\-(\d+)$', raw_range)
if m:
first = int(format(m.group(1)))
last = int(format(m.group(2)))
return [str(i) for i in range(first, last+1)]
m = re.search(r'[\d+,-]+', raw_range)
if m:
result = []
for raw_element in format(m.group(0)).split(','):
if '-' in raw_element:
for element in splitrange(raw_element):
result.append(element)
else:
result.append(raw_element)
return result
m = re.search(r'^none$', raw_range)
if m:
return ['None']
def unpack_optional_items(grouped_config_part):
"""
Helper function to unpack grouped config parts in template_parser
"""
context = ''
global_cfg = []
hierarc_cfg = [] # list of individual hierarchical config part
hierarc_cfgs = [] # list with all individual hierarchical confg parts
for previous_line, line in prev_cur_generator(grouped_config_part):
line = line.rstrip()
if not line.strip(): # skip empty lines
continue
if line.lstrip() == line and context == '':
if previous_line is None:
pass
elif (not previous_line.startswith('!') or previous_line == ''):
global_cfg.append(previous_line)
elif line.lstrip() != line and context == '':
hierarc_cfg = []
hierarc_cfg.append(previous_line)
context = 'hierarc'
elif line.lstrip() != line and context == 'hierarc':
hierarc_cfg.append(previous_line)
elif line == '!' or line.startswith('') and context == 'hierarc':
hierarc_cfg.append(previous_line)
hierarc_cfgs.append(hierarc_cfg)
context = ''
return global_cfg, hierarc_cfgs
def hierarc_cfg_diff(templ_cfg, hier_cfg, templ_wildcard_char='<<>>'):
"""
Function compares hierarchical configuration items and
takes into account that wildcards can be used in template.
If template --> key 7 <<>>
and config --> key 7 SDFT123WERfsdf
Then function considers these two lines identical.
"""
if len(templ_cfg) != len(hier_cfg):
return False
for line1, line2 in zip(templ_cfg, hier_cfg):
for word1, word2 in zip(line1.split(), line2.split()):
if word1 != word2 and word1 == templ_wildcard_char:
pass
elif word1 != word2 and word1 != templ_wildcard_char:
return False
return True
def prev_cur_generator(iterable):
"""
Helper function/generator to read lines (iterable) and yield both current
and previous line.
"""
previous = None
iterable = iter(iterable)
curr = next(iterable)
try:
while True:
yield previous, curr
previous = curr
curr = next(iterable)
except StopIteration:
pass