Skip to content

Commit 3c014a6

Browse files
stinospfalcon
authored andcommitted
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.
1 parent 7281d95 commit 3c014a6

File tree

3 files changed

+28
-1
lines changed

3 files changed

+28
-1
lines changed

py/objtype.c

Lines changed: 16 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -472,7 +472,22 @@ STATIC void mp_obj_instance_load_attr(mp_obj_t self_in, qstr attr, mp_obj_t *des
472472
dest[0] = elem->value;
473473
return;
474474
}
475-
475+
#if MICROPY_CPYTHON_COMPAT
476+
if (attr == MP_QSTR___dict__) {
477+
// Create a new dict with a copy of the instance's map items.
478+
// This creates, unlike CPython, a 'read-only' __dict__: modifying
479+
// it will not result in modifications to the actual instance members.
480+
mp_map_t *map = &self->members;
481+
mp_obj_t attr_dict = mp_obj_new_dict(map->used);
482+
for (mp_uint_t i = 0; i < map->alloc; ++i) {
483+
if (MP_MAP_SLOT_IS_FILLED(map, i)) {
484+
mp_obj_dict_store(attr_dict, map->table[i].key, map->table[i].value);
485+
}
486+
}
487+
dest[0] = attr_dict;
488+
return;
489+
}
490+
#endif
476491
struct class_lookup_data lookup = {
477492
.obj = self,
478493
.attr = attr,

py/qstrdefs.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -46,6 +46,7 @@ Q(__locals__)
4646
Q(__main__)
4747
Q(__module__)
4848
Q(__name__)
49+
Q(__dict__)
4950
Q(__hash__)
5051
Q(__next__)
5152
Q(__qualname__)

tests/basics/builtin_dict.py

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
class A:
2+
def __init__(self):
3+
self.a=1
4+
self.b=2
5+
6+
try:
7+
d=A().__dict__
8+
print(d['a'])
9+
print(d['b'])
10+
except AttributeError:
11+
print("SKIP")

0 commit comments

Comments
 (0)