diff --git a/src/public/PyDict.c b/src/public/PyDict.c index c0e47b8b..b1647771 100644 --- a/src/public/PyDict.c +++ b/src/public/PyDict.c @@ -568,22 +568,25 @@ static bool dict_pop(int argc, py_Ref argv) { if(res == 0) py_assign(py_retval(), default_val); return true; } + static bool dict_popitem(int argc, py_Ref argv) { PY_CHECK_ARGC(1); Dict* self = py_touserdata(argv); - if(self->length == 0) return KeyError(py_None()); for(int i = self->entries.length - 1; i >= 0; i--) { DictEntry* entry = c11__at(DictEntry, &self->entries, i); if(py_isnil(&entry->key)) continue; - py_Ref p = py_newtuple(py_retval(), 2); + py_Ref p = py_newtuple(py_pushtmp(), 2); p[0] = entry->key; p[1] = entry->val; - py_TValue key_copy = entry->key; - Dict__pop(self, &key_copy); + int res = Dict__pop(self, &p[0]); + c11__rtassert(res == 1); + py_assign(py_retval(), py_peek(-1)); + py_pop(); return true; } return KeyError(py_None()); } + static bool dict_keys(int argc, py_Ref argv) { PY_CHECK_ARGC(1); Dict* self = py_touserdata(argv); diff --git a/tests/080_dict.py b/tests/080_dict.py index 1ccc6603..32431517 100644 --- a/tests/080_dict.py +++ b/tests/080_dict.py @@ -142,6 +142,17 @@ for i in range(n): del a[str(i)] assert len(a) == 0 +# test popitem +n = 2 ** 17 +a = {} +for i in range(n): + a[str(i)] = i +for i in range(n): + k, v = a.popitem() + assert k == str(n - 1 - i) + assert v == n - 1 - i +assert len(a) == 0 + # test del with int keys if 0: n = 2 ** 17