Skip to content

Commit

Permalink
Merge pull request hpyproject#300 from fangerer/fa/add_mp_slots
Browse files Browse the repository at this point in the history
Enable and test slots HPy_mp_*
  • Loading branch information
fangerer authored Mar 7, 2022
2 parents 9b5d200 + 3b75b8e commit 4e7dfbf
Show file tree
Hide file tree
Showing 5 changed files with 141 additions and 8 deletions.
14 changes: 12 additions & 2 deletions hpy/debug/src/debug_ctx.c
Original file line number Diff line number Diff line change
Expand Up @@ -121,9 +121,19 @@ void debug_ctx_Close(HPyContext *dctx, DHPy dh)
const char *debug_ctx_Unicode_AsUTF8AndSize(HPyContext *dctx, DHPy h, HPy_ssize_t *size)
{
const char *ptr = HPyUnicode_AsUTF8AndSize(get_info(dctx)->uctx, DHPy_unwrap(dctx, h), size);
HPy_ssize_t data_size = *size + 1;
char* new_ptr = (char*) raw_data_copy(ptr, data_size, true);
DebugHandle *handle = as_DebugHandle(h);
HPy_ssize_t data_size;
char* new_ptr;
if (ptr != NULL)
{
data_size = size != NULL ? *size + 1 : strlen(ptr) + 1;
new_ptr = (char*) raw_data_copy(ptr, data_size, true);
}
else
{
data_size = 0;
new_ptr = NULL;
}
handle->associated_data = new_ptr;
handle->associated_data_size = data_size;
return new_ptr;
Expand Down
6 changes: 6 additions & 0 deletions hpy/devel/include/hpy/autogen_hpyslot.h

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

6 changes: 3 additions & 3 deletions hpy/tools/autogen/public_api.h
Original file line number Diff line number Diff line change
Expand Up @@ -417,9 +417,9 @@ typedef void (*HPyFunc_destroyfunc)(void *);
typedef enum {
HPy_bf_getbuffer = SLOT(1, HPyFunc_GETBUFFERPROC),
HPy_bf_releasebuffer = SLOT(2, HPyFunc_RELEASEBUFFERPROC),
//HPy_mp_ass_subscript = SLOT(3, HPyFunc_X),
//HPy_mp_length = SLOT(4, HPyFunc_X),
//HPy_mp_subscript = SLOT(5, HPyFunc_X),
HPy_mp_ass_subscript = SLOT(3, HPyFunc_OBJOBJARGPROC),
HPy_mp_length = SLOT(4, HPyFunc_LENFUNC),
HPy_mp_subscript = SLOT(5, HPyFunc_BINARYFUNC),
HPy_nb_absolute = SLOT(6, HPyFunc_UNARYFUNC),
HPy_nb_add = SLOT(7, HPyFunc_BINARYFUNC),
HPy_nb_and = SLOT(8, HPyFunc_BINARYFUNC),
Expand Down
30 changes: 27 additions & 3 deletions test/test_hpyunicode.py
Original file line number Diff line number Diff line change
Expand Up @@ -100,21 +100,45 @@ def test_AsLatin1String(self):

def test_AsUTF8AndSize(self):
mod = self.make_module("""
HPyDef_METH(f, "f", f_impl, HPyFunc_O)
static HPy f_impl(HPyContext *ctx, HPy self, HPy arg)
#include <string.h>
static HPy as_utf8_and_size(HPyContext *ctx, HPy arg, HPy_ssize_t *size)
{
HPy_ssize_t n;
const char* buf = HPyUnicode_AsUTF8AndSize(ctx, arg, &n);
const char* buf = HPyUnicode_AsUTF8AndSize(ctx, arg, size);
long res = 0;
if (size)
n = *size;
else
n = strlen(buf);
for(int i=0; i<n; i++)
res = (res * 10) + buf[i];
return HPyLong_FromLong(ctx, res);
}
HPyDef_METH(f, "f", f_impl, HPyFunc_O)
static HPy f_impl(HPyContext *ctx, HPy self, HPy arg)
{
HPy_ssize_t n;
return as_utf8_and_size(ctx, arg, &n);
}
HPyDef_METH(g, "g", g_impl, HPyFunc_O)
static HPy g_impl(HPyContext *ctx, HPy self, HPy arg)
{
return as_utf8_and_size(ctx, arg, NULL);
}
@EXPORT(f)
@EXPORT(g)
@INIT
""")
assert mod.f('ABC') == 100*ord('A') + 10*ord('B') + ord('C')
assert mod.f(b'A\0C'.decode('utf-8')) == 100*ord('A') + ord('C')
assert mod.g('ABC') == 100*ord('A') + 10*ord('B') + ord('C')
assert mod.g(b'A'.decode('utf-8')) == ord('A')
assert mod.g(b'A\0'.decode('utf-8')) == ord('A')

def test_DecodeLatin1(self):
mod = self.make_module("""
Expand Down
93 changes: 93 additions & 0 deletions test/test_slots.py
Original file line number Diff line number Diff line change
Expand Up @@ -428,6 +428,99 @@ class TestSqSlots(HPyTest):

ExtensionTemplate = PointTemplate

def test_mp_subscript_and_mp_length(self):
mod = self.make_module("""
@DEFINE_PointObject
HPyDef_SLOT(Point_getitem, Point_getitem_impl, HPy_mp_subscript);
static HPy Point_getitem_impl(HPyContext *ctx, HPy self, HPy key)
{
HPy prefix = HPyUnicode_FromString(ctx, "key was: ");
HPy key_repr = HPy_Repr(ctx, key);
HPy res = HPy_Add(ctx, prefix, key_repr);
HPy_Close(ctx, key_repr);
HPy_Close(ctx, prefix);
return res;
}
HPyDef_SLOT(Point_length, Point_length_impl, HPy_mp_length);
static HPy_ssize_t Point_length_impl(HPyContext *ctx, HPy self)
{
return 1234;
}
@EXPORT_POINT_TYPE(&Point_getitem, &Point_length)
@INIT
""")
p = mod.Point()
class Dummy:
def __repr__(self):
return "Hello, World"
assert len(p) == 1234
assert p[4] == "key was: 4"
assert p["hello"] == "key was: 'hello'"
assert p[Dummy()] == "key was: Hello, World"

def test_mp_ass_subscript(self):
import pytest
mod = self.make_module("""
@DEFINE_PointObject
@DEFINE_Point_new
@DEFINE_Point_xy
HPyDef_SLOT(Point_len, Point_len_impl, HPy_mp_length);
static HPy_ssize_t Point_len_impl(HPyContext *ctx, HPy self)
{
return 2;
}
HPyDef_SLOT(Point_setitem, Point_setitem_impl, HPy_mp_ass_subscript);
static int Point_setitem_impl(HPyContext *ctx, HPy self, HPy key,
HPy h_value)
{
long value;
if (HPy_IsNull(h_value)) {
value = -123; // this is the del p[] case
} else {
value = HPyLong_AsLong(ctx, h_value);
if (HPyErr_Occurred(ctx))
return -1;
}
PointObject *point = PointObject_AsStruct(ctx, self);
const char *s_key = HPyUnicode_AsUTF8AndSize(ctx, key, NULL);
if (s_key == NULL) {
return -1;
}
if (s_key[0] == 'x') {
point->x = value;
} else if (s_key[0] == 'y') {
point->y = value;
} else {
HPyErr_SetString(ctx, ctx->h_KeyError, "invalid key");
return -1;
}
return 0;
}
@EXPORT_POINT_TYPE(&Point_new, &Point_x, &Point_y, &Point_len, &Point_setitem)
@INIT
""")
p = mod.Point(1, 2)
# check __setitem__
p['x'] = 100
assert p.x == 100
p['y'] = 200
assert p.y == 200
with pytest.raises(KeyError):
p['z'] = 300
with pytest.raises(TypeError):
p[0] = 300
# check __delitem__
del p['x']
assert p.x == -123
del p['y']
assert p.y == -123

def test_sq_item_and_sq_length(self):
mod = self.make_module("""
@DEFINE_PointObject
Expand Down

0 comments on commit 4e7dfbf

Please sign in to comment.