
Inline adoc files when they are included exactly once. Also fix language tags because this inlining gives us better information on what language the code is written in.
88 lines
2.6 KiB
Plaintext
88 lines
2.6 KiB
Plaintext
== Why is this an issue?
|
|
|
|
:link-with-uscores1: https://docs.python.org/3/reference/datamodel.html?highlight=__exit__%20special%20methods#emulating-numeric-types
|
|
:link-with-uscores2: https://docs.python.org/3/reference/datamodel.html?highlight=__exit__%20special%20methods#object.__lt__
|
|
|
|
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. It is for example possible to add two integers: ``++1 + 2++``. It is however not possible to add a string and an integer: ``++1 + "2"++`` and such an operation will raise a ``++TypeError++``.
|
|
|
|
|
|
It is possible to define how an operator will behave with a custom class by defining the corresponding special method. See python documentation for a complete list of operators and their methods: {link-with-uscores1}[arithmetic and bitwise operators], {link-with-uscores2}[comparison operators].
|
|
|
|
|
|
For symmetrical binary operators you need to define two methods so that the order of operands doesn't matter, ex: ``++__add__++`` and ``++__radd__++``.
|
|
|
|
|
|
This rule raises an issue when an operator is used on incompatible types. Types are considered incompatible if no built-in operations between those types exist and none of the operands has implemented the corresponding special methods.
|
|
|
|
|
|
=== Noncompliant code example
|
|
|
|
[source,python]
|
|
----
|
|
class Empty:
|
|
pass
|
|
|
|
class Add:
|
|
def __add__(self, other):
|
|
return 42
|
|
|
|
1 + 2
|
|
1 + "2" # Noncompliant
|
|
Empty() + 1 # Noncompliant
|
|
Add() + 1
|
|
1 + Add() # Noncompliant
|
|
Add() + Empty()
|
|
Empty() + Add() # Noncompliant
|
|
----
|
|
|
|
|
|
=== 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()
|
|
----
|
|
|
|
|
|
:link-with-uscores1: https://docs.python.org/3/reference/datamodel.html?highlight=__exit__%20special%20methods#object.__lt__
|
|
:link-with-uscores2: https://docs.python.org/3/reference/datamodel.html?highlight=__exit__%20special%20methods#emulating-numeric-types
|
|
|
|
== Resources
|
|
|
|
* Python documentation - {link-with-uscores1}[Rich comparison methods]
|
|
* Python documentation - {link-with-uscores2}[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[]
|