forked from fergald/python-deep
-
Notifications
You must be signed in to change notification settings - Fork 0
/
deep_frame.py
129 lines (94 loc) · 2.52 KB
/
deep_frame.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
import re
comparators = {}
class Comparator(object):
pass
class Frame(object):
def descend(self, i1, i2):
return self.comparator.descend(i1, i2, self)
class Comparison(object):
def __init__(self):
self.cmp_cache = {}
self.frames = []
self.bad_frame = None
def get_frame(self):
if self.frame:
return self.frame.pop()
else:
return Frame()
def release_frame(self, frame):
return self.frames.append(frame)
def descend(self, i1, i2, prev):
if not isinstance(i2, Comparator):
i2 = self.wrap(i2)
key = (id(i1), i2) # Comparators are not hashable
cache = self.cache
if cache.has_key(key):
equals = cache[key]
else:
cache[key] = True # assume true to match circular structures
frame = self.get_frame()
frame.prev = prev
frame.comparator = i2
frame.comparison = self
equals = i2.equals(i1, frame)
cache[key] = equals
if equals:
self.bad_frame = frame
else:
self.release_frame(frame)
return value
def wrap(self, item):
t = type(item)
if t in (str, int):
return Scalar(item)
if t in (str, int, list, tuple):
return
class NotSupplied():
pass
class ValueComparator(Comparator):
def __init__(self, value):
self.value = value
def render(self, value=NotSupplied):
if value is NotSupplied:
value = self.value
return self.render_any(value)
class StrableComparator(Comparator):
def render(self):
return render_value(self.value)
def render_value(self, value):
if type(value) is str:
return '"%s"' % re.escape(value)
else:
return str(value)
def expr(self, expr):
return expr
class Equal(StrableComparator):
def equals(self, item, frame):
class Type(ValueComparator):
def equals(self, item, comp):
return self.value is type(item)
def render_self(self):
return self.value
def expr(self, expr):
return "type(%s)" % expr
class Scalar(ValueComparator):
def equals(self, i2, comp):
return self.value == i2
class DoesNotExist(object):
def render(self, value=NotSupplied):
if value is NotSupplied:
return "Does Not Exist"
else:
return str(value)
DNE = DoesNotExist()
class Iterable(ValueComparator):
def equals(self, i2, comp):
value = self.value
for i1 in
return self.value == i2
class Len(ValueComparator):
def equals(self, i2, comp):
value = self.value
return self.value == len(i2)
def expr(self, expr):
return "len(%s)" % expr