diff options
Diffstat (limited to 'py/objtype.c')
| -rw-r--r-- | py/objtype.c | 47 |
1 files changed, 41 insertions, 6 deletions
diff --git a/py/objtype.c b/py/objtype.c index 1d6dc0b6c..5b70e8e48 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 @@ -980,8 +981,14 @@ const mp_obj_type_t mp_type_type = { }; mp_obj_t mp_obj_new_type(qstr name, mp_obj_t bases_tuple, mp_obj_t locals_dict) { - assert(MP_OBJ_IS_TYPE(bases_tuple, &mp_type_tuple)); // MicroPython restriction, for now - assert(MP_OBJ_IS_TYPE(locals_dict, &mp_type_dict)); // MicroPython restriction, for now + if(!MP_OBJ_IS_TYPE(bases_tuple, &mp_type_tuple)) { + // MicroPython restriction, for now + mp_raise_TypeError("type() argument 2 must be tuple"); + } + if(!MP_OBJ_IS_TYPE(locals_dict, &mp_type_dict)) { + // MicroPython restriction, for now + mp_raise_TypeError("type() argument 3 must be dict"); + } // TODO might need to make a copy of locals_dict; at least that's how CPython does it @@ -990,7 +997,9 @@ mp_obj_t mp_obj_new_type(qstr name, mp_obj_t bases_tuple, mp_obj_t locals_dict) mp_obj_t *items; mp_obj_tuple_get(bases_tuple, &len, &items); for (size_t i = 0; i < len; i++) { - assert(MP_OBJ_IS_TYPE(items[i], &mp_type_type)); + if(!MP_OBJ_IS_TYPE(items[i], &mp_type_type)) { + mp_raise_TypeError("type is not an acceptable base type"); + } mp_obj_type_t *t = MP_OBJ_TO_PTR(items[i]); // TODO: Verify with CPy, tested on function type if (t->make_new == NULL) { @@ -1076,6 +1085,9 @@ STATIC mp_obj_t super_make_new(const mp_obj_type_t *type_in, size_t n_args, size // 0 arguments are turned into 2 in the compiler // 1 argument is not yet implemented mp_arg_check_num(n_args, n_kw, 2, 2, false); + if(!MP_OBJ_IS_TYPE(args[0], &mp_type_type)) { + mp_raise_TypeError("first argument to super() must be type"); + } mp_obj_super_t *o = m_new_obj(mp_obj_super_t); *o = (mp_obj_super_t){{type_in}, args[0], args[1]}; return MP_OBJ_FROM_PTR(o); @@ -1112,14 +1124,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); |
