From 457fdf61c3bca550b4ad3fb2c6822c838984dac0 Mon Sep 17 00:00:00 2001 From: Damien George Date: Sun, 21 Jun 2020 17:25:44 +1000 Subject: [PATCH] py/objtype: Support passing in an OrderedDict to type() as the locals. An OrderedDict can now be used for the locals when creating a type explicitly via type(name, bases, locals). Signed-off-by: Damien George --- py/objtype.c | 6 +++--- tests/basics/class_ordereddict.py | 18 ++++++++++++++++++ tests/basics/class_ordereddict.py.exp | 1 + 3 files changed, 22 insertions(+), 3 deletions(-) create mode 100644 tests/basics/class_ordereddict.py create mode 100644 tests/basics/class_ordereddict.py.exp diff --git a/py/objtype.c b/py/objtype.c index a539fcab29..40900dc050 100644 --- a/py/objtype.c +++ b/py/objtype.c @@ -153,7 +153,7 @@ STATIC void mp_obj_class_lookup(struct class_lookup_data *lookup, const mp_obj_t if (type->locals_dict != NULL) { // search locals_dict (the set of methods/attributes) - assert(type->locals_dict->base.type == &mp_type_dict); // MicroPython restriction, for now + assert(mp_obj_is_dict_or_ordereddict(MP_OBJ_FROM_PTR(type->locals_dict))); // MicroPython restriction, for now mp_map_t *locals_map = &type->locals_dict->map; mp_map_elem_t *elem = mp_map_lookup(locals_map, MP_OBJ_NEW_QSTR(lookup->attr), MP_MAP_LOOKUP); if (elem != NULL) { @@ -1053,7 +1053,7 @@ STATIC void type_attr(mp_obj_t self_in, qstr attr, mp_obj_t *dest) { // delete/store attribute if (self->locals_dict != NULL) { - assert(self->locals_dict->base.type == &mp_type_dict); // MicroPython restriction, for now + assert(mp_obj_is_dict_or_ordereddict(MP_OBJ_FROM_PTR(self->locals_dict))); // MicroPython restriction, for now mp_map_t *locals_map = &self->locals_dict->map; if (locals_map->is_fixed) { // can't apply delete/store to a fixed map @@ -1103,7 +1103,7 @@ mp_obj_t mp_obj_new_type(qstr name, mp_obj_t bases_tuple, mp_obj_t locals_dict) if (!mp_obj_is_type(bases_tuple, &mp_type_tuple)) { mp_raise_TypeError(NULL); } - if (!mp_obj_is_type(locals_dict, &mp_type_dict)) { + if (!mp_obj_is_dict_or_ordereddict(locals_dict)) { mp_raise_TypeError(NULL); } diff --git a/tests/basics/class_ordereddict.py b/tests/basics/class_ordereddict.py new file mode 100644 index 0000000000..4dd25eb6e1 --- /dev/null +++ b/tests/basics/class_ordereddict.py @@ -0,0 +1,18 @@ +# test using an OrderedDict as the locals to construct a class + +try: + from ucollections import OrderedDict +except ImportError: + try: + from collections import OrderedDict + except ImportError: + print("SKIP") + raise SystemExit + +if not hasattr(int, "__dict__"): + print("SKIP") + raise SystemExit + + +A = type("A", (), OrderedDict(a=1, b=2, c=3, d=4, e=5)) +print([k for k in A.__dict__.keys() if not k.startswith("_")]) diff --git a/tests/basics/class_ordereddict.py.exp b/tests/basics/class_ordereddict.py.exp new file mode 100644 index 0000000000..b723e32751 --- /dev/null +++ b/tests/basics/class_ordereddict.py.exp @@ -0,0 +1 @@ +['a', 'b', 'c', 'd', 'e']