Merge pull request #8175 from kbsriram/fromkeys-fix

py/objdict: Fix fromkeys to return the right type.
This commit is contained in:
Scott Shawcroft 2023-07-17 14:56:14 -07:00 committed by GitHub
commit e2e8b162b6
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
2 changed files with 23 additions and 4 deletions

View File

@ -110,8 +110,10 @@ STATIC void dict_print(const mp_print_t *print, mp_obj_t self_in, mp_print_kind_
} }
} }
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) { // This is a helper function to initialize an empty, but typed dictionary with
mp_obj_t dict_out = mp_obj_new_dict(0); // a given number of slots.
STATIC mp_obj_t dict_new_typed(const mp_obj_type_t *type, const size_t n) {
mp_obj_t dict_out = mp_obj_new_dict(n);
mp_obj_dict_t *dict = MP_OBJ_TO_PTR(dict_out); mp_obj_dict_t *dict = MP_OBJ_TO_PTR(dict_out);
dict->base.type = type; dict->base.type = type;
#if MICROPY_PY_COLLECTIONS_ORDEREDDICT #if MICROPY_PY_COLLECTIONS_ORDEREDDICT
@ -119,6 +121,11 @@ mp_obj_t mp_obj_dict_make_new(const mp_obj_type_t *type, size_t n_args, size_t n
dict->map.is_ordered = 1; dict->map.is_ordered = 1;
} }
#endif #endif
return dict_out;
}
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) {
mp_obj_t dict_out = dict_new_typed(type, 0);
if (n_args > 0 || n_kw > 0) { if (n_args > 0 || n_kw > 0) {
mp_obj_t args2[2] = {dict_out, args[0]}; // args[0] is always valid, even if it's not a positional arg mp_obj_t args2[2] = {dict_out, args[0]}; // args[0] is always valid, even if it's not a positional arg
mp_map_t kwargs; mp_map_t kwargs;
@ -264,6 +271,7 @@ STATIC MP_DEFINE_CONST_FUN_OBJ_1(dict_copy_obj, mp_obj_dict_copy);
#if MICROPY_PY_BUILTINS_DICT_FROMKEYS #if MICROPY_PY_BUILTINS_DICT_FROMKEYS
// this is a classmethod // this is a classmethod
STATIC mp_obj_t dict_fromkeys(size_t n_args, const mp_obj_t *args) { STATIC mp_obj_t dict_fromkeys(size_t n_args, const mp_obj_t *args) {
mp_obj_type_t *type = MP_OBJ_TO_PTR(args[0]);
mp_obj_t iter = mp_getiter(args[1], NULL); mp_obj_t iter = mp_getiter(args[1], NULL);
mp_obj_t value = mp_const_none; mp_obj_t value = mp_const_none;
mp_obj_t next = MP_OBJ_NULL; 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) {
mp_obj_t len = mp_obj_len_maybe(args[1]); mp_obj_t len = mp_obj_len_maybe(args[1]);
if (len == MP_OBJ_NULL) { if (len == MP_OBJ_NULL) {
/* object's type doesn't have a __len__ slot */ /* object's type doesn't have a __len__ slot */
self_out = mp_obj_new_dict(0); self_out = dict_new_typed(type, 0);
} else { } else {
self_out = mp_obj_new_dict(MP_OBJ_SMALL_INT_VALUE(len)); self_out = dict_new_typed(type, MP_OBJ_SMALL_INT_VALUE(len));
} }
mp_obj_dict_t *self = MP_OBJ_TO_PTR(self_out); mp_obj_dict_t *self = MP_OBJ_TO_PTR(self_out);

View File

@ -41,3 +41,14 @@ try:
d.popitem() d.popitem()
except: except:
print('empty') print('empty')
# fromkeys returns the correct type and order
d = dict.fromkeys('abcdefghij')
print(type(d) == dict)
d = OrderedDict.fromkeys('abcdefghij')
print(type(d) == OrderedDict)
print(''.join(d))
# fromkey handles ordering with duplicates
d = OrderedDict.fromkeys('abcdefghijjihgfedcba')
print(''.join(d))