-
Notifications
You must be signed in to change notification settings - Fork 20
/
Cfg.py
157 lines (139 loc) · 4.14 KB
/
Cfg.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
#!/usr/bin/env python3
"""
This program is part of MoaT.
Its job is simply to extract values from a YAML-formatted config file.
"""
import yaml
import sys
#_depth = -2
#def arm(p):
# def wrap(*a,**k):
# global _depth
# _depth += 2
# s=" "*_depth
# print(s+">",repr((p.__name__,a,k)))
# try:
# #if a[1] == ["test","0"]:
# # import pdb;pdb.set_trace()
# r = p(*a,**k)
# except Exception:
# print_exc()
# raise
# else:
# print(s+"<"+repr(r))
# #if r is None:
# # import pdb;pdb.set_trace()
# return r
# finally:
# _depth += -2
# return wrap
#@arm
def get1(ak,k,loc):
try:
try:
return ak[k]
except KeyError:
raise KeyError((k,loc))
except Exception as e:
ee = e
if isinstance(k,str):
#if k == "test.1":
# import pdb;pdb.set_trace()
try:
k = int(k)
except ValueError:
pass
else:
return ak[k]
raise ee
#@arm
class Cfg(object):
"""\
Encapsultates looking up items in a config tree.
"""
follow = True
iseq = 1
def __init__(self, f):
with open(f) as fd:
self.data = yaml.load(fd)
self.ipath = {}
self.data['_idata_'] = {}
def inc1(self,f):
i = self.ipath.get(f,None)
if i is None:
i = str(self.iseq)
self.iseq += 1
with open(f) as fd:
self.data['_idata_'][i] = yaml.load(fd)
self.ipath[f] = i
return "_idata_."+i
def inc(self,ak):
"parse _ref entries"
r = ak.get('_ref',None)
if r is None:
ak['_ref'] = r = []
elif not isinstance(r,list):
ak['_ref'] = r = [r]
ri = ak.get('_include',None)
if ri is not None:
if isinstance(ri,list):
for rin in ri:
r.append(self.inc1(rin))
else:
r.append(self.inc1(ri))
del ak['_include']
if not r:
del ak['_ref']
return iter(r)
def getpath(self,loc,ak,k1,*rest):
try:
try:
v1 = get1(ak,k1,loc)
if rest:
v1 = self.getpath(loc+(2,k1,),v1,*rest)
return v1
except (KeyError,AttributeError) as e:
if not self.follow: raise
try: v1 = get1(ak,'_default',loc+(3,k1,))
except KeyError: raise e
if rest:
v1 = self.getpath(loc+(4,k1,),v1,*rest)
return v1
except (KeyError,AttributeError) as e:
if not self.follow: raise
if k1 == "_idata_": raise
for v in self.inc(ak):
try:
#print ("GP",self.data,"==",v.split('.'),[k1],list(rest), file=sys.stderr)
return self.getpath(loc+(1,v,),self.data,*(v.split('.')+[k1]+list(rest)))
except KeyError:
pass
raise e
def getkeys(self,lk,ak,*rest):
if rest:
if isinstance(ak,list):
self.getkeys(lk,ak[int(rest[0])],*rest[1:])
else:
if rest[0] in ak:
self.getkeys(lk,ak[rest[0]],*rest[1:])
if self.follow and '_default' in ak:
self.getkeys(lk,ak['_default'], *rest[1:])
else:
for k in ak:
lk.add(k)
if self.follow and isinstance(ak,dict):
if not rest or rest[0] != '_idata_':
for v in self.inc(ak):
self.getkeys(lk,self.data,*(v.split('.')+list(rest)))
def subtree(self,*key):
return self.getpath((),self.data, *key)
def keyval(self,*key):
lk = set()
self.getkeys(lk,self.data,*key)
for k in lk:
if k.startswith('_'):
continue
kp=key+(k,)
v = self.subtree(*kp)
if isinstance(v,(int,str,float)):
yield k,v