From a8718b1c1a48bfb94aec4b8b9221444fa54b3cda Mon Sep 17 00:00:00 2001 From: Andrew Leech Date: Wed, 10 Jun 2020 10:45:24 +1000 Subject: [PATCH 1/2] py/objtype: Add __dict__ attribute for class objects. --- py/obj.h | 1 + py/objdict.c | 4 ++-- py/objtype.c | 15 +++++++++++++++ tests/basics/class_dict.py | 10 ++++++++++ 4 files changed, 28 insertions(+), 2 deletions(-) create mode 100644 tests/basics/class_dict.py diff --git a/py/obj.h b/py/obj.h index 125acf118f08d..468125eb75699 100644 --- a/py/obj.h +++ b/py/obj.h @@ -895,6 +895,7 @@ size_t mp_obj_dict_len(mp_obj_t self_in); mp_obj_t mp_obj_dict_get(mp_obj_t self_in, mp_obj_t index); mp_obj_t mp_obj_dict_store(mp_obj_t self_in, mp_obj_t key, mp_obj_t value); mp_obj_t mp_obj_dict_delete(mp_obj_t self_in, mp_obj_t key); +mp_obj_t mp_obj_dict_copy(mp_obj_t self_in); static inline mp_map_t *mp_obj_dict_get_map(mp_obj_t dict) { return &((mp_obj_dict_t *)MP_OBJ_TO_PTR(dict))->map; } diff --git a/py/objdict.c b/py/objdict.c index 7690eeab29af1..69eda99738eec 100644 --- a/py/objdict.c +++ b/py/objdict.c @@ -227,7 +227,7 @@ STATIC mp_obj_t dict_clear(mp_obj_t self_in) { } STATIC MP_DEFINE_CONST_FUN_OBJ_1(dict_clear_obj, dict_clear); -STATIC mp_obj_t dict_copy(mp_obj_t self_in) { +mp_obj_t mp_obj_dict_copy(mp_obj_t self_in) { mp_check_self(mp_obj_is_dict_type(self_in)); mp_obj_dict_t *self = MP_OBJ_TO_PTR(self_in); mp_obj_t other_out = mp_obj_new_dict(self->map.alloc); @@ -240,7 +240,7 @@ STATIC mp_obj_t dict_copy(mp_obj_t self_in) { memcpy(other->map.table, self->map.table, self->map.alloc * sizeof(mp_map_elem_t)); return other_out; } -STATIC MP_DEFINE_CONST_FUN_OBJ_1(dict_copy_obj, dict_copy); +STATIC MP_DEFINE_CONST_FUN_OBJ_1(dict_copy_obj, mp_obj_dict_copy); #if MICROPY_PY_BUILTINS_DICT_FROMKEYS // this is a classmethod diff --git a/py/objtype.c b/py/objtype.c index d08c69e284b3e..cb0fb267c8165 100644 --- a/py/objtype.c +++ b/py/objtype.c @@ -1013,6 +1013,21 @@ STATIC void type_attr(mp_obj_t self_in, qstr attr, mp_obj_t *dest) { dest[0] = MP_OBJ_NEW_QSTR(self->name); return; } + #if MICROPY_CPYTHON_COMPAT + if (attr == MP_QSTR___dict__) { + // Returns a read-only dict of the class attributes. + // If the internal locals is not fixed, a copy will be created. + mp_obj_dict_t *dict = self->locals_dict; + if (dict->map.is_fixed) { + dest[0] = MP_OBJ_FROM_PTR(dict); + } else { + dest[0] = mp_obj_dict_copy(MP_OBJ_FROM_PTR(dict)); + dict = MP_OBJ_TO_PTR(dest[0]); + dict->map.is_fixed = 1; + } + return; + } + #endif if (attr == MP_QSTR___bases__) { if (self == &mp_type_object) { dest[0] = mp_const_empty_tuple; diff --git a/tests/basics/class_dict.py b/tests/basics/class_dict.py new file mode 100644 index 0000000000000..6c8fa680ba67d --- /dev/null +++ b/tests/basics/class_dict.py @@ -0,0 +1,10 @@ + +class Foo: + a = 1 + b = "bar" + +if not hasattr(Foo, "__dict__"): + print("SKIP") + raise SystemExit + +print(Foo.__dict__ == {'a': 1, 'b': 'bar'}) From bc310ef0d4761de72d26fd5426a0a729202ef730 Mon Sep 17 00:00:00 2001 From: Andrew Leech Date: Wed, 10 Jun 2020 10:46:38 +1000 Subject: [PATCH 2/2] py/objtype: Use mp_obj_dict_copy() for creating obj.__dict__ attribute. --- py/objtype.c | 17 ++++++++--------- 1 file changed, 8 insertions(+), 9 deletions(-) diff --git a/py/objtype.c b/py/objtype.c index cb0fb267c8165..709beb610a45b 100644 --- a/py/objtype.c +++ b/py/objtype.c @@ -587,17 +587,16 @@ STATIC void mp_obj_instance_load_attr(mp_obj_t self_in, qstr attr, mp_obj_t *des } #if MICROPY_CPYTHON_COMPAT if (attr == MP_QSTR___dict__) { - // Create a new dict with a copy of the instance's map items. + // Returns a read-only dict of the instance members. + // If the internal locals is not fixed, a copy will be created. // 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 (size_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; + mp_obj_dict_t dict; + dict.map = self->members; + dict.base.type = &mp_type_dict; + dest[0] = mp_obj_dict_copy(MP_OBJ_FROM_PTR(&dict)); + mp_obj_dict_t *dest_dict = MP_OBJ_TO_PTR(dest[0]); + dest_dict->map.is_fixed = 1; return; } #endif pFad - Phonifier reborn

Pfad - The Proxy pFad of © 2024 Garber Painting. All rights reserved.

Note: This service is not intended for secure transactions such as banking, social media, email, or purchasing. Use at your own risk. We assume no liability whatsoever for broken pages.


Alternative Proxies:

Alternative Proxy

pFad Proxy

pFad v3 Proxy

pFad v4 Proxy