Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

introduce HPy_Type and tentatively HPy_TypeCheck #161

Merged
merged 4 commits into from
Jan 28, 2021
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
10 changes: 10 additions & 0 deletions hpy/devel/include/common/autogen_impl.h

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

1 change: 1 addition & 0 deletions hpy/devel/include/common/runtime/ctx_object.h
Original file line number Diff line number Diff line change
Expand Up @@ -5,5 +5,6 @@
#include "hpy.h"

_HPy_HIDDEN void ctx_Dump(HPyContext ctx, HPy h);
_HPy_HIDDEN int ctx_TypeCheck(HPyContext ctx, HPy h_obj, HPy h_type);

#endif /* HPY_COMMON_RUNTIME_CTX_OBJECT_H */
6 changes: 6 additions & 0 deletions hpy/devel/include/cpython/hpy.h
Original file line number Diff line number Diff line change
Expand Up @@ -329,6 +329,12 @@ _HPy_Dump(HPyContext ctx, HPy h)
return ctx_Dump(ctx, h);
}

HPyAPI_FUNC(int)
HPy_TypeCheck(HPyContext ctx, HPy h_obj, HPy h_type)
{
return ctx_TypeCheck(ctx, h_obj, h_type);
}

HPyAPI_FUNC(HPyListBuilder)
HPyListBuilder_New(HPyContext ctx, HPy_ssize_t initial_size)
{
Expand Down
3 changes: 3 additions & 0 deletions hpy/devel/include/universal/autogen_ctx.h

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

12 changes: 12 additions & 0 deletions hpy/devel/include/universal/autogen_trampolines.h

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

24 changes: 24 additions & 0 deletions hpy/devel/src/runtime/ctx_object.c
Original file line number Diff line number Diff line change
Expand Up @@ -14,3 +14,27 @@ ctx_Dump(HPyContext ctx, HPy h)
// about the handle itself in the future.
_PyObject_Dump(_h2py(h));
}

/* NOTE: contrarily to CPython, the HPy have to check that h_type is a
type. On CPython it's not necessarily because it passes a PyTypeObject*,
but here we can only receive an HPy.

However, we can't/don't want to raise an exception if you pass a non-type,
because the CPython version (PyObject_TypeCheck) always succeed and it
would be too easy to forget to check the return value. We just raise a
fatal error instead.

Hopefully the slowdown is not too much. If it proves to be too much, we
could say that the function is allowed to crash if you pass a non-type, and
do the check only in debug mode.
*/
_HPy_HIDDEN int
ctx_TypeCheck(HPyContext ctx, HPy h_obj, HPy h_type)
{
PyObject *type= _h2py(h_type);
assert(type != NULL);
if (!PyType_Check(type)) {
Py_FatalError("HPy_TypeCheck arg 2 must be a type");
}
return PyObject_TypeCheck(_h2py(h_obj), (PyTypeObject*)type);
}
2 changes: 2 additions & 0 deletions hpy/tools/autogen/parse.py
Original file line number Diff line number Diff line change
Expand Up @@ -219,6 +219,8 @@ def _visit_hpyslot_slot(self, node):
'HPyTracker_ForgetAll': None,
'HPyTracker_Close': None,
'_HPy_Dump': None,
'HPy_Type': 'PyObject_Type',
'HPy_TypeCheck': None,
}


Expand Down
7 changes: 7 additions & 0 deletions hpy/tools/autogen/public_api.h
Original file line number Diff line number Diff line change
Expand Up @@ -125,6 +125,9 @@ HPy_ssize_t HPyLong_AsSsize_t(HPyContext ctx, HPy h);
HPy HPyFloat_FromDouble(HPyContext ctx, double v);
double HPyFloat_AsDouble(HPyContext ctx, HPy h);

HPy HPyBool_FromLong(HPyContext ctx, long v);


/* abstract.h */
HPy_ssize_t HPy_Length(HPyContext ctx, HPy h);

Expand Down Expand Up @@ -200,6 +203,10 @@ int HPy_SetItem(HPyContext ctx, HPy obj, HPy key, HPy value);
int HPy_SetItem_i(HPyContext ctx, HPy obj, HPy_ssize_t idx, HPy value);
int HPy_SetItem_s(HPyContext ctx, HPy obj, const char *key, HPy value);

HPy HPy_Type(HPyContext ctx, HPy obj);
// WARNING: HPy_TypeCheck could be tweaked/removed in the future, see issue #160
int HPy_TypeCheck(HPyContext ctx, HPy obj, HPy type);

void* _HPy_Cast(HPyContext ctx, HPy h);
HPy _HPy_New(HPyContext ctx, HPy h_type, void **data);

Expand Down
3 changes: 3 additions & 0 deletions hpy/universal/src/autogen_ctx_def.h

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

16 changes: 16 additions & 0 deletions test/test_number.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,22 @@

class TestNumber(HPyTest):

def test_bool_from_long(self):
mod = self.make_module("""
HPyDef_METH(f, "f", f_impl, HPyFunc_O)
static HPy f_impl(HPyContext ctx, HPy self, HPy arg)
{
long x = HPyLong_AsLong(ctx, arg);
if (HPyErr_Occurred(ctx))
return HPy_NULL;
return HPyBool_FromLong(ctx, x);
}
@EXPORT(f)
@INIT
""")
assert mod.f(0) is False
assert mod.f(42) is True

def test_unary(self):
import pytest
import operator
Expand Down
33 changes: 33 additions & 0 deletions test/test_object.py
Original file line number Diff line number Diff line change
Expand Up @@ -477,3 +477,36 @@ def test_dump(self):
@INIT
""")
mod.f('hello')

def test_type(self):
mod = self.make_module("""
HPyDef_METH(f, "f", f_impl, HPyFunc_O)
static HPy f_impl(HPyContext ctx, HPy self, HPy arg)
{
return HPy_Type(ctx, arg);
}
@EXPORT(f)
@INIT
""")
assert mod.f('hello') is str
assert mod.f(42) is int

def test_typecheck(self):
mod = self.make_module("""
HPyDef_METH(f, "f", f_impl, HPyFunc_VARARGS)
static HPy f_impl(HPyContext ctx, HPy self, HPy *args, HPy_ssize_t nargs)
{
HPy a, b;
if (!HPyArg_Parse(ctx, NULL, args, nargs, "OO", &a, &b))
return HPy_NULL;
int res = HPy_TypeCheck(ctx, a, b);
return HPyBool_FromLong(ctx, res);
}
@EXPORT(f)
@INIT
""")
class MyStr(str):
pass
assert mod.f('hello', str)
assert not mod.f('hello', int)
assert mod.f(MyStr('hello'), str)