Re-add passing native methods the subclass instance

Fixes #8488
This commit is contained in:
Scott Shawcroft 2023-10-24 16:04:13 -07:00
parent 53bc6d4bd1
commit 63079c75b0
No known key found for this signature in database
GPG Key ID: 0DFD512649C052DA
5 changed files with 41 additions and 13 deletions

View File

@ -55,8 +55,24 @@ MP_PROPERTY_GETSET(native_base_class_test_obj,
(mp_obj_t)&native_base_class_get_test_obj,
(mp_obj_t)&native_base_class_set_test_obj);
STATIC mp_obj_t native_base_class_obj_print_subclass_attr(mp_obj_t self_in, mp_obj_t attr_name_obj) {
if (!mp_obj_is_str(attr_name_obj)) {
mp_raise_TypeError(NULL);
}
qstr attr_name = mp_obj_str_get_qstr(attr_name_obj);
mp_obj_t value = mp_load_attr(self_in, attr_name);
mp_printf(&mp_plat_print, "native base class .%q set to: ", attr_name);
mp_obj_print_helper(&mp_plat_print, value, PRINT_REPR);
mp_printf(&mp_plat_print, "\n");
return mp_const_none;
}
MP_DEFINE_CONST_FUN_OBJ_2(native_base_class_print_subclass_attr_obj, native_base_class_obj_print_subclass_attr);
STATIC const mp_rom_map_elem_t native_base_class_locals_dict_table[] = {
{ MP_ROM_QSTR(MP_QSTR_test), MP_ROM_PTR(&native_base_class_test_obj) },
{ MP_ROM_QSTR(MP_QSTR_print_subclass_attr), MP_ROM_PTR(&native_base_class_print_subclass_attr_obj) },
};
STATIC MP_DEFINE_CONST_DICT(native_base_class_locals_dict, native_base_class_locals_dict_table);

View File

@ -45,15 +45,26 @@ STATIC void check_stringio_is_open(const mp_obj_stringio_t *o) {
#define check_stringio_is_open(o)
#endif
STATIC mp_obj_stringio_t *native_obj(mp_obj_t o_in) {
mp_obj_stringio_t *native = mp_obj_cast_to_native_base(o_in, &mp_type_stringio);
#if MICROPY_PY_IO_BYTESIO
if (native == MP_OBJ_NULL) {
native = mp_obj_cast_to_native_base(o_in, &mp_type_bytesio);
}
#endif
return native;
}
STATIC void stringio_print(const mp_print_t *print, mp_obj_t self_in, mp_print_kind_t kind) {
(void)kind;
mp_obj_stringio_t *self = MP_OBJ_TO_PTR(self_in);
mp_obj_stringio_t *self = native_obj(self_in);
mp_printf(print, self->base.type == &mp_type_stringio ? "<io.StringIO 0x%x>" : "<io.BytesIO 0x%x>", self);
}
STATIC mp_uint_t stringio_read(mp_obj_t o_in, void *buf, mp_uint_t size, int *errcode) {
(void)errcode;
mp_obj_stringio_t *o = MP_OBJ_TO_PTR(o_in);
mp_obj_stringio_t *o = native_obj(o_in);
check_stringio_is_open(o);
if (o->vstr->len <= o->pos) { // read to EOF, or seeked to EOF or beyond
return 0;
@ -77,7 +88,7 @@ STATIC void stringio_copy_on_write(mp_obj_stringio_t *o) {
STATIC mp_uint_t stringio_write(mp_obj_t o_in, const void *buf, mp_uint_t size, int *errcode) {
(void)errcode;
mp_obj_stringio_t *o = MP_OBJ_TO_PTR(o_in);
mp_obj_stringio_t *o = native_obj(o_in);
check_stringio_is_open(o);
if (o->vstr->fixed_buf) {
@ -111,7 +122,7 @@ STATIC mp_uint_t stringio_write(mp_obj_t o_in, const void *buf, mp_uint_t size,
STATIC mp_uint_t stringio_ioctl(mp_obj_t o_in, mp_uint_t request, uintptr_t arg, int *errcode) {
(void)errcode;
mp_obj_stringio_t *o = MP_OBJ_TO_PTR(o_in);
mp_obj_stringio_t *o = native_obj(o_in);
switch (request) {
case MP_STREAM_SEEK: {
struct mp_stream_seek_t *s = (struct mp_stream_seek_t *)arg;
@ -163,7 +174,7 @@ STATIC mp_uint_t stringio_ioctl(mp_obj_t o_in, mp_uint_t request, uintptr_t arg,
#define STREAM_TO_CONTENT_TYPE(o) (((o)->base.type == &mp_type_stringio) ? &mp_type_str : &mp_type_bytes)
STATIC mp_obj_t stringio_getvalue(mp_obj_t self_in) {
mp_obj_stringio_t *self = MP_OBJ_TO_PTR(self_in);
mp_obj_stringio_t *self = native_obj(self_in);
check_stringio_is_open(self);
// TODO: Try to avoid copying string
return mp_obj_new_str_of_type(STREAM_TO_CONTENT_TYPE(self), (byte *)self->vstr->buf, self->vstr->len);

View File

@ -199,14 +199,9 @@ STATIC void mp_obj_class_lookup(struct class_lookup_data *lookup, const mp_obj_t
return;
} else {
mp_obj_instance_t *obj = lookup->obj;
mp_obj_t obj_obj;
if (obj != NULL && mp_obj_is_native_type(type) && type != &mp_type_object /* object is not a real type */) {
// If we're dealing with native base class, then it applies to native sub-object
obj_obj = obj->subobj[0];
} else {
obj_obj = MP_OBJ_FROM_PTR(obj);
}
mp_convert_member_lookup(obj_obj, type, elem->value, lookup->dest);
// CIRCUITPY-CHANGE: Pass object directly. MP passes the native object.
// This allows native code to lookup and call functions on Python subclasses.
mp_convert_member_lookup(obj, type, elem->value, lookup->dest);
}
#if DEBUG_PRINT
DEBUG_printf("mp_obj_class_lookup: Returning: ");

View File

@ -29,6 +29,8 @@ print(".test:", a.test)
a._new_attribute = True
print("._new_attribute", a._new_attribute)
a.print_subclass_attr("_new_attribute")
class B(NativeBaseClass):
def __init__(self, suffix):
@ -43,3 +45,5 @@ print(".test:", b.test)
b._new_attribute = True
print("._new_attribute", b._new_attribute)
b.print_subclass_attr("_new_attribute")

View File

@ -5,7 +5,9 @@ native base class .test set to: 'test set directly'
native base class .test set to: 'test set indirectly'
.test: test set indirectly
._new_attribute True
native base class ._new_attribute set to: True
.test: super init suffix
native base class .test set to: 'test set indirectly through b'
.test: test set indirectly through b
._new_attribute True
native base class ._new_attribute set to: True