This rule raises an issue when a special method raises a `NotImplementedError` instead of returning `NotImplemented`. == Why is this an issue? In Python, special methods corresponding to numeric operators and rich comparison operators should return ``++NotImplemented++`` when the operation is not supported. 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)++``. If these special methods were to raise `NotImplementedError`, the callers would not catch the exception and the reverse operation would not be called. Below is the list of special methods this rule applies to: * ``++__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)`` == How to fix it Make sure special methods return `NotImplemented` instead of raising a `NotImplementedError`. === Code examples ==== Noncompliant code example [source,python,diff-id=1,diff-type=noncompliant] ---- class MyClass: def __add__(self, other): raise NotImplementedError() # Noncompliant: the exception will be propagated def __radd__(self, other): raise NotImplementedError() # Noncompliant: the exception will be propagated class MyOtherClass: def __add__(self, other): return 42 def __radd__(self, other): return 42 MyClass() + MyOtherClass() # This will raise NotImplementedError ---- ==== Compliant solution [source,python,diff-id=1,diff-type=compliant] ---- 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 ---- === Pitfalls The ``++__length_hint__++`` special method also requires to return a `NotImplemented`. Its behavior differs from the other methods, because when it returns `NotImplemented`, a default value will be returned instead. See https://peps.python.org/pep-0424/[PEP 424] for more information. == Resources === Documentation * 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] === Standards * PEP 424 - https://peps.python.org/pep-0424/[A method exposing ``++__length_hint__++``] 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[]