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 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237
|
from pypy.interpreter import eval
from pypy.interpreter.function import Function, Method
from pypy.interpreter.gateway import descr_function_get
from pypy.interpreter.pycode import PyCode
from pypy.interpreter.argument import Arguments
class TestMethod:
@classmethod
def compile(cls, src):
assert src.strip().startswith("def ")
compiler = cls.space.createcompiler()
code = compiler.compile(src, '<hello>', 'exec', 0).co_consts_w[0]
return Function(cls.space, code, cls.space.newdict())
def setup_class(cls):
src = """
def c(self, bar):
return bar
"""
cls.fn = cls.compile(src)
def test_get(self):
space = self.space
w_meth = descr_function_get(space, self.fn, space.wrap(5), space.type(space.wrap(5)))
meth = space.unwrap(w_meth)
assert isinstance(meth, Method)
def test_call(self):
space = self.space
w_meth = descr_function_get(space, self.fn, space.wrap(5), space.type(space.wrap(5)))
meth = space.unwrap(w_meth)
w_result = meth.call_args(Arguments(space, [space.wrap(42)]))
assert space.unwrap(w_result) == 42
def test_fail_call(self):
space = self.space
w_meth = descr_function_get(space, self.fn, space.wrap(5), space.type(space.wrap(5)))
meth = space.unwrap(w_meth)
args = Arguments(space, [space.wrap("spam"), space.wrap("egg")])
self.space.raises_w(self.space.w_TypeError, meth.call_args, args)
def test_method_get(self):
space = self.space
# Create some function for this test only
func = self.compile("def m(self): return self")
# Some shorthands
obj1 = space.wrap(23)
obj2 = space.wrap(42)
args = Arguments(space, [])
# Check method returned from func.__get__()
w_meth1 = descr_function_get(space, func, obj1, space.type(obj1))
meth1 = space.unwrap(w_meth1)
assert isinstance(meth1, Method)
assert meth1.call_args(args) == obj1
# Check method returned from method.__get__()
# --- meth1 is already bound so meth1.__get__(*) is meth1.
w_meth2 = meth1.descr_method_get(obj2, space.type(obj2))
meth2 = space.unwrap(w_meth2)
assert isinstance(meth2, Method)
assert meth2.call_args(args) == obj1
# Check method returned from unbound_method.__get__()
w_meth3 = descr_function_get(space, func, space.w_None, space.type(obj2))
meth3 = space.unwrap(w_meth3)
assert meth3 is func
class TestShortcuts(object):
def compile(self, src):
assert src.strip().startswith("def ")
compiler = self.space.createcompiler()
code = compiler.compile(src, '<hello>', 'exec', 0).co_consts_w[0]
return Function(self.space, code, self.space.newdict())
def test_call_function(self):
space = self.space
d = {}
for i in range(10):
args = "(" + ''.join(["a%d," % a for a in range(i)]) + ")"
src = """
def f%s:
return %s
""" % (args, args)
exec src in d
f = d['f']
res = f(*range(i))
fn = self.compile(src)
code = fn.code
assert fn.code.fast_natural_arity == i|PyCode.FLATPYCALL
if i < 5:
def bomb(*args):
assert False, "shortcutting should have avoided this"
code.funcrun = bomb
code.funcrun_obj = bomb
args_w = map(space.wrap, range(i))
w_res = space.call_function(fn, *args_w)
check = space.is_true(space.eq(w_res, space.wrap(res)))
assert check
def test_flatcall(self):
space = self.space
src = """
def f(a):
return a"""
fn = self.compile(src)
assert fn.code.fast_natural_arity == 1|PyCode.FLATPYCALL
def bomb(*args):
assert False, "shortcutting should have avoided this"
fn.code.funcrun = bomb
fn.code.funcrun_obj = bomb
w_3 = space.newint(3)
w_res = space.call_function(fn, w_3)
assert w_res is w_3
w_res = space.appexec([fn, w_3], """(f, x):
return f(x)
""")
assert w_res is w_3
def test_flatcall_method(self):
space = self.space
src = """
def f(self, a):
return a
"""
fn = self.compile(src)
assert fn.code.fast_natural_arity == 2|PyCode.FLATPYCALL
def bomb(*args):
assert False, "shortcutting should have avoided this"
fn.code.funcrun = bomb
fn.code.funcrun_obj = bomb
w_3 = space.newint(3)
w_res = space.appexec([fn, w_3], """(f, x):
class A(object):
m = f
y = A().m(x)
b = A().m
z = b(x)
return y is x and z is x
""")
assert space.is_true(w_res)
def test_flatcall_default_arg(self):
space = self.space
src = """
def f(a, b):
return a+b
"""
code = self.compile(src).code
fn = Function(self.space, code, self.space.newdict(),
defs_w=[space.newint(1)])
assert fn.code.fast_natural_arity == 2|eval.Code.FLATPYCALL
def bomb(*args):
assert False, "shortcutting should have avoided this"
code.funcrun = bomb
code.funcrun_obj = bomb
w_3 = space.newint(3)
w_4 = space.newint(4)
# ignore this for now
#w_res = space.call_function(fn, w_3)
# assert space.eq_w(w_res, w_4)
w_res = space.appexec([fn, w_3], """(f, x):
return f(x)
""")
assert space.eq_w(w_res, w_4)
def test_flatcall_default_arg_method(self):
space = self.space
src = """
def f(self, a, b):
return a+b
"""
code = self.compile(src).code
fn = Function(self.space, code, self.space.newdict(),
defs_w=[space.newint(1)])
assert fn.code.fast_natural_arity == 3|eval.Code.FLATPYCALL
def bomb(*args):
assert False, "shortcutting should have avoided this"
code.funcrun = bomb
code.funcrun_obj = bomb
w_3 = space.newint(3)
w_res = space.appexec([fn, w_3], """(f, x):
class A(object):
m = f
y = A().m(x)
b = A().m
z = b(x)
return y+10*z
""")
assert space.eq_w(w_res, space.wrap(44))
class TestFunction:
def test_func_defaults(self):
from pypy.interpreter import gateway
def g(w_a=None):
pass
app_g = gateway.interp2app_temp(g)
space = self.space
w_g = space.wrap(app_g)
w_defs = space.getattr(w_g, space.wrap("__defaults__"))
assert space.is_w(w_defs, space.w_None)
w_count = space.getattr(w_g, space.wrap("__defaults_count__"))
assert space.unwrap(w_count) == 1
|