From 2fe6d4eb86a8496620a5db0958972ad5573932fb Mon Sep 17 00:00:00 2001 From: David Lechner Date: Wed, 18 Jan 2023 13:59:54 -0600 Subject: [PATCH] py/objdict: Fix __hash__ for dict_view types. This adds a unary_op implementation for the dict_view type that makes the implementation of `hash()` for these types compatible with CPython. Signed-off-by: David Lechner --- py/objdict.c | 10 ++++++++++ tests/basics/dict_views.py | 18 ++++++++++++++++++ 2 files changed, 28 insertions(+) diff --git a/py/objdict.c b/py/objdict.c index baad8a1b9e..a621c4feaf 100644 --- a/py/objdict.c +++ b/py/objdict.c @@ -515,6 +515,15 @@ STATIC void dict_view_print(const mp_print_t *print, mp_obj_t self_in, mp_print_ mp_print_str(print, "])"); } +STATIC mp_obj_t dict_view_unary_op(mp_unary_op_t op, mp_obj_t o_in) { + mp_obj_dict_view_t *o = MP_OBJ_TO_PTR(o_in); + // only dict.values() supports __hash__. + if (op == MP_UNARY_OP_HASH && o->kind == MP_DICT_VIEW_VALUES) { + return MP_OBJ_NEW_SMALL_INT((mp_uint_t)o_in); + } + return MP_OBJ_NULL; +} + STATIC mp_obj_t dict_view_binary_op(mp_binary_op_t op, mp_obj_t lhs_in, mp_obj_t rhs_in) { // only supported for the 'keys' kind until sets and dicts are refactored mp_obj_dict_view_t *o = MP_OBJ_TO_PTR(lhs_in); @@ -532,6 +541,7 @@ STATIC MP_DEFINE_CONST_OBJ_TYPE( MP_QSTR_dict_view, MP_TYPE_FLAG_ITER_IS_GETITER, print, dict_view_print, + unary_op, dict_view_unary_op, binary_op, dict_view_binary_op, iter, dict_view_getiter ); diff --git a/tests/basics/dict_views.py b/tests/basics/dict_views.py index 7ebcc1f56d..a82f47b6be 100644 --- a/tests/basics/dict_views.py +++ b/tests/basics/dict_views.py @@ -18,4 +18,22 @@ try: except TypeError: print('TypeError') +# keys dict_view is not hashable + +try: + hash({}.keys()) +except TypeError: + print('TypeError') + +# values dict_view is hashable + +print(type(hash({}.values()))) + +# items dict_view is not hashable + +try: + hash({}.items()) +except TypeError: + print('TypeError') + # set operations still to come