aboutsummaryrefslogtreecommitdiff
path: root/py/obj.h
diff options
context:
space:
mode:
authorNicko van Someren <nicko@nicko.org>2019-12-31 15:19:12 -0700
committerDamien George <damien.p.george@gmail.com>2020-01-30 14:53:07 +1100
commit3aab54bf434e7f025a91ea05052f1bac439fad8c (patch)
tree838593685c39f9ee39dd0556715e4a1fc7038e93 /py/obj.h
parentc3450effd4c3a402eeccf44a84a05ef4b36d69a0 (diff)
py: Support non-boolean results for equality and inequality tests.
This commit implements a more complete replication of CPython's behaviour for equality and inequality testing of objects. This addresses the issues discussed in #5382 and a few other inconsistencies. Improvements over the old code include: - Support for returning non-boolean results from comparisons (as used by numpy and others). - Support for non-reflexive equality tests. - Preferential use of __ne__ methods and MP_BINARY_OP_NOT_EQUAL binary operators for inequality tests, when available. - Fallback to op2 == op1 or op2 != op1 when op1 does not implement the (in)equality operators. The scheme here makes use of a new flag, MP_TYPE_FLAG_NEEDS_FULL_EQ_TEST, in the flags word of mp_obj_type_t to indicate if various shortcuts can or cannot be used when performing equality and inequality tests. Currently four built-in classes have the flag set: float and complex are non-reflexive (since nan != nan) while bytearray and frozenszet instances can equal other builtin class instances (bytes and set respectively). The flag is also set for any new class defined by the user. This commit also includes a more comprehensive set of tests for the behaviour of (in)equality operators implemented in special methods.
Diffstat (limited to 'py/obj.h')
-rw-r--r--py/obj.h7
1 files changed, 7 insertions, 0 deletions
diff --git a/py/obj.h b/py/obj.h
index 2bc72b586..2e91b6b15 100644
--- a/py/obj.h
+++ b/py/obj.h
@@ -445,8 +445,14 @@ typedef mp_obj_t (*mp_fun_var_t)(size_t n, const mp_obj_t *);
typedef mp_obj_t (*mp_fun_kw_t)(size_t n, const mp_obj_t *, mp_map_t *);
// Flags for type behaviour (mp_obj_type_t.flags)
+// If MP_TYPE_FLAG_NEEDS_FULL_EQ_TEST is clear then all the following hold:
+// (a) the type only implements the __eq__ operator and not the __ne__ operator;
+// (b) __eq__ returns a boolean result (False or True);
+// (c) __eq__ is reflexive (A==A is True);
+// (d) the type can't be equal to an instance of any different class that also clears this flag.
#define MP_TYPE_FLAG_IS_SUBCLASSED (0x0001)
#define MP_TYPE_FLAG_HAS_SPECIAL_ACCESSORS (0x0002)
+#define MP_TYPE_FLAG_NEEDS_FULL_EQ_TEST (0x0004)
typedef enum {
PRINT_STR = 0,
@@ -729,6 +735,7 @@ void mp_obj_print_exception(const mp_print_t *print, mp_obj_t exc);
bool mp_obj_is_true(mp_obj_t arg);
bool mp_obj_is_callable(mp_obj_t o_in);
+mp_obj_t mp_obj_equal_not_equal(mp_binary_op_t op, mp_obj_t o1, mp_obj_t o2);
bool mp_obj_equal(mp_obj_t o1, mp_obj_t o2);
static inline bool mp_obj_is_integer(mp_const_obj_t o) { return mp_obj_is_int(o) || mp_obj_is_bool(o); } // returns true if o is bool, small int or long int