Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
9 changes: 0 additions & 9 deletions py/obj.c
Original file line number Diff line number Diff line change
Expand Up @@ -594,12 +594,3 @@ void mp_get_buffer_raise(mp_obj_t obj, mp_buffer_info_t *bufinfo, mp_uint_t flag
mp_raise_TypeError(MP_ERROR_TEXT("object with buffer protocol required"));
}
}

mp_obj_t mp_generic_unary_op(mp_unary_op_t op, mp_obj_t o_in) {
switch (op) {
case MP_UNARY_OP_HASH:
return MP_OBJ_NEW_SMALL_INT((mp_uint_t)o_in);
default:
return MP_OBJ_NULL; // op not supported
}
}
1 change: 0 additions & 1 deletion py/obj.h
Original file line number Diff line number Diff line change
Expand Up @@ -1016,7 +1016,6 @@ mp_obj_t mp_obj_id(mp_obj_t o_in);
mp_obj_t mp_obj_len(mp_obj_t o_in);
mp_obj_t mp_obj_len_maybe(mp_obj_t o_in); // may return MP_OBJ_NULL
mp_obj_t mp_obj_subscr(mp_obj_t base, mp_obj_t index, mp_obj_t val);
mp_obj_t mp_generic_unary_op(mp_unary_op_t op, mp_obj_t o_in);

// cell

