Return NotImplemented in newstr.eq · Issue #432 · PythonCharmers/python-future (original) (raw)

We stumbled upon an edge case in our codebase, related to newstr.__eq__ returning False instead of NotImplemented. Is this intended?

def __eq__(self, other):
if (isinstance(other, unicode) or
isinstance(other, bytes) and not isnewbytes(other)):
return super(newstr, self).__eq__(other)
else:
return False

For clarification, returning False in __eq__ indicates a successful comparison of inequal objects. Judging by the code, the else branch should return Notimplemented, which indicates that the check was not successful. This allows the other object's __eq__ to be called.

See Python 2 data model and Python 3 data model:

A rich comparison method may return the singleton NotImplemented if it does not implement the operation for a given pair of arguments. By convention, False and True are returned for a successful comparison.
[...]
Numeric methods and rich comparison methods should return [NotImplemented] if they do not implement the operation for the operands provided. (The interpreter will then try the reflected operation, or some other fallback, depending on the operator.)

Our codebase has string-like objects that are not a subclass of str or unicode but have identical semantics. Whether this is a good idea is big internal debate, but for now it is part of the codebase. This leads to asymmetrical equality, which we would like to fix:

our_str = OurCustomString("foobar") new_str = future.builtins.str("foobar")

our_str == new_str # -> True new_str == our_str # -> False