From 922b7c313197a28aa8243710d2d26f1034575674 Mon Sep 17 00:00:00 2001 From: Jeff Epler Date: Sun, 25 Mar 2018 14:25:04 -0500 Subject: [PATCH 1/3] Don't assume the type of the prop->proxy objects This fixes a crash running the cpydiff/core_class_superproperty.py test, but it does not fix the difference to cpython3. Closes: #705 --- py/gc_long_lived.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/py/gc_long_lived.c b/py/gc_long_lived.c index c50bbcd83631c..d34fde5d9bcd1 100644 --- a/py/gc_long_lived.c +++ b/py/gc_long_lived.c @@ -78,9 +78,9 @@ mp_obj_property_t *make_property_long_lived(mp_obj_property_t *prop, uint8_t max if (max_depth == 0) { return prop; } - prop->proxy[0] = make_fun_bc_long_lived((mp_obj_fun_bc_t*) prop->proxy[0], max_depth - 1); - prop->proxy[1] = make_fun_bc_long_lived((mp_obj_fun_bc_t*) prop->proxy[1], max_depth - 1); - prop->proxy[2] = make_fun_bc_long_lived((mp_obj_fun_bc_t*) prop->proxy[2], max_depth - 1); + prop->proxy[0] = make_obj_long_lived((mp_obj_fun_bc_t*) prop->proxy[0], max_depth - 1); + prop->proxy[1] = make_obj_long_lived((mp_obj_fun_bc_t*) prop->proxy[1], max_depth - 1); + prop->proxy[2] = make_obj_long_lived((mp_obj_fun_bc_t*) prop->proxy[2], max_depth - 1); return gc_make_long_lived(prop); } From 74fefe45a4cc6073d16af32e0fe35e1fd389d558 Mon Sep 17 00:00:00 2001 From: Jeff Epler Date: Sun, 25 Mar 2018 14:25:32 -0500 Subject: [PATCH 2/3] super(): Do the same lookup tasks as regular getattr .. in the presence of properties and descriptors --- py/objtype.c | 30 +++++++++++++++++++++++++++--- 1 file changed, 27 insertions(+), 3 deletions(-) diff --git a/py/objtype.c b/py/objtype.c index 1d6dc0b6cd4ac..7262892bd8709 100644 --- a/py/objtype.c +++ b/py/objtype.c @@ -567,6 +567,7 @@ STATIC void mp_obj_instance_load_attr(mp_obj_t self_in, qstr attr, mp_obj_t *des mp_obj_class_lookup(&lookup, self->base.type); mp_obj_t member = dest[0]; if (member != MP_OBJ_NULL) { + // changes here may may require changes to super_attr, below #if MICROPY_PY_BUILTINS_PROPERTY if (MP_OBJ_IS_TYPE(member, &mp_type_property)) { // object member is a property; delegate the load to the property @@ -1112,14 +1113,37 @@ STATIC void super_attr(mp_obj_t self_in, qstr attr, mp_obj_t *dest) { assert(MP_OBJ_IS_TYPE(items[i], &mp_type_type)); mp_obj_class_lookup(&lookup, (mp_obj_type_t*)MP_OBJ_TO_PTR(items[i])); if (dest[0] != MP_OBJ_NULL) { - return; + break; } } } else { mp_obj_class_lookup(&lookup, type->parent); - if (dest[0] != MP_OBJ_NULL) { - return; + } + + if (dest[0] != MP_OBJ_NULL) { + mp_obj_t member = dest[0]; + // changes to mp_obj_instance_load_attr may require changes + // here... + #if MICROPY_PY_BUILTINS_PROPERTY + if (MP_OBJ_IS_TYPE(member, &mp_type_property)) { + const mp_obj_t *proxy = mp_obj_property_get(member); + if (proxy[0] == mp_const_none) { + mp_raise_AttributeError("unreadable attribute"); + } else { + dest[0] = mp_call_function_n_kw(proxy[0], 1, 0, &self_in); + } + } + #endif + #if MICROPY_PY_DESCRIPTORS + mp_obj_t attr_get_method[4]; + mp_load_method_maybe(member, MP_QSTR___get__, attr_get_method); + if (attr_get_method[0] != MP_OBJ_NULL) { + attr_get_method[2] = self_in; + attr_get_method[3] = MP_OBJ_FROM_PTR(mp_obj_get_type(self_in)); + dest[0] = mp_call_method_n_kw(2, 0, attr_get_method); } + #endif + return; } mp_obj_class_lookup(&lookup, &mp_type_object); From 047a4f59c5acc6ab70bab177b33f0cef2972e8a1 Mon Sep 17 00:00:00 2001 From: Jeff Epler Date: Sun, 25 Mar 2018 14:30:59 -0500 Subject: [PATCH 3/3] This test now passes, make it run regularly --- tests/{cpydiff => basics}/core_class_superproperty.py | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-) rename tests/{cpydiff => basics}/core_class_superproperty.py (50%) diff --git a/tests/cpydiff/core_class_superproperty.py b/tests/basics/core_class_superproperty.py similarity index 50% rename from tests/cpydiff/core_class_superproperty.py rename to tests/basics/core_class_superproperty.py index 1ec210550ef96..69db10046a273 100644 --- a/tests/cpydiff/core_class_superproperty.py +++ b/tests/basics/core_class_superproperty.py @@ -1,8 +1,5 @@ """ -categories: Core,Classes -description: Calling super() getter property in subclass will return a property object, not the value -cause: Unknown -workaround: Unknown +test that calling super() getter property in subclass will return the value """ class A: @property