rspec/rules/S5712/python/rule.adoc

98 lines
3.2 KiB
Plaintext
Raw Normal View History

2021-04-28 16:49:39 +02:00
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
----
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
----
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
----
== See
* 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]