Skip to content

Commit 03e93f8

Browse files
committed
py/objdict: Fix fromkeys to return the right type.
Fixes #8173 It looks like a small fix, and mostly independent of upstream plans around micropython#6173 I also filed an issue upstream micropython#12011
1 parent 8de9d5a commit 03e93f8

File tree

2 files changed

+23
-4
lines changed

2 files changed

+23
-4
lines changed

py/objdict.c

Lines changed: 12 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -110,15 +110,22 @@ STATIC void dict_print(const mp_print_t *print, mp_obj_t self_in, mp_print_kind_
110110
}
111111
}
112112

113-
mp_obj_t mp_obj_dict_make_new(const mp_obj_type_t *type, size_t n_args, size_t n_kw, const mp_obj_t *args) {
114-
mp_obj_t dict_out = mp_obj_new_dict(0);
113+
// This is a helper function to initialize an empty, but typed dictionary with
114+
// a given number of slots.
115+
STATIC mp_obj_t dict_new_typed(const mp_obj_type_t *type, const size_t n) {
116+
mp_obj_t dict_out = mp_obj_new_dict(n);
115117
mp_obj_dict_t *dict = MP_OBJ_TO_PTR(dict_out);
116118
dict->base.type = type;
117119
#if MICROPY_PY_COLLECTIONS_ORDEREDDICT
118120
if (type == &mp_type_ordereddict) {
119121
dict->map.is_ordered = 1;
120122
}
121123
#endif
124+
return dict_out;
125+
}
126+
127+
mp_obj_t mp_obj_dict_make_new(const mp_obj_type_t *type, size_t n_args, size_t n_kw, const mp_obj_t *args) {
128+
mp_obj_t dict_out = dict_new_typed(type, 0);
122129
if (n_args > 0 || n_kw > 0) {
123130
mp_obj_t args2[2] = {dict_out, args[0]}; // args[0] is always valid, even if it's not a positional arg
124131
mp_map_t kwargs;
@@ -264,6 +271,7 @@ STATIC MP_DEFINE_CONST_FUN_OBJ_1(dict_copy_obj, mp_obj_dict_copy);
264271
#if MICROPY_PY_BUILTINS_DICT_FROMKEYS
265272
// this is a classmethod
266273
STATIC mp_obj_t dict_fromkeys(size_t n_args, const mp_obj_t *args) {
274+
mp_obj_type_t *type = MP_OBJ_TO_PTR(args[0]);
267275
mp_obj_t iter = mp_getiter(args[1], NULL);
268276
mp_obj_t value = mp_const_none;
269277
mp_obj_t next = MP_OBJ_NULL;
@@ -277,9 +285,9 @@ STATIC mp_obj_t dict_fromkeys(size_t n_args, const mp_obj_t *args) {
277285
mp_obj_t len = mp_obj_len_maybe(args[1]);
278286
if (len == MP_OBJ_NULL) {
279287
/* object's type doesn't have a __len__ slot */
280-
self_out = mp_obj_new_dict(0);
288+
self_out = dict_new_typed(type, 0);
281289
} else {
282-
self_out = mp_obj_new_dict(MP_OBJ_SMALL_INT_VALUE(len));
290+
self_out = dict_new_typed(type, MP_OBJ_SMALL_INT_VALUE(len));
283291
}
284292

285293
mp_obj_dict_t *self = MP_OBJ_TO_PTR(self_out);

tests/basics/ordereddict1.py

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -41,3 +41,14 @@
4141
d.popitem()
4242
except:
4343
print('empty')
44+
45+
# fromkeys returns the correct type and order
46+
d = dict.fromkeys('abcdefghij')
47+
print(type(d) == dict)
48+
d = OrderedDict.fromkeys('abcdefghij')
49+
print(type(d) == OrderedDict)
50+
print(''.join(d))
51+
52+
# fromkey handles ordering with duplicates
53+
d = OrderedDict.fromkeys('abcdefghijjihgfedcba')
54+
print(''.join(d))

0 commit comments

Comments
 (0)