-
Notifications
You must be signed in to change notification settings - Fork 10
/
Copy pathcore.py
161 lines (127 loc) · 3.41 KB
/
core.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
import collections
import mud.core.components
from mud.core import predicates
from mud.core.CAPSMODE import *
__all__ = ["given", "check", "before", "after", "instead", "fail", "call", "act_stack", "stack"]
registry = {}
def OD(ltps=[]):
return collections.OrderedDict(ltps)
def fn_name(f):
try:
return f.__name__
except:
return str(f)
def tunnel(cursor, key, notfound={}):
if key not in cursor:
cursor[key] = notfound
return cursor[key]
def walk(cursor, key):
if isinstance(key, dict):
return False
if cursor:
if cursor.get(key):
return cursor[key]
return False
def _register(f, tag, spec=[]):
v = f.__name__
arity = len(spec)
cursor = tunnel(registry, v, OD())
cursor = tunnel(cursor, arity, OD())
cursor = tunnel(cursor, tag, OD())
cursor = tunnel(cursor, spec, f)
def check(*types):
def decorator(f):
_register(f, "check", types)
return f
return decorator
def before(*types):
def decorator(f):
_register(f, "before", types)
return f
return decorator
def given(*types):
def decorator(f):
_register(f, "given", types)
return f
return decorator
def after(*types):
def decorator(f):
_register(f, "after", types)
return f
return decorator
def instead(*types):
def decorator(f):
_register(f, "instead", types)
return f
return decorator
def fail(*types):
def decorator(f):
_register(f, "fail", types)
return f
return decorator
def printable_preds(col):
return "<"+", ".join(map(fn_name, col))+">"
def compose(roles, args, report = [], every=False):
for f in roles.get("check") or []:
if not apply(f, args):
print "[check failed]"
return False
res = {}
if every: res = {"before":[], "given":[], "after":[]}
for role in ["before", "given", "after"]:
fns = roles.get(role) or []
for f in fns:
if every:
res[role].append(apply(f, args))
else:
res[role] = apply(f, args)
break
return res
def speccheck(t, e):
if isinstance(t, str):
return predicates._get(t)(e)
return t(e)
def dict_act(verb, every, *args):
try:
report = []
arity = len(args)
cursor = walk(registry, verb)
cursor = walk(cursor, arity)
rolereport = []
if cursor:
results = OD()
for role in cursor:
for spec in cursor[role]:
good = True
specced = map(speccheck, spec, args)
for b in specced:
if b == False:
good = b
break
if good:
roledict = tunnel(results, role, [])
roledict.insert(0, cursor[role][spec])
rolereport += [str(printable_preds(spec))]
if len(rolereport) > 0:
report.append(" ".join([" "+str(role)+"->["] + rolereport + ["]\r\n"]))
res = compose(results, args, report, every)
return res
except Exception as exc:
print exc, "\r\n", verb, " ".join(report)
raise
def call(verb, *args):
res = apply(dict_act, [verb, False] + list(args))
if res:
return res.get("given")
def stack(verb, *args):
res = apply(dict_act, [verb, True] + list(args))
if res:
return GET(res,"before") + GET(res,"given") + GET(res,"after")
def act_stack(verb, *args):
out = []
res = apply(dict_act, [verb, False] + list(args))
if res:
for role in ["before", "given", "after"]:
if res.get(role):
out.append(res.get(role))
return out