90 lines
2.6 KiB
Plaintext
90 lines
2.6 KiB
Plaintext
This rule raises an issue when an operator is used on incompatible types.
|
|
|
|
== Why is this an issue?
|
|
|
|
:link-with-uscores1: https://docs.python.org/3/reference/datamodel.html?#emulating-numeric-types
|
|
:link-with-uscores2: https://docs.python.org/3/reference/datamodel.html?#object.__lt__
|
|
|
|
For a specific operator, two types are considered incompatible if no built-in operations between those types exist and none of the operands has implemented the operator's corresponding special methods.
|
|
Performing such an operation on incompatible types will raise a `TypeError`.
|
|
|
|
Calling an operator in Python is equivalent to calling a special method (except for the identity operator `is`).
|
|
Python provides a set of built-in operations. For example, to add two integers: `1 + 2`, calling the built-in operator `+` is equivalent to calling the special method ``++__add__++`` on the type `int`.
|
|
|
|
Python allows developers to define how an operator will behave with a custom class by implementing the corresponding special method.
|
|
When defining such methods for symmetrical binary operators, developers need to define two methods so that the order of operands doesn't matter, ex: ``++__add__++`` and ``++__radd__++``.
|
|
|
|
For a complete list of operators and their methods see the Python documentation: {link-with-uscores1}[arithmetic and bitwise operators], {link-with-uscores2}[comparison operators].
|
|
|
|
== How to fix it
|
|
|
|
Implementing the special methods for a specific operator will fix the issue.
|
|
|
|
=== Code examples
|
|
|
|
==== Noncompliant code example
|
|
|
|
[source,python]
|
|
----
|
|
class Empty:
|
|
pass
|
|
|
|
class Add:
|
|
def __add__(self, other):
|
|
return 42
|
|
|
|
Empty() + 1 # Noncompliant: no __add__ method is defined on the Empty class
|
|
Add() + 1
|
|
1 + Add() # Noncompliant: no __radd__ method is defined on the Add class
|
|
Add() + Empty()
|
|
Empty() + Add() # Noncompliant: no __radd__ method is defined on the Add class
|
|
----
|
|
|
|
==== Compliant solution
|
|
|
|
[source,python]
|
|
----
|
|
class Empty:
|
|
pass
|
|
|
|
class Add:
|
|
def __add__(self, other):
|
|
return 42
|
|
|
|
def __radd__(self, other):
|
|
return 42
|
|
|
|
Add() + 1
|
|
1 + Add()
|
|
Add() + Empty()
|
|
Empty() + Add()
|
|
----
|
|
|
|
== Resources
|
|
|
|
=== Documentation
|
|
|
|
* {link-with-uscores2}[Rich comparison methods]
|
|
* {link-with-uscores1}[Emulating numeric types]
|
|
|
|
ifdef::env-github,rspecator-view[]
|
|
|
|
'''
|
|
== Implementation Specification
|
|
(visible only on this page)
|
|
|
|
=== Message
|
|
|
|
* Fix this invalid XXX operation between incompatible types.
|
|
* Fix this invalid XXX operation on a type which doesn't support it.
|
|
|
|
|
|
=== Highlighting
|
|
|
|
Primary location: the operator
|
|
|
|
Secondary locations: the operand(s)
|
|
|
|
|
|
endif::env-github,rspecator-view[]
|