diff --git a/py/objdict.c b/py/objdict.c index 753db7d808..7cfd597ed4 100644 --- a/py/objdict.c +++ b/py/objdict.c @@ -157,7 +157,7 @@ static mp_obj_t dict_get_helper(mp_map_t *self, mp_obj_t key, mp_obj_t deflt, bo value = elem->value; if (pop) { /* catch the leak (from mp_map_lookup_helper) */ - m_free(elem, 2 * sizeof(mp_obj_t)); + m_free(elem, sizeof(mp_map_elem_t)); } } if (set) { @@ -220,6 +220,32 @@ static mp_obj_t dict_popitem(mp_obj_t self_in) { } static MP_DEFINE_CONST_FUN_OBJ_1(dict_popitem_obj, dict_popitem); +static mp_obj_t dict_update(mp_obj_t self_in, mp_obj_t iterable) { + assert(MP_OBJ_IS_TYPE(self_in, &dict_type)); + mp_obj_dict_t *self = self_in; + /* TODO: check for the "keys" method */ + mp_obj_t iter = rt_getiter(iterable); + mp_obj_t next = NULL; + while ((next = rt_iternext(iter)) != mp_const_stop_iteration) { + mp_obj_t inneriter = rt_getiter(next); + mp_obj_t key = rt_iternext(inneriter); + mp_obj_t value = rt_iternext(inneriter); + mp_obj_t stop = rt_iternext(inneriter); + if (key == mp_const_stop_iteration + || value == mp_const_stop_iteration + || stop != mp_const_stop_iteration) { + nlr_jump(mp_obj_new_exception_msg( + MP_QSTR_ValueError, + "dictionary update sequence has the wrong length")); + } else { + mp_map_lookup_helper(&self->map, key, true, false)->value = value; + } + } + + return mp_const_none; +} +static MP_DEFINE_CONST_FUN_OBJ_2(dict_update_obj, dict_update); + /******************************************************************************/ /* dict constructors & etc */ @@ -238,6 +264,7 @@ const mp_obj_type_t dict_type = { { "pop", &dict_pop_obj }, { "popitem", &dict_popitem_obj }, { "setdefault", &dict_setdefault_obj }, + { "update", &dict_update_obj }, { NULL, NULL }, // end-of-list sentinel }, }; diff --git a/py/runtime.c b/py/runtime.c index 6bc71abff7..f3fabc39c9 100644 --- a/py/runtime.c +++ b/py/runtime.c @@ -859,13 +859,13 @@ mp_obj_t rt_getiter(mp_obj_t o_in) { mp_obj_t rt_iternext(mp_obj_t o_in) { if (MP_OBJ_IS_SMALL_INT(o_in)) { - nlr_jump(mp_obj_new_exception_msg(MP_QSTR_TypeError, "? 'int' object is not iterable")); + nlr_jump(mp_obj_new_exception_msg(MP_QSTR_TypeError, "'int' object is not an iterator")); } else { mp_obj_base_t *o = o_in; if (o->type->iternext != NULL) { return o->type->iternext(o_in); } else { - nlr_jump(mp_obj_new_exception_msg_1_arg(MP_QSTR_TypeError, "? '%s' object is not iterable", o->type->name)); + nlr_jump(mp_obj_new_exception_msg_1_arg(MP_QSTR_TypeError, "'%s' object is not an iterator", o->type->name)); } } }