diff --git a/docs/api-reference/function-index.rst b/docs/api-reference/function-index.rst index 01f41d74..9c4014bb 100644 --- a/docs/api-reference/function-index.rst +++ b/docs/api-reference/function-index.rst @@ -118,6 +118,7 @@ HPy Core API Function Index * :c:func:`HPy_DelItem` * :c:func:`HPy_DelItem_i` * :c:func:`HPy_DelItem_s` +* :c:func:`HPy_DelSlice` * :c:func:`HPy_Divmod` * :c:func:`HPy_Dup` * :c:func:`HPy_EvalCode` @@ -130,6 +131,7 @@ HPy Core API Function Index * :c:func:`HPy_GetItem` * :c:func:`HPy_GetItem_i` * :c:func:`HPy_GetItem_s` +* :c:func:`HPy_GetSlice` * :c:func:`HPy_HasAttr` * :c:func:`HPy_HasAttr_s` * :c:func:`HPy_Hash` @@ -172,6 +174,7 @@ HPy Core API Function Index * :c:func:`HPy_SetItem` * :c:func:`HPy_SetItem_i` * :c:func:`HPy_SetItem_s` +* :c:func:`HPy_SetSlice` * :c:func:`HPy_Str` * :c:func:`HPy_Subtract` * :c:func:`HPy_TrueDivide` diff --git a/docs/api-reference/hpy-object.rst b/docs/api-reference/hpy-object.rst index 57f62de2..eeb5a654 100644 --- a/docs/api-reference/hpy-object.rst +++ b/docs/api-reference/hpy-object.rst @@ -2,4 +2,4 @@ HPy Object ========== .. autocmodule:: autogen/public_api.h - :members: HPy_IsTrue,HPy_GetAttr,HPy_GetAttr_s,HPy_HasAttr,HPy_HasAttr_s,HPy_SetAttr,HPy_SetAttr_s,HPy_GetItem,HPy_GetItem_s,HPy_GetItem_i,HPy_SetItem,HPy_SetItem_s,HPy_SetItem_i,HPy_DelItem,HPy_DelItem_s,HPy_DelItem_i,HPy_Type,HPy_TypeCheck,HPy_Is,HPy_Repr,HPy_Str,HPy_ASCII,HPy_Bytes,HPy_RichCompare,HPy_RichCompareBool,HPy_Hash,HPy_SetCallFunction + :members: HPy_IsTrue,HPy_GetAttr,HPy_GetAttr_s,HPy_HasAttr,HPy_HasAttr_s,HPy_SetAttr,HPy_SetAttr_s,HPy_GetItem,HPy_GetItem_s,HPy_GetItem_i,HPy_GetSlice,HPy_SetItem,HPy_SetItem_s,HPy_SetItem_i,HPy_SetSlice,HPy_DelItem,HPy_DelItem_s,HPy_DelItem_i,HPy_DelSlice,HPy_Type,HPy_TypeCheck,HPy_Is,HPy_Repr,HPy_Str,HPy_ASCII,HPy_Bytes,HPy_RichCompare,HPy_RichCompareBool,HPy_Hash,HPy_SetCallFunction diff --git a/docs/porting-guide.rst b/docs/porting-guide.rst index 2cad0be3..70d3e8f6 100644 --- a/docs/porting-guide.rst +++ b/docs/porting-guide.rst @@ -269,6 +269,9 @@ with the code for the :term:`CPython ABI` mode, so it is guaranteed to be correc `PyObject_Vectorcall `_ :c:func:`HPy_Call` `PyObject_VectorcallMethod `_ :c:func:`HPy_CallMethod` `PySequence_Contains `_ :c:func:`HPy_Contains` + `PySequence_DelSlice `_ :c:func:`HPy_DelSlice` + `PySequence_GetSlice `_ :c:func:`HPy_GetSlice` + `PySequence_SetSlice `_ :c:func:`HPy_SetSlice` `PySlice_AdjustIndices `_ :c:func:`HPySlice_AdjustIndices` `PySlice_Unpack `_ :c:func:`HPySlice_Unpack` `PyTuple_Check `_ :c:func:`HPyTuple_Check` diff --git a/hpy/debug/src/autogen_debug_ctx_init.h b/hpy/debug/src/autogen_debug_ctx_init.h index cb4256e2..598e7a3f 100644 --- a/hpy/debug/src/autogen_debug_ctx_init.h +++ b/hpy/debug/src/autogen_debug_ctx_init.h @@ -96,13 +96,16 @@ int debug_ctx_SetAttr_s(HPyContext *dctx, DHPy obj, const char *utf8_name, DHPy DHPy debug_ctx_GetItem(HPyContext *dctx, DHPy obj, DHPy key); DHPy debug_ctx_GetItem_i(HPyContext *dctx, DHPy obj, HPy_ssize_t idx); DHPy debug_ctx_GetItem_s(HPyContext *dctx, DHPy obj, const char *utf8_key); +DHPy debug_ctx_GetSlice(HPyContext *dctx, DHPy obj, HPy_ssize_t start, HPy_ssize_t end); int debug_ctx_Contains(HPyContext *dctx, DHPy container, DHPy key); 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 *utf8_key, DHPy value); +int debug_ctx_SetSlice(HPyContext *dctx, DHPy obj, HPy_ssize_t start, HPy_ssize_t end, DHPy value); int debug_ctx_DelItem(HPyContext *dctx, DHPy obj, DHPy key); int debug_ctx_DelItem_i(HPyContext *dctx, DHPy obj, HPy_ssize_t idx); int debug_ctx_DelItem_s(HPyContext *dctx, DHPy obj, const char *utf8_key); +int debug_ctx_DelSlice(HPyContext *dctx, DHPy obj, HPy_ssize_t start, HPy_ssize_t end); DHPy debug_ctx_Type(HPyContext *dctx, DHPy obj); int debug_ctx_TypeCheck(HPyContext *dctx, DHPy obj, DHPy type); const char *debug_ctx_Type_GetName(HPyContext *dctx, DHPy type); @@ -365,13 +368,16 @@ static inline void debug_ctx_init_fields(HPyContext *dctx, HPyContext *uctx) dctx->ctx_GetItem = &debug_ctx_GetItem; dctx->ctx_GetItem_i = &debug_ctx_GetItem_i; dctx->ctx_GetItem_s = &debug_ctx_GetItem_s; + dctx->ctx_GetSlice = &debug_ctx_GetSlice; dctx->ctx_Contains = &debug_ctx_Contains; dctx->ctx_SetItem = &debug_ctx_SetItem; dctx->ctx_SetItem_i = &debug_ctx_SetItem_i; dctx->ctx_SetItem_s = &debug_ctx_SetItem_s; + dctx->ctx_SetSlice = &debug_ctx_SetSlice; dctx->ctx_DelItem = &debug_ctx_DelItem; dctx->ctx_DelItem_i = &debug_ctx_DelItem_i; dctx->ctx_DelItem_s = &debug_ctx_DelItem_s; + dctx->ctx_DelSlice = &debug_ctx_DelSlice; dctx->ctx_Type = &debug_ctx_Type; dctx->ctx_TypeCheck = &debug_ctx_TypeCheck; dctx->ctx_Type_GetName = &debug_ctx_Type_GetName; diff --git a/hpy/debug/src/autogen_debug_wrappers.c b/hpy/debug/src/autogen_debug_wrappers.c index 7d155608..87b73384 100644 --- a/hpy/debug/src/autogen_debug_wrappers.c +++ b/hpy/debug/src/autogen_debug_wrappers.c @@ -1007,6 +1007,18 @@ DHPy debug_ctx_GetItem_s(HPyContext *dctx, DHPy obj, const char *utf8_key) return DHPy_open(dctx, universal_result); } +DHPy debug_ctx_GetSlice(HPyContext *dctx, DHPy obj, HPy_ssize_t start, HPy_ssize_t end) +{ + if (!get_ctx_info(dctx)->is_valid) { + report_invalid_debug_context(); + } + HPy dh_obj = DHPy_unwrap(dctx, obj); + get_ctx_info(dctx)->is_valid = false; + HPy universal_result = HPy_GetSlice(get_info(dctx)->uctx, dh_obj, start, end); + get_ctx_info(dctx)->is_valid = true; + return DHPy_open(dctx, universal_result); +} + int debug_ctx_Contains(HPyContext *dctx, DHPy container, DHPy key) { if (!get_ctx_info(dctx)->is_valid) { @@ -1060,6 +1072,19 @@ int debug_ctx_SetItem_s(HPyContext *dctx, DHPy obj, const char *utf8_key, DHPy v return universal_result; } +int debug_ctx_SetSlice(HPyContext *dctx, DHPy obj, HPy_ssize_t start, HPy_ssize_t end, DHPy value) +{ + if (!get_ctx_info(dctx)->is_valid) { + report_invalid_debug_context(); + } + HPy dh_obj = DHPy_unwrap(dctx, obj); + HPy dh_value = DHPy_unwrap(dctx, value); + get_ctx_info(dctx)->is_valid = false; + int universal_result = HPy_SetSlice(get_info(dctx)->uctx, dh_obj, start, end, dh_value); + get_ctx_info(dctx)->is_valid = true; + return universal_result; +} + int debug_ctx_DelItem(HPyContext *dctx, DHPy obj, DHPy key) { if (!get_ctx_info(dctx)->is_valid) { @@ -1097,6 +1122,18 @@ int debug_ctx_DelItem_s(HPyContext *dctx, DHPy obj, const char *utf8_key) return universal_result; } +int debug_ctx_DelSlice(HPyContext *dctx, DHPy obj, HPy_ssize_t start, HPy_ssize_t end) +{ + if (!get_ctx_info(dctx)->is_valid) { + report_invalid_debug_context(); + } + HPy dh_obj = DHPy_unwrap(dctx, obj); + get_ctx_info(dctx)->is_valid = false; + int universal_result = HPy_DelSlice(get_info(dctx)->uctx, dh_obj, start, end); + get_ctx_info(dctx)->is_valid = true; + return universal_result; +} + DHPy debug_ctx_Type(HPyContext *dctx, DHPy obj) { if (!get_ctx_info(dctx)->is_valid) { diff --git a/hpy/devel/include/hpy/cpython/autogen_api_impl.h b/hpy/devel/include/hpy/cpython/autogen_api_impl.h index 85653b03..95d6b053 100644 --- a/hpy/devel/include/hpy/cpython/autogen_api_impl.h +++ b/hpy/devel/include/hpy/cpython/autogen_api_impl.h @@ -339,6 +339,11 @@ HPyAPI_FUNC HPy HPy_GetItem(HPyContext *ctx, HPy obj, HPy key) return _py2h(PyObject_GetItem(_h2py(obj), _h2py(key))); } +HPyAPI_FUNC HPy HPy_GetSlice(HPyContext *ctx, HPy obj, HPy_ssize_t start, HPy_ssize_t end) +{ + return _py2h(PySequence_GetSlice(_h2py(obj), start, end)); +} + HPyAPI_FUNC int HPy_Contains(HPyContext *ctx, HPy container, HPy key) { return PySequence_Contains(_h2py(container), _h2py(key)); @@ -349,11 +354,21 @@ HPyAPI_FUNC int HPy_SetItem(HPyContext *ctx, HPy obj, HPy key, HPy value) return PyObject_SetItem(_h2py(obj), _h2py(key), _h2py(value)); } +HPyAPI_FUNC int HPy_SetSlice(HPyContext *ctx, HPy obj, HPy_ssize_t start, HPy_ssize_t end, HPy value) +{ + return PySequence_SetSlice(_h2py(obj), start, end, _h2py(value)); +} + HPyAPI_FUNC int HPy_DelItem(HPyContext *ctx, HPy obj, HPy key) { return PyObject_DelItem(_h2py(obj), _h2py(key)); } +HPyAPI_FUNC int HPy_DelSlice(HPyContext *ctx, HPy obj, HPy_ssize_t start, HPy_ssize_t end) +{ + return PySequence_DelSlice(_h2py(obj), start, end); +} + HPyAPI_FUNC HPy HPy_Type(HPyContext *ctx, HPy obj) { return _py2h(PyObject_Type(_h2py(obj))); diff --git a/hpy/devel/include/hpy/universal/autogen_ctx.h b/hpy/devel/include/hpy/universal/autogen_ctx.h index 63be5011..60ae238d 100644 --- a/hpy/devel/include/hpy/universal/autogen_ctx.h +++ b/hpy/devel/include/hpy/universal/autogen_ctx.h @@ -280,4 +280,7 @@ struct _HPyContext_s { HPy h_DictType; void *(*ctx_AsStruct_Dict)(HPyContext *ctx, HPy h); int (*ctx_List_Insert)(HPyContext *ctx, HPy h_list, HPy_ssize_t index, HPy h_item); + HPy (*ctx_GetSlice)(HPyContext *ctx, HPy obj, HPy_ssize_t start, HPy_ssize_t end); + int (*ctx_SetSlice)(HPyContext *ctx, HPy obj, HPy_ssize_t start, HPy_ssize_t end, HPy value); + int (*ctx_DelSlice)(HPyContext *ctx, HPy obj, HPy_ssize_t start, HPy_ssize_t end); }; diff --git a/hpy/devel/include/hpy/universal/autogen_trampolines.h b/hpy/devel/include/hpy/universal/autogen_trampolines.h index 9edeaba5..4d10e132 100644 --- a/hpy/devel/include/hpy/universal/autogen_trampolines.h +++ b/hpy/devel/include/hpy/universal/autogen_trampolines.h @@ -350,6 +350,10 @@ HPyAPI_FUNC HPy HPy_GetItem_s(HPyContext *ctx, HPy obj, const char *utf8_key) { return ctx->ctx_GetItem_s ( ctx, obj, utf8_key ); } +HPyAPI_FUNC HPy HPy_GetSlice(HPyContext *ctx, HPy obj, HPy_ssize_t start, HPy_ssize_t end) { + return ctx->ctx_GetSlice ( ctx, obj, start, end ); +} + HPyAPI_FUNC int HPy_Contains(HPyContext *ctx, HPy container, HPy key) { return ctx->ctx_Contains ( ctx, container, key ); } @@ -366,6 +370,10 @@ HPyAPI_FUNC int HPy_SetItem_s(HPyContext *ctx, HPy obj, const char *utf8_key, HP return ctx->ctx_SetItem_s ( ctx, obj, utf8_key, value ); } +HPyAPI_FUNC int HPy_SetSlice(HPyContext *ctx, HPy obj, HPy_ssize_t start, HPy_ssize_t end, HPy value) { + return ctx->ctx_SetSlice ( ctx, obj, start, end, value ); +} + HPyAPI_FUNC int HPy_DelItem(HPyContext *ctx, HPy obj, HPy key) { return ctx->ctx_DelItem ( ctx, obj, key ); } @@ -378,6 +386,10 @@ HPyAPI_FUNC int HPy_DelItem_s(HPyContext *ctx, HPy obj, const char *utf8_key) { return ctx->ctx_DelItem_s ( ctx, obj, utf8_key ); } +HPyAPI_FUNC int HPy_DelSlice(HPyContext *ctx, HPy obj, HPy_ssize_t start, HPy_ssize_t end) { + return ctx->ctx_DelSlice ( ctx, obj, start, end ); +} + HPyAPI_FUNC HPy HPy_Type(HPyContext *ctx, HPy obj) { return ctx->ctx_Type ( ctx, obj ); } diff --git a/hpy/tools/autogen/conf.py b/hpy/tools/autogen/conf.py index 07a47028..793eafb1 100644 --- a/hpy/tools/autogen/conf.py +++ b/hpy/tools/autogen/conf.py @@ -32,12 +32,15 @@ 'HPy_GetItem': 'PyObject_GetItem', 'HPy_GetItem_i': None, 'HPy_GetItem_s': None, + 'HPy_GetSlice': 'PySequence_GetSlice', 'HPy_SetItem': 'PyObject_SetItem', 'HPy_SetItem_i': None, 'HPy_SetItem_s': None, + 'HPy_SetSlice': 'PySequence_SetSlice', 'HPy_DelItem': 'PyObject_DelItem', 'HPy_DelItem_i': None, 'HPy_DelItem_s': None, + 'HPy_DelSlice': 'PySequence_DelSlice', 'HPy_Contains': 'PySequence_Contains', 'HPy_Length': 'PyObject_Length', 'HPy_CallTupleDict': None, diff --git a/hpy/tools/autogen/public_api.h b/hpy/tools/autogen/public_api.h index 972f0ffc..78286fcf 100644 --- a/hpy/tools/autogen/public_api.h +++ b/hpy/tools/autogen/public_api.h @@ -419,6 +419,27 @@ HPy HPy_GetItem_i(HPyContext *ctx, HPy obj, HPy_ssize_t idx); HPy_ID(160) HPy HPy_GetItem_s(HPyContext *ctx, HPy obj, const char *utf8_key); +/** + * Return the slice of sequence object ``obj`` between ``start`` and ``end``. + * This is the equivalent of the Python expression ``obj[start:end]``. + * + * :param ctx: + * The execution context. + * :param obj: + * A sliceable Python object (must not be ``HPy_NULL`` otherwise a + * ``SystemError`` will be raised). If the object is not sliceable, a + * ``TypeError`` will be raised. + * :param start: + * The start index (inclusive). + * :param end: + * The end index (exclusive). + * + * :returns: + * The requested slice or ``HPy_NULL`` on failure. + */ +HPy_ID(266) +HPy HPy_GetSlice(HPyContext *ctx, HPy obj, HPy_ssize_t start, HPy_ssize_t end); + HPy_ID(161) int HPy_Contains(HPyContext *ctx, HPy container, HPy key); @@ -429,6 +450,30 @@ int HPy_SetItem_i(HPyContext *ctx, HPy obj, HPy_ssize_t idx, HPy value); HPy_ID(164) int HPy_SetItem_s(HPyContext *ctx, HPy obj, const char *utf8_key, HPy value); +/** + * Assign the sequence object ``value`` to the slice in sequence object ``obj`` + * from ``start`` to ``end``. This is the equivalent of the Python statement + * ``obj[start:end] = value``. + * + * :param ctx: + * The execution context. + * :param obj: + * A sliceable Python object (must not be ``HPy_NULL`` otherwise a + * ``SystemError`` will be raised). If the object is not sliceable, a + * ``TypeError`` will be raised. + * :param start: + * The start index (inclusive). + * :param end: + * The end index (exclusive). + * :param value: + * The sequence object to assign (must not be ``HPy_NULL``). + * + * :returns: + * ``0`` on success; ``-1`` on failure + */ +HPy_ID(267) +int HPy_SetSlice(HPyContext *ctx, HPy obj, HPy_ssize_t start, HPy_ssize_t end, HPy value); + HPy_ID(235) int HPy_DelItem(HPyContext *ctx, HPy obj, HPy key); HPy_ID(236) @@ -436,6 +481,27 @@ int HPy_DelItem_i(HPyContext *ctx, HPy obj, HPy_ssize_t idx); HPy_ID(237) int HPy_DelItem_s(HPyContext *ctx, HPy obj, const char *utf8_key); +/** + * Delete the slice of sequence object ``obj`` between ``start`` and ``end``. + * This is the equivalent of the Python statement ``del obj[start:end]``. + * + * :param ctx: + * The execution context. + * :param obj: + * A sliceable Python object (must not be ``HPy_NULL`` otherwise a + * ``SystemError`` will be raised). If the object is not sliceable, a + * ``TypeError`` will be raised. + * :param start: + * The start index (inclusive). + * :param end: + * The end index (exclusive). + * + * :returns: + * ``0`` on success; ``-1`` on failure + */ +HPy_ID(268) +int HPy_DelSlice(HPyContext *ctx, HPy obj, HPy_ssize_t start, HPy_ssize_t end); + /** * Returns the type of the given object ``obj``. * diff --git a/hpy/trace/src/autogen_trace_ctx_init.h b/hpy/trace/src/autogen_trace_ctx_init.h index c86ea1c6..c6453373 100644 --- a/hpy/trace/src/autogen_trace_ctx_init.h +++ b/hpy/trace/src/autogen_trace_ctx_init.h @@ -95,13 +95,16 @@ int trace_ctx_SetAttr_s(HPyContext *tctx, HPy obj, const char *utf8_name, HPy va HPy trace_ctx_GetItem(HPyContext *tctx, HPy obj, HPy key); HPy trace_ctx_GetItem_i(HPyContext *tctx, HPy obj, HPy_ssize_t idx); HPy trace_ctx_GetItem_s(HPyContext *tctx, HPy obj, const char *utf8_key); +HPy trace_ctx_GetSlice(HPyContext *tctx, HPy obj, HPy_ssize_t start, HPy_ssize_t end); int trace_ctx_Contains(HPyContext *tctx, HPy container, HPy key); int trace_ctx_SetItem(HPyContext *tctx, HPy obj, HPy key, HPy value); int trace_ctx_SetItem_i(HPyContext *tctx, HPy obj, HPy_ssize_t idx, HPy value); int trace_ctx_SetItem_s(HPyContext *tctx, HPy obj, const char *utf8_key, HPy value); +int trace_ctx_SetSlice(HPyContext *tctx, HPy obj, HPy_ssize_t start, HPy_ssize_t end, HPy value); int trace_ctx_DelItem(HPyContext *tctx, HPy obj, HPy key); int trace_ctx_DelItem_i(HPyContext *tctx, HPy obj, HPy_ssize_t idx); int trace_ctx_DelItem_s(HPyContext *tctx, HPy obj, const char *utf8_key); +int trace_ctx_DelSlice(HPyContext *tctx, HPy obj, HPy_ssize_t start, HPy_ssize_t end); HPy trace_ctx_Type(HPyContext *tctx, HPy obj); int trace_ctx_TypeCheck(HPyContext *tctx, HPy obj, HPy type); const char *trace_ctx_Type_GetName(HPyContext *tctx, HPy type); @@ -195,8 +198,8 @@ static inline void trace_ctx_init_info(HPyTraceInfo *info, HPyContext *uctx) { info->magic_number = HPY_TRACE_MAGIC; info->uctx = uctx; - info->call_counts = (uint64_t *)calloc(266, sizeof(uint64_t)); - info->durations = (_HPyTime_t *)calloc(266, sizeof(_HPyTime_t)); + info->call_counts = (uint64_t *)calloc(269, sizeof(uint64_t)); + info->durations = (_HPyTime_t *)calloc(269, sizeof(_HPyTime_t)); info->on_enter_func = HPy_NULL; info->on_exit_func = HPy_NULL; } @@ -382,13 +385,16 @@ static inline void trace_ctx_init_fields(HPyContext *tctx, HPyContext *uctx) tctx->ctx_GetItem = &trace_ctx_GetItem; tctx->ctx_GetItem_i = &trace_ctx_GetItem_i; tctx->ctx_GetItem_s = &trace_ctx_GetItem_s; + tctx->ctx_GetSlice = &trace_ctx_GetSlice; tctx->ctx_Contains = &trace_ctx_Contains; tctx->ctx_SetItem = &trace_ctx_SetItem; tctx->ctx_SetItem_i = &trace_ctx_SetItem_i; tctx->ctx_SetItem_s = &trace_ctx_SetItem_s; + tctx->ctx_SetSlice = &trace_ctx_SetSlice; tctx->ctx_DelItem = &trace_ctx_DelItem; tctx->ctx_DelItem_i = &trace_ctx_DelItem_i; tctx->ctx_DelItem_s = &trace_ctx_DelItem_s; + tctx->ctx_DelSlice = &trace_ctx_DelSlice; tctx->ctx_Type = &trace_ctx_Type; tctx->ctx_TypeCheck = &trace_ctx_TypeCheck; tctx->ctx_Type_GetName = &trace_ctx_Type_GetName; diff --git a/hpy/trace/src/autogen_trace_func_table.c b/hpy/trace/src/autogen_trace_func_table.c index a89ce893..4a239e03 100644 --- a/hpy/trace/src/autogen_trace_func_table.c +++ b/hpy/trace/src/autogen_trace_func_table.c @@ -12,7 +12,7 @@ #include "trace_internal.h" -#define TRACE_NFUNC 182 +#define TRACE_NFUNC 185 #define NO_FUNC "" static const char *trace_func_table[] = { @@ -282,6 +282,9 @@ static const char *trace_func_table[] = { NO_FUNC, "ctx_AsStruct_Dict", "ctx_List_Insert", + "ctx_GetSlice", + "ctx_SetSlice", + "ctx_DelSlice", NULL /* sentinel */ }; @@ -292,7 +295,7 @@ int hpy_trace_get_nfunc(void) const char * hpy_trace_get_func_name(int idx) { - if (idx >= 0 && idx < 266) + if (idx >= 0 && idx < 269) return trace_func_table[idx]; return NULL; } diff --git a/hpy/trace/src/autogen_trace_wrappers.c b/hpy/trace/src/autogen_trace_wrappers.c index f1b8b1bf..6f53bcdb 100644 --- a/hpy/trace/src/autogen_trace_wrappers.c +++ b/hpy/trace/src/autogen_trace_wrappers.c @@ -1110,6 +1110,19 @@ HPy trace_ctx_GetItem_s(HPyContext *tctx, HPy obj, const char *utf8_key) return res; } +HPy trace_ctx_GetSlice(HPyContext *tctx, HPy obj, HPy_ssize_t start, HPy_ssize_t end) +{ + HPyTraceInfo *info = hpy_trace_on_enter(tctx, 266); + HPyContext *uctx = info->uctx; + _HPyTime_t _ts_start, _ts_end; + _HPyClockStatus_t r0, r1; + r0 = get_monotonic_clock(&_ts_start); + HPy res = HPy_GetSlice(uctx, obj, start, end); + r1 = get_monotonic_clock(&_ts_end); + hpy_trace_on_exit(info, 266, r0, r1, &_ts_start, &_ts_end); + return res; +} + int trace_ctx_Contains(HPyContext *tctx, HPy container, HPy key) { HPyTraceInfo *info = hpy_trace_on_enter(tctx, 161); @@ -1162,6 +1175,19 @@ int trace_ctx_SetItem_s(HPyContext *tctx, HPy obj, const char *utf8_key, HPy val return res; } +int trace_ctx_SetSlice(HPyContext *tctx, HPy obj, HPy_ssize_t start, HPy_ssize_t end, HPy value) +{ + HPyTraceInfo *info = hpy_trace_on_enter(tctx, 267); + HPyContext *uctx = info->uctx; + _HPyTime_t _ts_start, _ts_end; + _HPyClockStatus_t r0, r1; + r0 = get_monotonic_clock(&_ts_start); + int res = HPy_SetSlice(uctx, obj, start, end, value); + r1 = get_monotonic_clock(&_ts_end); + hpy_trace_on_exit(info, 267, r0, r1, &_ts_start, &_ts_end); + return res; +} + int trace_ctx_DelItem(HPyContext *tctx, HPy obj, HPy key) { HPyTraceInfo *info = hpy_trace_on_enter(tctx, 235); @@ -1201,6 +1227,19 @@ int trace_ctx_DelItem_s(HPyContext *tctx, HPy obj, const char *utf8_key) return res; } +int trace_ctx_DelSlice(HPyContext *tctx, HPy obj, HPy_ssize_t start, HPy_ssize_t end) +{ + HPyTraceInfo *info = hpy_trace_on_enter(tctx, 268); + HPyContext *uctx = info->uctx; + _HPyTime_t _ts_start, _ts_end; + _HPyClockStatus_t r0, r1; + r0 = get_monotonic_clock(&_ts_start); + int res = HPy_DelSlice(uctx, obj, start, end); + r1 = get_monotonic_clock(&_ts_end); + hpy_trace_on_exit(info, 268, r0, r1, &_ts_start, &_ts_end); + return res; +} + HPy trace_ctx_Type(HPyContext *tctx, HPy obj) { HPyTraceInfo *info = hpy_trace_on_enter(tctx, 165); diff --git a/hpy/universal/src/autogen_ctx_def.h b/hpy/universal/src/autogen_ctx_def.h index e1f9a829..e49c62e7 100644 --- a/hpy/universal/src/autogen_ctx_def.h +++ b/hpy/universal/src/autogen_ctx_def.h @@ -101,13 +101,16 @@ struct _HPyContext_s g_universal_ctx = { .ctx_GetItem = &ctx_GetItem, .ctx_GetItem_i = &ctx_GetItem_i, .ctx_GetItem_s = &ctx_GetItem_s, + .ctx_GetSlice = &ctx_GetSlice, .ctx_Contains = &ctx_Contains, .ctx_SetItem = &ctx_SetItem, .ctx_SetItem_i = &ctx_SetItem_i, .ctx_SetItem_s = &ctx_SetItem_s, + .ctx_SetSlice = &ctx_SetSlice, .ctx_DelItem = &ctx_DelItem, .ctx_DelItem_i = &ctx_DelItem_i, .ctx_DelItem_s = &ctx_DelItem_s, + .ctx_DelSlice = &ctx_DelSlice, .ctx_Type = &ctx_Type, .ctx_TypeCheck = &ctx_TypeCheck, .ctx_Type_GetName = &ctx_Type_GetName, diff --git a/hpy/universal/src/autogen_ctx_impl.h b/hpy/universal/src/autogen_ctx_impl.h index b1a59972..f64a0d85 100644 --- a/hpy/universal/src/autogen_ctx_impl.h +++ b/hpy/universal/src/autogen_ctx_impl.h @@ -335,6 +335,11 @@ HPyAPI_IMPL HPy ctx_GetItem(HPyContext *ctx, HPy obj, HPy key) return _py2h(PyObject_GetItem(_h2py(obj), _h2py(key))); } +HPyAPI_IMPL HPy ctx_GetSlice(HPyContext *ctx, HPy obj, HPy_ssize_t start, HPy_ssize_t end) +{ + return _py2h(PySequence_GetSlice(_h2py(obj), start, end)); +} + HPyAPI_IMPL int ctx_Contains(HPyContext *ctx, HPy container, HPy key) { return PySequence_Contains(_h2py(container), _h2py(key)); @@ -345,11 +350,21 @@ HPyAPI_IMPL int ctx_SetItem(HPyContext *ctx, HPy obj, HPy key, HPy value) return PyObject_SetItem(_h2py(obj), _h2py(key), _h2py(value)); } +HPyAPI_IMPL int ctx_SetSlice(HPyContext *ctx, HPy obj, HPy_ssize_t start, HPy_ssize_t end, HPy value) +{ + return PySequence_SetSlice(_h2py(obj), start, end, _h2py(value)); +} + HPyAPI_IMPL int ctx_DelItem(HPyContext *ctx, HPy obj, HPy key) { return PyObject_DelItem(_h2py(obj), _h2py(key)); } +HPyAPI_IMPL int ctx_DelSlice(HPyContext *ctx, HPy obj, HPy_ssize_t start, HPy_ssize_t end) +{ + return PySequence_DelSlice(_h2py(obj), start, end); +} + HPyAPI_IMPL HPy ctx_Type(HPyContext *ctx, HPy obj) { return _py2h(PyObject_Type(_h2py(obj))); diff --git a/test/test_object.py b/test/test_object.py index 46e82e9e..10ef4f84 100644 --- a/test/test_object.py +++ b/test/test_object.py @@ -530,6 +530,54 @@ def test_getitem_s(self): with pytest.raises(TypeError): mod.f([]) + def test_getslice(self): + import pytest + mod = self.make_module(""" + HPyDef_METH(f, "f", HPyFunc_VARARGS) + static HPy f_impl(HPyContext *ctx, HPy self, const HPy *args, size_t nargs) + { + HPy seq; + HPy_ssize_t i1, i2; + if (!HPyArg_Parse(ctx, NULL, args, nargs, "Onn", &seq, &i1, &i2)) { + return HPy_NULL; + } + if (HPy_Is(ctx, seq, ctx->h_None)) { + seq = HPy_NULL; + } + return HPy_GetSlice(ctx, seq, i1, i2); + } + @EXPORT(f) + @INIT + """) + l = [1,2,3,4,5] + assert mod.f(l, 0, 5) == l + assert mod.f(l, 2, 3) == [3] + assert mod.f(l, 1, 3) == [2, 3] + + s = "hello" + assert mod.f(s, 0, 5) == "hello" + assert mod.f(s, 1, 3) == "el" + + class Sliceable: + def __getitem__(self, key): + # assume 'key' is a slice + if key.start < 0: + raise ValueError + return key.start + key.stop + + o = Sliceable() + assert mod.f(o, 5, 13) == 18 + + # test that errors are propagated + with pytest.raises(ValueError): + mod.f(o, -1, 1) + + # 'None' will be mapped to 'HPy_NULL' by the C function + with pytest.raises(SystemError): + mod.f(None, 0, 1) + with pytest.raises(TypeError): + mod.f(123, 0, 1) + def test_setitem(self): import pytest mod = self.make_module(""" @@ -603,6 +651,67 @@ def test_setitem_s(self): with pytest.raises(TypeError): mod.f([]) + def test_setslice(self): + import pytest + mod = self.make_module(""" + HPyDef_METH(f, "f", HPyFunc_VARARGS) + static HPy f_impl(HPyContext *ctx, HPy self, const HPy *args, size_t nargs) + { + int res; + HPy seq, value; + HPy_ssize_t i1, i2; + if (!HPyArg_Parse(ctx, NULL, args, nargs, "OnnO", &seq, &i1, &i2, &value)) { + return HPy_NULL; + } + if (HPy_Is(ctx, seq, ctx->h_None)) { + seq = HPy_NULL; + } + res = HPy_SetSlice(ctx, seq, i1, i2, value); + if (res == 0) { + return HPy_Dup(ctx, seq); + } else if (res == -1) { + return HPy_NULL; + } + HPyErr_SetString(ctx, ctx->h_SystemError, + "HPy_SetSlice returned an invalid result code"); + return HPy_NULL; + } + @EXPORT(f) + @INIT + """) + l = [1,2,3,4,5] + val = [11,22,33,44,55] + x = mod.f(l, 0, 5, val) + assert x is l + assert x is not val + assert l == val + + l = [1,2,3,4,5] + assert mod.f(l, 0, 5, []) == [] + + l = [1,2,3,4,5] + assert mod.f(l, 1, 3, [10, 11, 12]) == [1, 10, 11, 12, 4, 5] + + class Sliceable: + def __setitem__(self, key, value): + # assume 'key' is a slice + if key.start < 0: + raise ValueError + self.value = (key.start, key.stop, value) + + o = Sliceable() + assert mod.f(o, 5, 13, [7, 8, 9]).value == (5, 13, [7, 8, 9]) + + # test that errors are propagated + with pytest.raises(ValueError): + mod.f(o, -1, 1, []) + + # 'None' will be mapped to 'HPy_NULL' by the C function + with pytest.raises(SystemError): + mod.f(None, 0, 1, []) + with pytest.raises(TypeError): + mod.f(123, 0, 1, []) + def test_delitem(self): import pytest mod = self.make_module(""" @@ -675,6 +784,62 @@ def test_delitem(self): with pytest.raises(TypeError): mod.delitem_s3([1, 2, 3, 4]) + def test_delslice(self): + import pytest + mod = self.make_module(""" + HPyDef_METH(f, "f", HPyFunc_VARARGS) + static HPy f_impl(HPyContext *ctx, HPy self, const HPy *args, size_t nargs) + { + int res; + HPy seq; + HPy_ssize_t i1, i2; + if (!HPyArg_Parse(ctx, NULL, args, nargs, "Onn", &seq, &i1, &i2)) { + return HPy_NULL; + } + if (HPy_Is(ctx, seq, ctx->h_None)) { + seq = HPy_NULL; + } + res = HPy_DelSlice(ctx, seq, i1, i2); + if (res == 0) { + return HPy_Dup(ctx, seq); + } else if (res == -1) { + return HPy_NULL; + } + HPyErr_SetString(ctx, ctx->h_SystemError, + "HPy_DelSlice returned an invalid result code"); + return HPy_NULL; + } + @EXPORT(f) + @INIT + """) + l = [1,2,3,4,5] + x = mod.f(l, 0, 5) + assert x is l + assert l == [] + + l = [1,2,3,4,5] + assert mod.f(l, 1, 3) == [1, 4, 5] + + class Sliceable: + def __delitem__(self, key): + # assume 'key' is a slice + if key.start < 0: + raise ValueError + self.value = key.start + key.stop + + o = Sliceable() + assert mod.f(o, 5, 13).value == 18 + + # test that errors are propagated + with pytest.raises(ValueError): + mod.f(o, -1, 1) + + # 'None' will be mapped to 'HPy_NULL' by the C function + with pytest.raises(SystemError): + mod.f(None, 0, 1) + with pytest.raises(TypeError): + mod.f(123, 0, 1) + def test_length(self): mod = self.make_module(""" HPyDef_METH(f, "f", HPyFunc_O)