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
|
from .support import HPyTest
class TestCall(HPyTest):
def argument_combinations(self, **items):
""" Returns all possible ways of expressing the given items as
arguments to a function.
"""
items = list(items.items())
for i in range(len(items) + 1):
args = tuple(item[1] for item in items[:i])
kw = dict(items[i:])
yield {"args": args, "kw": kw}
if not args:
yield {"kw": kw}
if not kw:
yield {"args": args}
if not args and not kw:
yield {}
def test_hpy_calltupledict(self):
import pytest
mod = self.make_module("""
HPyDef_METH(call, "call", call_impl, HPyFunc_KEYWORDS)
static HPy call_impl(HPyContext *ctx, HPy self,
HPy *args, HPy_ssize_t nargs, HPy kw)
{
HPy f, result;
HPy f_args = HPy_NULL;
HPy f_kw = HPy_NULL;
HPyTracker ht;
static const char *kwlist[] = { "f", "args", "kw", NULL };
if (!HPyArg_ParseKeywords(ctx, &ht, args, nargs, kw, "O|OO",
kwlist, &f, &f_args, &f_kw)) {
return HPy_NULL;
}
result = HPy_CallTupleDict(ctx, f, f_args, f_kw);
HPyTracker_Close(ctx, ht);
return result;
}
@EXPORT(call)
@INIT
""")
def f(a, b):
return a + b
def g():
return "this is g"
# test passing arguments with handles of the correct type --
# i.e. args is a tuple or a null handle, kw is a dict or a null handle.
for d in self.argument_combinations(a=1, b=2):
assert mod.call(f, **d) == 3
for d in self.argument_combinations(a=1):
with pytest.raises(TypeError):
mod.call(f, **d)
for d in self.argument_combinations():
with pytest.raises(TypeError):
mod.call(f, **d)
for d in self.argument_combinations():
assert mod.call(g, **d) == "this is g"
for d in self.argument_combinations(object=2):
assert mod.call(str, **d) == "2"
for d in self.argument_combinations():
with pytest.raises(TypeError):
mod.call("not callable", **d)
for d in self.argument_combinations(unknown=2):
with pytest.raises(TypeError):
mod.call("not callable", **d)
# test passing handles of the incorrect type as arguments
with pytest.raises(TypeError):
mod.call(f, args=[1, 2])
with pytest.raises(TypeError):
mod.call(f, args="string")
with pytest.raises(TypeError):
mod.call(f, args=1)
with pytest.raises(TypeError):
mod.call(f, args=None)
with pytest.raises(TypeError):
mod.call(f, kw=[1, 2])
with pytest.raises(TypeError):
mod.call(f, kw="string")
with pytest.raises(TypeError):
mod.call(f, kw=1)
with pytest.raises(TypeError):
mod.call(f, kw=None)
def test_hpycallable_check(self):
mod = self.make_module("""
HPyDef_METH(f, "f", f_impl, HPyFunc_O)
static HPy f_impl(HPyContext *ctx, HPy self, HPy arg)
{
if (HPyCallable_Check(ctx, arg))
return HPy_Dup(ctx, ctx->h_True);
return HPy_Dup(ctx, ctx->h_False);
}
@EXPORT(f)
@INIT
""")
def f():
return "this is f"
assert mod.f(f) is True
assert mod.f(str) is True
assert mod.f("a") is False
assert mod.f(3) is False
|