From 3c014a67ea0c2d080905e40a1e45638fd868dccf Mon Sep 17 00:00:00 2001 From: stijn Date: Tue, 23 Dec 2014 14:06:55 +0100 Subject: [PATCH] py: Implement __dict__ for instances. Note that even though wrapped in MICROPY_CPYTHON_COMPAT, it is not fully compatible because the modifications to the dictionary do not propagate to the actual instance members. --- py/objtype.c | 17 ++++++++++++++++- py/qstrdefs.h | 1 + tests/basics/builtin_dict.py | 11 +++++++++++ 3 files changed, 28 insertions(+), 1 deletion(-) create mode 100644 tests/basics/builtin_dict.py diff --git a/py/objtype.c b/py/objtype.c index db99d407ac..ca52006f25 100644 --- a/py/objtype.c +++ b/py/objtype.c @@ -472,7 +472,22 @@ STATIC void mp_obj_instance_load_attr(mp_obj_t self_in, qstr attr, mp_obj_t *des dest[0] = elem->value; return; } - +#if MICROPY_CPYTHON_COMPAT + if (attr == MP_QSTR___dict__) { + // Create a new dict with a copy of the instance's map items. + // This creates, unlike CPython, a 'read-only' __dict__: modifying + // it will not result in modifications to the actual instance members. + mp_map_t *map = &self->members; + mp_obj_t attr_dict = mp_obj_new_dict(map->used); + for (mp_uint_t i = 0; i < map->alloc; ++i) { + if (MP_MAP_SLOT_IS_FILLED(map, i)) { + mp_obj_dict_store(attr_dict, map->table[i].key, map->table[i].value); + } + } + dest[0] = attr_dict; + return; + } +#endif struct class_lookup_data lookup = { .obj = self, .attr = attr, diff --git a/py/qstrdefs.h b/py/qstrdefs.h index 3be6168a8f..496896dad4 100644 --- a/py/qstrdefs.h +++ b/py/qstrdefs.h @@ -46,6 +46,7 @@ Q(__locals__) Q(__main__) Q(__module__) Q(__name__) +Q(__dict__) Q(__hash__) Q(__next__) Q(__qualname__) diff --git a/tests/basics/builtin_dict.py b/tests/basics/builtin_dict.py new file mode 100644 index 0000000000..f51ec21d00 --- /dev/null +++ b/tests/basics/builtin_dict.py @@ -0,0 +1,11 @@ +class A: + def __init__(self): + self.a=1 + self.b=2 + +try: + d=A().__dict__ + print(d['a']) + print(d['b']) +except AttributeError: + print("SKIP")