== Why is this an issue? In Python, special methods corresponding to numeric operators, rich comparison operators and the ``++__length_hint__++`` method should return ``++NotImplemented++`` when the operation is not supported. These methods should not raise ``++NotImplementedError++`` as callers don't expect it and won't catch this exception. For example ``++A + B++`` is equivalent to calling ``++A.__add__(B)++``. If this binary operation is not supported by class A, ``++A.__add__(B)++`` should return ``++NotImplemented++``. The interpreter will then try the reverse operation, i.e. ``++B.__radd__(A)++``. This enables adding new operations by changing only one class instead of two. This rule raises an issue when one of the following methods raises ``++NotImplementedError++`` instead of returning ``++NotImplemented++``: * ++__lt__++(self, other) * ++__le__++(self, other) * ++__eq__++(self, other) * ++__ne__++(self, other) * ++__gt__++(self, other) * ++__ge__++(self, other) * ++__add__++(self, other) * ++__sub__++(self, other) * ++__mul__++(self, other) * ++__matmul__++(self, other) * ++__truediv__++(self, other) * ++__floordiv__++(self, other) * ++__mod__++(self, other) * ++__divmod__++(self, other) * ++__pow__++(self, other[, modulo]) * ++__lshift__++(self, other) * ++__rshift__++(self, other) * ++__and__++(self, other) * ++__xor__++(self, other) * ++__or__++(self, other) * ++__radd__++(self, other) * ++__rsub__++(self, other) * ++__rmul__++(self, other) * ++__rmatmul__++(self, other) * ++__rtruediv__++(self, other) * ++__rfloordiv__++(self, other) * ++__rmod__++(self, other) * ++__rdivmod__++(self, other) * ++__rpow__++(self, other[, modulo]) * ++__rlshift__++(self, other) * ++__rrshift__++(self, other) * ++__rand__++(self, other) * ++__rxor__++(self, other) * ++__ror__++(self, other) * ++__iadd__++(self, other) * ++__isub__++(self, other) * ++__imul__++(self, other) * ++__imatmul__++(self, other) * ++__itruediv__++(self, other) * ++__ifloordiv__++(self, other) * ++__imod__++(self, other) * ++__ipow__++(self, other[, modulo]) * ++__ilshift__++(self, other) * ++__irshift__++(self, other) * ++__iand__++(self, other) * ++__ixor__++(self, other) * ++__ior__++(self, other) * ++__length_hint__++(self) === Noncompliant code example [source,python] ---- class MyClass: def __add__(self, other): raise NotImplementedError() # Noncompliant def __radd__(self, other): raise NotImplementedError() # Noncompliant class MyOtherClass: def __add__(self, other): return 42 def __radd__(self, other): return 42 MyClass() + MyOtherClass() # This will raise NotImplementedError ---- === Compliant solution [source,python] ---- class MyClass: def __add__(self, other): return NotImplemented def __radd__(self, other): return NotImplemented class MyOtherClass: def __add__(self, other): return 42 def __radd__(self, other): return 42 MyClass() + MyOtherClass() # This returns 42 ---- == Resources * Python documentation - https://docs.python.org/3/library/constants.html#NotImplemented[Built-in Constants - NotImplemented] * Python documentation - https://docs.python.org/3/library/numbers.html#implementing-the-arithmetic-operations[Implementing the arithmetic operations] ifdef::env-github,rspecator-view[] ''' == Implementation Specification (visible only on this page) === Message Return "NotImplemented" instead of raising "NotImplementedError" === Highlighting The raise statement. endif::env-github,rspecator-view[]