ITADN

Result classes do not respect rich comparison

#2272Opendrhagenabm 创建于 2025-10-07
D
drhagenabmcommented
In an equality `A() == B()`, Python first invokes `A.__eq__(a, b)`. If `A` does not understand `B` as a type to which it can do a comparison, [it is supposed to](https://docs.python.org/3/reference/datamodel.html#object.__eq__) return the `NotImplemented` sentinel, which triggers Python to invoke `B.__eq__(b, a)`. The `Success` and `Failure` classes of `returns.result` do not return `NotImplemented` from their `__eq__` methods and therefore do not allow for a rich comparison with instances of these classes. This is annoying for a number of reason. For example, this make it impossible to implement a shim that would be needed to do a backwards-compatible migration of a custom `MyResult` class hierarchy to the Returns `Result` hierarchy. See below, where it is impossible to create a `MySuccess` class that is equal to the `Success` class, but only when the Returns class is first. ```python from dataclasses import dataclass from typing import Never from returns import result class MyResult[Value, Error]: pass @dataclass class MySuccess[Value](MyResult[Value, Never]): value: Value def __eq__(self, other): match other: case MySuccess(value): return self.value == value case result.Success(value): return self.value == value case _: return False @dataclass class MyFailure[Error](MyResult[Never, Error]): error: Error def __eq__(self, other): match other: case MyFailure(error): return self.error == error case result.Failure(error): return self.error == error case _: return False assert MySuccess(10) == result.Success(10) assert result.Success(10) == MySuccess(10) # Fails assert MyFailure("error") == result.Failure("error") assert result.Failure("error") == MyFailure("error") # Fails ```
4 条评论