From 5fe94f9c646a0eaad64fab4d0532b0f0002f6c63 Mon Sep 17 00:00:00 2001 From: Florian Angerer Date: Mon, 21 Mar 2022 10:37:02 +0100 Subject: [PATCH 1/2] Extend HPy_TypeCheck to allow exact type checks --- hpy/debug/src/_debugmod.c | 2 +- hpy/debug/src/autogen_debug_ctx_init.h | 2 +- hpy/debug/src/autogen_debug_wrappers.c | 4 ++-- hpy/devel/include/hpy/cpython/misc.h | 4 ++-- hpy/devel/include/hpy/runtime/ctx_funcs.h | 2 +- hpy/devel/include/hpy/universal/autogen_ctx.h | 2 +- .../include/hpy/universal/autogen_trampolines.h | 4 ++-- hpy/devel/src/runtime/ctx_object.c | 5 ++++- hpy/tools/autogen/public_api.h | 2 +- test/test_object.py | 15 ++++++++++----- 10 files changed, 25 insertions(+), 17 deletions(-) diff --git a/hpy/debug/src/_debugmod.c b/hpy/debug/src/_debugmod.c index 0b9b0a4db..cf933fab2 100644 --- a/hpy/debug/src/_debugmod.c +++ b/hpy/debug/src/_debugmod.c @@ -230,7 +230,7 @@ HPyDef_SLOT(DebugHandle_cmp, DebugHandle_cmp_impl, HPy_tp_richcompare) static UHPy DebugHandle_cmp_impl(HPyContext *uctx, UHPy self, UHPy o, HPy_RichCmpOp op) { UHPy T = HPy_Type(uctx, self); - if (!HPy_TypeCheck(uctx, o, T)) + if (!HPy_TypeCheck(uctx, o, T, 0)) return HPy_Dup(uctx, uctx->h_NotImplemented); DebugHandleObject *dh_self = DebugHandleObject_AsStruct(uctx, self); DebugHandleObject *dh_o = DebugHandleObject_AsStruct(uctx, o); diff --git a/hpy/debug/src/autogen_debug_ctx_init.h b/hpy/debug/src/autogen_debug_ctx_init.h index 63ebae53d..cea80fdb7 100644 --- a/hpy/debug/src/autogen_debug_ctx_init.h +++ b/hpy/debug/src/autogen_debug_ctx_init.h @@ -100,7 +100,7 @@ int debug_ctx_SetItem(HPyContext *dctx, DHPy obj, DHPy key, DHPy value); int debug_ctx_SetItem_i(HPyContext *dctx, DHPy obj, HPy_ssize_t idx, DHPy value); int debug_ctx_SetItem_s(HPyContext *dctx, DHPy obj, const char *key, DHPy value); DHPy debug_ctx_Type(HPyContext *dctx, DHPy obj); -int debug_ctx_TypeCheck(HPyContext *dctx, DHPy obj, DHPy type); +int debug_ctx_TypeCheck(HPyContext *dctx, DHPy obj, DHPy type, int exact); int debug_ctx_Is(HPyContext *dctx, DHPy obj, DHPy other); void *debug_ctx_AsStruct(HPyContext *dctx, DHPy h); void *debug_ctx_AsStructLegacy(HPyContext *dctx, DHPy h); diff --git a/hpy/debug/src/autogen_debug_wrappers.c b/hpy/debug/src/autogen_debug_wrappers.c index f18b1bb8f..44bab8c23 100644 --- a/hpy/debug/src/autogen_debug_wrappers.c +++ b/hpy/debug/src/autogen_debug_wrappers.c @@ -447,9 +447,9 @@ DHPy debug_ctx_Type(HPyContext *dctx, DHPy obj) return DHPy_open(dctx, HPy_Type(get_info(dctx)->uctx, DHPy_unwrap(dctx, obj))); } -int debug_ctx_TypeCheck(HPyContext *dctx, DHPy obj, DHPy type) +int debug_ctx_TypeCheck(HPyContext *dctx, DHPy obj, DHPy type, int exact) { - return HPy_TypeCheck(get_info(dctx)->uctx, DHPy_unwrap(dctx, obj), DHPy_unwrap(dctx, type)); + return HPy_TypeCheck(get_info(dctx)->uctx, DHPy_unwrap(dctx, obj), DHPy_unwrap(dctx, type), exact); } int debug_ctx_Is(HPyContext *dctx, DHPy obj, DHPy other) diff --git a/hpy/devel/include/hpy/cpython/misc.h b/hpy/devel/include/hpy/cpython/misc.h index d2befe9c6..a7660d386 100644 --- a/hpy/devel/include/hpy/cpython/misc.h +++ b/hpy/devel/include/hpy/cpython/misc.h @@ -324,9 +324,9 @@ HPyAPI_FUNC void _HPy_Dump(HPyContext *ctx, HPy h) ctx_Dump(ctx, h); } -HPyAPI_FUNC int HPy_TypeCheck(HPyContext *ctx, HPy h_obj, HPy h_type) +HPyAPI_FUNC int HPy_TypeCheck(HPyContext *ctx, HPy h_obj, HPy h_type, int exact) { - return ctx_TypeCheck(ctx, h_obj, h_type); + return ctx_TypeCheck(ctx, h_obj, h_type, exact); } HPyAPI_FUNC int HPy_Is(HPyContext *ctx, HPy h_obj, HPy h_other) diff --git a/hpy/devel/include/hpy/runtime/ctx_funcs.h b/hpy/devel/include/hpy/runtime/ctx_funcs.h index dee5f214f..c523a8cb1 100644 --- a/hpy/devel/include/hpy/runtime/ctx_funcs.h +++ b/hpy/devel/include/hpy/runtime/ctx_funcs.h @@ -29,7 +29,7 @@ _HPy_HIDDEN HPy ctx_Module_Create(HPyContext *ctx, HPyModuleDef *hpydef); // ctx_object.c _HPy_HIDDEN void ctx_Dump(HPyContext *ctx, HPy h); -_HPy_HIDDEN int ctx_TypeCheck(HPyContext *ctx, HPy h_obj, HPy h_type); +_HPy_HIDDEN int ctx_TypeCheck(HPyContext *ctx, HPy h_obj, HPy h_type, int exact); _HPy_HIDDEN int ctx_Is(HPyContext *ctx, HPy h_obj, HPy h_other); _HPy_HIDDEN HPy ctx_GetItem_i(HPyContext *ctx, HPy obj, HPy_ssize_t idx); _HPy_HIDDEN HPy ctx_GetItem_s(HPyContext *ctx, HPy obj, const char *key); diff --git a/hpy/devel/include/hpy/universal/autogen_ctx.h b/hpy/devel/include/hpy/universal/autogen_ctx.h index 08b66ecf9..36d4fa12f 100644 --- a/hpy/devel/include/hpy/universal/autogen_ctx.h +++ b/hpy/devel/include/hpy/universal/autogen_ctx.h @@ -181,7 +181,7 @@ struct _HPyContext_s { int (*ctx_SetItem_i)(HPyContext *ctx, HPy obj, HPy_ssize_t idx, HPy value); int (*ctx_SetItem_s)(HPyContext *ctx, HPy obj, const char *key, HPy value); HPy (*ctx_Type)(HPyContext *ctx, HPy obj); - int (*ctx_TypeCheck)(HPyContext *ctx, HPy obj, HPy type); + int (*ctx_TypeCheck)(HPyContext *ctx, HPy obj, HPy type, int exact); int (*ctx_Is)(HPyContext *ctx, HPy obj, HPy other); void *(*ctx_AsStruct)(HPyContext *ctx, HPy h); void *(*ctx_AsStructLegacy)(HPyContext *ctx, HPy h); diff --git a/hpy/devel/include/hpy/universal/autogen_trampolines.h b/hpy/devel/include/hpy/universal/autogen_trampolines.h index 6a4e4c435..33c9c62e9 100644 --- a/hpy/devel/include/hpy/universal/autogen_trampolines.h +++ b/hpy/devel/include/hpy/universal/autogen_trampolines.h @@ -366,8 +366,8 @@ HPyAPI_FUNC HPy HPy_Type(HPyContext *ctx, HPy obj) { return ctx->ctx_Type ( ctx, obj ); } -HPyAPI_FUNC int HPy_TypeCheck(HPyContext *ctx, HPy obj, HPy type) { - return ctx->ctx_TypeCheck ( ctx, obj, type ); +HPyAPI_FUNC int HPy_TypeCheck(HPyContext *ctx, HPy obj, HPy type, int exact) { + return ctx->ctx_TypeCheck ( ctx, obj, type, exact ); } HPyAPI_FUNC int HPy_Is(HPyContext *ctx, HPy obj, HPy other) { diff --git a/hpy/devel/src/runtime/ctx_object.c b/hpy/devel/src/runtime/ctx_object.c index 706d486ec..99b03c1a2 100644 --- a/hpy/devel/src/runtime/ctx_object.c +++ b/hpy/devel/src/runtime/ctx_object.c @@ -29,13 +29,16 @@ ctx_Dump(HPyContext *ctx, HPy h) do the check only in debug mode. */ _HPy_HIDDEN int -ctx_TypeCheck(HPyContext *ctx, HPy h_obj, HPy h_type) +ctx_TypeCheck(HPyContext *ctx, HPy h_obj, HPy h_type, int exact) { PyObject *type= _h2py(h_type); assert(type != NULL); if (!PyType_Check(type)) { Py_FatalError("HPy_TypeCheck arg 2 must be a type"); } + if (exact) { + return Py_TYPE(_h2py(h_obj)) == (PyTypeObject*)type; + } return PyObject_TypeCheck(_h2py(h_obj), (PyTypeObject*)type); } diff --git a/hpy/tools/autogen/public_api.h b/hpy/tools/autogen/public_api.h index 969ab5488..d829d606c 100644 --- a/hpy/tools/autogen/public_api.h +++ b/hpy/tools/autogen/public_api.h @@ -226,7 +226,7 @@ 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); +int HPy_TypeCheck(HPyContext *ctx, HPy obj, HPy type, int exact); int HPy_Is(HPyContext *ctx, HPy obj, HPy other); diff --git a/test/test_object.py b/test/test_object.py index 739aec5a9..c807a30f9 100644 --- a/test/test_object.py +++ b/test/test_object.py @@ -546,9 +546,10 @@ def test_typecheck(self): 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)) + int exact; + if (!HPyArg_Parse(ctx, NULL, args, nargs, "OOi", &a, &b, &exact)) return HPy_NULL; - int res = HPy_TypeCheck(ctx, a, b); + int res = HPy_TypeCheck(ctx, a, b, exact); return HPyBool_FromLong(ctx, res); } @EXPORT(f) @@ -556,9 +557,13 @@ def test_typecheck(self): """) class MyStr(str): pass - assert mod.f('hello', str) - assert not mod.f('hello', int) - assert mod.f(MyStr('hello'), str) + assert mod.f('hello', str, False) + assert not mod.f('hello', int, False) + assert mod.f(MyStr('hello'), str, False) + + assert mod.f('hello', str, True) + assert not mod.f('hello', int, True) + assert not mod.f(MyStr('hello'), str, True) def test_is(self): mod = self.make_module(""" From 4ce5125f937ebd2694f9a942e483f8fe6c45e791 Mon Sep 17 00:00:00 2001 From: Florian Angerer Date: Thu, 24 Mar 2022 13:16:46 +0100 Subject: [PATCH 2/2] Add description for HPy handle impl on GraalPython --- hpy/devel/include/hpy.h | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/hpy/devel/include/hpy.h b/hpy/devel/include/hpy.h index 4f063e374..2c509f800 100644 --- a/hpy/devel/include/hpy.h +++ b/hpy/devel/include/hpy.h @@ -104,7 +104,8 @@ extern "C" { - PyPy: ._i is an index into a list - - GraalPython: ??? + - GraalPython: _i is an index into a list (may be optimized to a direct + reference depending on the runtime options and control flow) - Debug mode: _i is a pointer to a DebugHandle, which contains a another HPy among other stuff