From 3c014a67ea0c2d080905e40a1e45638fd868dccf Mon Sep 17 00:00:00 2001
From: stijn <stinos@zoho.com>
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 db99d407a..ca52006f2 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 3be6168a8..496896dad 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 000000000..f51ec21d0
--- /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")
-- 
GitLab