summaryrefslogtreecommitdiffstatshomepage
diff options
context:
space:
mode:
-rw-r--r--py/obj.h1
-rw-r--r--py/objdict.c4
-rw-r--r--py/objtype.c15
-rw-r--r--tests/basics/class_dict.py19
4 files changed, 37 insertions, 2 deletions
diff --git a/py/obj.h b/py/obj.h
index 125acf118f..468125eb75 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 7690eeab29..69eda99738 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 d08c69e284..cb0fb267c8 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 0000000000..f80ded678b
--- /dev/null
+++ b/tests/basics/class_dict.py
@@ -0,0 +1,19 @@
+# test __dict__ attribute of a class
+
+if not hasattr(int, "__dict__"):
+ print("SKIP")
+ raise SystemExit
+
+
+# dict of a built-in type
+print("from_bytes" in int.__dict__)
+
+
+# dict of a user class
+class Foo:
+ a = 1
+ b = "bar"
+
+
+d = Foo.__dict__
+print(d["a"], d["b"])