summaryrefslogtreecommitdiff
path: root/py
diff options
context:
space:
mode:
authorYonatan Goldschmidt <yon.goldschmidt@gmail.com>2019-12-09 18:31:35 +0200
committerDamien George <damien.p.george@gmail.com>2019-12-21 00:12:08 +1100
commit07ccb5588c4abcffa28f25907e699d1727d38bae (patch)
treeb3a198c7bc563df81bdfd2b6b55c6a589cb9c8df /py
parent90f286465b670feb94c3ce8857c81bad3df18b96 (diff)
py/objobject: Add object.__setattr__ function.
Allows assigning attributes on class instances that implement their own __setattr__. Both object.__setattr__ and super(A, b).__setattr__ will work with this commit.
Diffstat (limited to 'py')
-rw-r--r--py/objobject.c22
-rw-r--r--py/runtime.c4
2 files changed, 24 insertions, 2 deletions
diff --git a/py/objobject.c b/py/objobject.c
index 45228347e..ae8436bc8 100644
--- a/py/objobject.c
+++ b/py/objobject.c
@@ -50,7 +50,7 @@ STATIC MP_DEFINE_CONST_FUN_OBJ_1(object___init___obj, object___init__);
STATIC mp_obj_t object___new__(mp_obj_t cls) {
if (!mp_obj_is_type(cls, &mp_type_type) || !mp_obj_is_instance_type((mp_obj_type_t*)MP_OBJ_TO_PTR(cls))) {
- mp_raise_TypeError("__new__ arg must be a user-type");
+ mp_raise_TypeError("arg must be user-type");
}
// This executes only "__new__" part of instance creation.
// TODO: This won't work well for classes with native bases.
@@ -62,6 +62,23 @@ STATIC mp_obj_t object___new__(mp_obj_t cls) {
STATIC MP_DEFINE_CONST_FUN_OBJ_1(object___new___fun_obj, object___new__);
STATIC MP_DEFINE_CONST_STATICMETHOD_OBJ(object___new___obj, MP_ROM_PTR(&object___new___fun_obj));
+#if MICROPY_PY_DELATTR_SETATTR
+STATIC mp_obj_t object___setattr__(mp_obj_t self_in, mp_obj_t attr, mp_obj_t value) {
+ if (!mp_obj_is_instance_type(mp_obj_get_type(MP_OBJ_TO_PTR(self_in)))) {
+ mp_raise_TypeError("arg must be user-type");
+ }
+
+ if (!mp_obj_is_str(attr)) {
+ mp_raise_TypeError(NULL);
+ }
+
+ mp_obj_instance_t *self = MP_OBJ_TO_PTR(self_in);
+ mp_map_lookup(&self->members, attr, MP_MAP_LOOKUP_ADD_IF_NOT_FOUND)->value = value;
+ return mp_const_none;
+}
+STATIC MP_DEFINE_CONST_FUN_OBJ_3(object___setattr___obj, object___setattr__);
+#endif
+
STATIC const mp_rom_map_elem_t object_locals_dict_table[] = {
#if MICROPY_CPYTHON_COMPAT
{ MP_ROM_QSTR(MP_QSTR___init__), MP_ROM_PTR(&object___init___obj) },
@@ -69,6 +86,9 @@ STATIC const mp_rom_map_elem_t object_locals_dict_table[] = {
#if MICROPY_CPYTHON_COMPAT
{ MP_ROM_QSTR(MP_QSTR___new__), MP_ROM_PTR(&object___new___obj) },
#endif
+ #if MICROPY_PY_DELATTR_SETATTR
+ { MP_ROM_QSTR(MP_QSTR___setattr__), MP_ROM_PTR(&object___setattr___obj) },
+ #endif
};
STATIC MP_DEFINE_CONST_DICT(object_locals_dict, object_locals_dict_table);
diff --git a/py/runtime.c b/py/runtime.c
index deb82e935..cf4fc5d38 100644
--- a/py/runtime.c
+++ b/py/runtime.c
@@ -1038,9 +1038,11 @@ void mp_convert_member_lookup(mp_obj_t self, const mp_obj_type_t *type, mp_obj_t
|| m_type == &mp_type_fun_builtin_1
|| m_type == &mp_type_fun_builtin_2
|| m_type == &mp_type_fun_builtin_3
- || m_type == &mp_type_fun_builtin_var)) {
+ || m_type == &mp_type_fun_builtin_var)
+ && type != &mp_type_object) {
// we extracted a builtin method without a first argument, so we must
// wrap this function in a type checker
+ // Note that object will do its own checking so shouldn't be wrapped.
dest[0] = mp_obj_new_checked_fun(type, member);
} else
#endif