1
from py.test import raises
3
from pypy.objspace.std import multimethod
4
from pypy.objspace.std.multimethod import FailedToImplement
10
class W_IntObject(W_Root):
13
class W_BoolObject(W_Root):
16
class W_StringObject(W_Root):
19
def delegate_b2i(space, w_x):
20
assert isinstance(w_x, W_BoolObject)
23
def add__Int_Int(space, w_x, w_y):
24
assert space == 'space'
25
assert isinstance(w_x, W_IntObject)
26
assert isinstance(w_y, W_IntObject)
30
class TestMultiMethod1:
31
Installer = multimethod.InstallerVersion1
34
cls.prev_installer = multimethod.Installer
35
multimethod.Installer = cls.Installer
36
add = multimethod.MultiMethodTable(2, root_class=W_Root,
37
argnames_before=['space'])
38
add.register(add__Int_Int, W_IntObject, W_IntObject)
40
W_IntObject: [(W_IntObject, None), (W_Root, None)],
41
W_BoolObject: [(W_BoolObject, None), (W_IntObject, delegate_b2i),
43
W_StringObject: [(W_StringObject, None), (W_Root, None)],
45
cls.typeorder = typeorder
47
cls.add1 = staticmethod(add.install('__add', [typeorder, typeorder]))
49
def teardown_class(cls):
50
multimethod.Installer = cls.prev_installer
52
def test_simple(self):
56
assert self.add1(space, w_x, w_y) == 'fine'
58
def test_failtoimplement(self):
61
w_s = W_StringObject()
62
raises(FailedToImplement, "self.add1(space, w_x, w_s)")
63
raises(FailedToImplement, "self.add1(space, w_s, w_x)")
65
def test_delegate(self):
68
w_s = W_StringObject()
70
assert self.add1(space, w_x, w_b) == 'fine'
71
assert self.add1(space, w_b, w_x) == 'fine'
72
assert self.add1(space, w_b, w_b) == 'fine'
73
raises(FailedToImplement, "self.add1(space, w_b, w_s)")
74
raises(FailedToImplement, "self.add1(space, w_s, w_b)")
76
def test_not_baked(self):
77
typeorder = self.typeorder
78
add2 = self.add.install('__add2', [typeorder, typeorder],
79
baked_perform_call=False)
80
assert add2[0] == ['space', 'arg0', 'arg1']
81
if multimethod.Installer is multimethod.InstallerVersion1:
82
assert add2[1] == 'arg0.__add2(space, arg1)'
83
assert isinstance(add2[2], dict)
87
add3_installer = multimethod.Installer(self.add, '__add3', [{},{}])
88
assert add3_installer.is_empty()
89
if multimethod.Installer is multimethod.InstallerVersion1:
90
assert len(add3_installer.to_install) == 1
91
assert add3_installer.to_install[0][0] is None
93
def test_empty_direct(self):
94
assert not self.add.install_if_not_empty('__add4', [{},{}])
96
def test_empty_not_baked(self):
97
add5_installer = multimethod.Installer(self.add, '__add5', [{},{}],
98
baked_perform_call=False)
99
assert add5_installer.is_empty()
100
if multimethod.Installer is multimethod.InstallerVersion1:
101
assert len(add5_installer.to_install) == 0
102
add5 = add5_installer.install()
103
assert add5[0] == ['space', 'arg0', 'arg1']
104
assert add5[1] == 'raiseFailedToImplement()'
105
assert isinstance(add5[2], dict)
108
def test_mmdispatcher(self):
109
typeorder = self.typeorder
110
add2 = multimethod.MMDispatcher(self.add, [typeorder, typeorder])
113
w_s = W_StringObject()
114
w_b1 = W_BoolObject()
115
w_b2 = W_BoolObject()
116
assert add2(space, w_x, w_b1) == 'fine'
117
assert add2(space, w_b2, w_x) == 'fine'
118
assert add2(space, w_b1, w_b2) == 'fine'
119
raises(FailedToImplement, "add2(space, w_b2, w_s)")
120
raises(FailedToImplement, "add2(space, w_s, w_b1)")
122
def test_all_cases(self):
126
w_x.expected = [W_IntObject, W_Root]
127
w_s = W_StringObject()
128
w_s.expected = [W_StringObject, W_Root]
130
w_b.expected = [W_BoolObject, W_IntObject, W_Root]
133
sub = multimethod.MultiMethodTable(2, root_class=W_Root,
134
argnames_before=['space'])
135
def addimpl(cls1, cls2):
136
token = random.random()
137
def sub__cls1_cls2(space, w_x, w_y):
138
assert space == 'space'
139
assert isinstance(w_x, cls1)
140
assert isinstance(w_y, cls2)
142
sub.register(sub__cls1_cls2, cls1, cls2)
147
res = sub1(space, w1, w2)
148
except FailedToImplement:
149
res = FailedToImplement
150
for cls1 in w1.expected:
151
for cls2 in w2.expected:
152
if (cls1, cls2) in expected:
153
assert res == expected[cls1, cls2]
156
assert res is FailedToImplement
158
random.shuffle(indices)
160
for index in indices:
161
cls1, cls2 = choices[index]
162
token = addimpl(cls1, cls2)
163
expected[cls1, cls2] = token
165
typeorder = self.typeorder
166
sub1 = sub.install('__sub', [typeorder, typeorder])
167
for w1 in [w_x, w_s, w_b]:
168
for w2 in [w_x, w_s, w_b]:
171
classes = [W_Root, W_StringObject, W_IntObject, W_BoolObject]
172
choices = [(cls1, cls2) for cls1 in classes
174
# each choice is a pair of classes which can be implemented or
175
# not by the multimethod 'sub'. Test all combinations that
176
# involve at most three implemented choices.
177
for i in range(len(choices)):
179
for j in range(i+1, len(choices)):
181
for k in range(j+1, len(choices)):
183
#for l in range(k+1, len(choices)): -- for a 4th choice
184
# test([i, j, k, l]) -- (takes a while)
187
class TestMultiMethod2(TestMultiMethod1):
188
Installer = multimethod.InstallerVersion2