Expand Down
10 changes: 10 additions & 0 deletions py/objdict.c
Original file line number Diff line number Diff line change
Expand Up @@ -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);
Expand All @@ -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
);
Expand Down
24 changes: 8 additions & 16 deletions py/objfun.c
Original file line number Diff line number Diff line change
Expand Up @@ -58,8 +58,7 @@ STATIC mp_obj_t fun_builtin_0_call(mp_obj_t self_in, size_t n_args, size_t n_kw,

MP_DEFINE_CONST_OBJ_TYPE(
mp_type_fun_builtin_0, MP_QSTR_function, MP_TYPE_FLAG_BINDS_SELF | MP_TYPE_FLAG_BUILTIN_FUN,
call, fun_builtin_0_call,
unary_op, mp_generic_unary_op
call, fun_builtin_0_call
);

STATIC mp_obj_t fun_builtin_1_call(mp_obj_t self_in, size_t n_args, size_t n_kw, const mp_obj_t *args) {
Expand All @@ -71,8 +70,7 @@ STATIC mp_obj_t fun_builtin_1_call(mp_obj_t self_in, size_t n_args, size_t n_kw,

MP_DEFINE_CONST_OBJ_TYPE(
mp_type_fun_builtin_1, MP_QSTR_function, MP_TYPE_FLAG_BINDS_SELF | MP_TYPE_FLAG_BUILTIN_FUN,
call, fun_builtin_1_call,
unary_op, mp_generic_unary_op
call, fun_builtin_1_call
);

STATIC mp_obj_t fun_builtin_2_call(mp_obj_t self_in, size_t n_args, size_t n_kw, const mp_obj_t *args) {
Expand All @@ -84,8 +82,7 @@ STATIC mp_obj_t fun_builtin_2_call(mp_obj_t self_in, size_t n_args, size_t n_kw,

MP_DEFINE_CONST_OBJ_TYPE(
mp_type_fun_builtin_2, MP_QSTR_function, MP_TYPE_FLAG_BINDS_SELF | MP_TYPE_FLAG_BUILTIN_FUN,
call, fun_builtin_2_call,
unary_op, mp_generic_unary_op
call, fun_builtin_2_call
);

STATIC mp_obj_t fun_builtin_3_call(mp_obj_t self_in, size_t n_args, size_t n_kw, const mp_obj_t *args) {
Expand All @@ -97,8 +94,7 @@ STATIC mp_obj_t fun_builtin_3_call(mp_obj_t self_in, size_t n_args, size_t n_kw,

MP_DEFINE_CONST_OBJ_TYPE(
mp_type_fun_builtin_3, MP_QSTR_function, MP_TYPE_FLAG_BINDS_SELF | MP_TYPE_FLAG_BUILTIN_FUN,
call, fun_builtin_3_call,
unary_op, mp_generic_unary_op
call, fun_builtin_3_call
);

STATIC mp_obj_t fun_builtin_var_call(mp_obj_t self_in, size_t n_args, size_t n_kw, const mp_obj_t *args) {
Expand Down Expand Up @@ -126,8 +122,7 @@ STATIC mp_obj_t fun_builtin_var_call(mp_obj_t self_in, size_t n_args, size_t n_k

MP_DEFINE_CONST_OBJ_TYPE(
mp_type_fun_builtin_var, MP_QSTR_function, MP_TYPE_FLAG_BINDS_SELF | MP_TYPE_FLAG_BUILTIN_FUN,
call, fun_builtin_var_call,
unary_op, mp_generic_unary_op
call, fun_builtin_var_call
);

/******************************************************************************/
Expand Down Expand Up @@ -370,8 +365,7 @@ MP_DEFINE_CONST_OBJ_TYPE(
MP_TYPE_FLAG_BINDS_SELF,
FUN_BC_TYPE_PRINT
FUN_BC_TYPE_ATTR
call, fun_bc_call,
unary_op, mp_generic_unary_op
call, fun_bc_call
);

mp_obj_t mp_obj_new_fun_bc(const mp_obj_t *def_args, const byte *code, const mp_module_context_t *context, struct _mp_raw_code_t *const *child_table) {
Expand Down Expand Up @@ -432,8 +426,7 @@ STATIC MP_DEFINE_CONST_OBJ_TYPE(
MP_TYPE_FLAG_BINDS_SELF,
FUN_BC_TYPE_PRINT
FUN_BC_TYPE_ATTR
call, fun_native_call,
unary_op, mp_generic_unary_op
call, fun_native_call
);

mp_obj_t mp_obj_new_fun_native(const mp_obj_t *def_args, const void *fun_data, const mp_module_context_t *mc, struct _mp_raw_code_t *const *child_table) {
Expand Down Expand Up @@ -540,8 +533,7 @@ STATIC MP_DEFINE_CONST_OBJ_TYPE(
mp_type_fun_asm,
MP_QSTR_function,
MP_TYPE_FLAG_BINDS_SELF,
call, fun_asm_call,
unary_op, mp_generic_unary_op
call, fun_asm_call
);

mp_obj_t mp_obj_new_fun_asm(size_t n_args, const void *fun_data, mp_uint_t type_sig) {
Expand Down
9 changes: 3 additions & 6 deletions py/objgenerator.c
Original file line number Diff line number Diff line change
Expand Up @@ -81,8 +81,7 @@ MP_DEFINE_CONST_OBJ_TYPE(
MP_QSTR_generator,
MP_TYPE_FLAG_BINDS_SELF,
GEN_WRAP_TYPE_ATTR
call, gen_wrap_call,
unary_op, mp_generic_unary_op
call, gen_wrap_call
);

/******************************************************************************/
Expand Down Expand Up @@ -136,7 +135,7 @@ STATIC mp_obj_t native_gen_wrap_call(mp_obj_t self_in, size_t n_args, size_t n_k
}

#if MICROPY_PY_FUNCTION_ATTRS
#define NATIVE_GEN_WRAP_TYPE_ATTR attr, mp_obj_fun_bc_attr,
#define NATIVE_GEN_WRAP_TYPE_ATTR , attr, mp_obj_fun_bc_attr
#else
#define NATIVE_GEN_WRAP_TYPE_ATTR
#endif
Expand All @@ -145,9 +144,8 @@ MP_DEFINE_CONST_OBJ_TYPE(
mp_type_native_gen_wrap,
MP_QSTR_generator,
MP_TYPE_FLAG_BINDS_SELF,
call, native_gen_wrap_call,
call, native_gen_wrap_call
NATIVE_GEN_WRAP_TYPE_ATTR
unary_op, mp_generic_unary_op
);

#endif // MICROPY_EMIT_NATIVE
Expand Down Expand Up @@ -370,7 +368,6 @@ MP_DEFINE_CONST_OBJ_TYPE(
MP_QSTR_generator,
MP_TYPE_FLAG_ITER_IS_ITERNEXT,
print, gen_instance_print,
unary_op, mp_generic_unary_op,
iter, gen_instance_iternext,
locals_dict, &gen_instance_locals_dict
);
3 changes: 1 addition & 2 deletions py/objnone.c
Original file line number Diff line number Diff line change
Expand Up @@ -47,8 +47,7 @@ MP_DEFINE_CONST_OBJ_TYPE(
mp_type_NoneType,
MP_QSTR_NoneType,
MP_TYPE_FLAG_NONE,
print, none_print,
unary_op, mp_generic_unary_op
print, none_print
);

#if !MICROPY_OBJ_IMMEDIATE_OBJS
Expand Down
3 changes: 1 addition & 2 deletions py/objsingleton.c
Original file line number Diff line number Diff line change
Expand Up @@ -45,8 +45,7 @@ STATIC void singleton_print(const mp_print_t *print, mp_obj_t self_in, mp_print_

MP_DEFINE_CONST_OBJ_TYPE(
mp_type_singleton, MP_QSTR_, MP_TYPE_FLAG_NONE,
print, singleton_print,
unary_op, mp_generic_unary_op
print, singleton_print
);

const mp_obj_singleton_t mp_const_ellipsis_obj = {{&mp_type_singleton}, MP_QSTR_Ellipsis};
Expand Down
7 changes: 7 additions & 0 deletions py/objslice.c
Original file line number Diff line number Diff line change
Expand Up @@ -46,6 +46,12 @@ STATIC void slice_print(const mp_print_t *print, mp_obj_t o_in, mp_print_kind_t
mp_print_str(print, ")");
}

STATIC mp_obj_t slice_unary_op(mp_unary_op_t op, mp_obj_t o_in) {
// Needed to explicitly opt out of default __hash__.
// REVISIT: CPython implements comparison operators for slice.
return MP_OBJ_NULL;
}

#if MICROPY_PY_BUILTINS_SLICE_INDICES
STATIC mp_obj_t slice_indices(mp_obj_t self_in, mp_obj_t length_obj) {
mp_int_t length = mp_obj_int_get_checked(length_obj);
Expand Down Expand Up @@ -104,6 +110,7 @@ MP_DEFINE_CONST_OBJ_TYPE(
mp_type_slice,
MP_QSTR_slice,
MP_TYPE_FLAG_NONE,
unary_op, slice_unary_op,
SLICE_TYPE_ATTR_OR_LOCALS_DICT
print, slice_print
);
Expand Down
1 change: 0 additions & 1 deletion py/objtype.c
Original file line number Diff line number Diff line change
Expand Up @@ -1112,7 +1112,6 @@ MP_DEFINE_CONST_OBJ_TYPE(
make_new, type_make_new,
print, type_print,
call, type_call,
unary_op, mp_generic_unary_op,
attr, type_attr
);

Expand Down
2 changes: 0 additions & 2 deletions py/profile.c
Original file line number Diff line number Diff line change
Expand Up @@ -177,7 +177,6 @@ MP_DEFINE_CONST_OBJ_TYPE(
MP_QSTR_code,
MP_TYPE_FLAG_NONE,
print, code_print,
unary_op, mp_generic_unary_op,
attr, code_attr
);

Expand Down Expand Up @@ -247,7 +246,6 @@ MP_DEFINE_CONST_OBJ_TYPE(
MP_QSTR_frame,
MP_TYPE_FLAG_NONE,
print, frame_print,
unary_op, mp_generic_unary_op,
attr, frame_attr
);

Expand Down
3 changes: 3 additions & 0 deletions py/runtime.c
Original file line number Diff line number Diff line change
Expand Up @@ -314,6 +314,9 @@ mp_obj_t mp_unary_op(mp_unary_op_t op, mp_obj_t arg) {
if (result != MP_OBJ_NULL) {
return result;
}
} else if (op == MP_UNARY_OP_HASH) {
// Type doesn't have unary_op so use hash of object instance.
return MP_OBJ_NEW_SMALL_INT((mp_uint_t)arg);
}
if (op == MP_UNARY_OP_BOOL) {
// Type doesn't have unary_op (or didn't handle MP_UNARY_OP_BOOL),
Expand Down
3 changes: 3 additions & 0 deletions tests/basics/builtin_compile.py
Original file line number Diff line number Diff line change
Expand Up @@ -42,4 +42,7 @@ def test():
print("NameError")
print(x) # check 'x' still exists as a global

# hashing a compiled function object
print(type(hash(compile("", "", "exec"))))

test()
18 changes: 18 additions & 0 deletions tests/basics/builtin_hash.py
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,24 @@
print({():1}) # hash tuple
print({(1,):1}) # hash non-empty tuple
print(hash in {hash:1}) # hash function
print(type(hash(list.pop))) # hash checked function (mp_type_checked_fun)
print(type(hash([].pop))) # hash bound method
print(type(hash(object()))) # hash object instance
print(type(hash(super(object, object)))) # hash super
print(type(hash(classmethod(hash)))) # hash classmethod
print(type(hash(staticmethod(hash)))) # hash staticmethod
print(type(hash(iter("")))) # hash string iterator
print(type(hash(iter(b"")))) # hash bytes iterator
print(type(hash(iter(range(0))))) # hash range iterator
print(type(hash(map(None, [])))) # hash map object
print(type(hash(zip([])))) # hash zip object

def f(x):
def g():
return x
return g

print(type(hash(f(1)))) # hash closure

try:
hash([])
Expand Down
18 changes: 18 additions & 0 deletions tests/basics/dict_views.py
Original file line number Diff line number Diff line change
Expand Up @@ -18,4 +18,22 @@
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
3 changes: 3 additions & 0 deletions tests/basics/io_buffered_writer.py
Original file line number Diff line number Diff line change
Expand Up @@ -25,3 +25,6 @@
buf = io.BufferedWriter(bts, 1)
buf.write(b"foo")
print(bts.getvalue())

# hashing a BufferedWriter
print(type(hash(buf)))
1 change: 1 addition & 0 deletions tests/basics/io_buffered_writer.py.exp
Original file line number Diff line number Diff line change
Expand Up @@ -3,3 +3,4 @@ b'foobarfo'
b'foobarfoobar'
b'foobarfoobar'
b'foo'
<class 'int'>
15 changes: 15 additions & 0 deletions tests/basics/slice_op.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@

try:
t = [][:]
except:
print("SKIP")
raise SystemExit


# REVISIT: slice comparison operators are not implemented in MicroPython

# test that slice is not hashable, i.e. it can't be used to copy a dict
try:
{}[:] = {}
except TypeError:
print('TypeError')