This rule raises an issue when a class defines one or more rich comparison methods (__lt__, __le__, __gt__, __ge__) without using the functools.total_ordering decorator or defining all of them.

Why is this an issue?

Python classes can implement rich comparison methods to enable sorting and comparison operations. These methods include:

When you define only some of these methods, Python cannot automatically infer the missing ones. This leads to inconsistent behavior:

Python provides the functools.total_ordering decorator specifically to solve this problem. It allows you to define just __eq__ and one other comparison method, and it automatically generates the rest. This ensures consistent and correct comparison behavior across all operations.

What is the potential impact?

Incomplete comparison method implementations can cause several problems:

While this typically will not cause security vulnerabilities, it can lead to application logic errors that are difficult to diagnose and debug.

How to fix it

Either use the @functools.total_ordering decorator and define __eq__ and one ordering method, typically __lt__, or define all four ordering methods (__lt__, __le__, __gt__, __ge__) explicitly.

Code examples

Noncompliant code example

class Person:
    def __init__(self, name, age):
        self.name = name
        self.age = age

    def __lt__(self, other):  # Noncompliant
        return self.age < other.age

Compliant solution

from functools import total_ordering

@total_ordering
class Person:
    def __init__(self, name, age):
        self.name = name
        self.age = age

    def __eq__(self, other):
        return self.age == other.age

    def __lt__(self, other):
        return self.age < other.age

Noncompliant code example

class Point:
    def __init__(self, x, y):
        self.x = x
        self.y = y

    def __lt__(self, other):  # Noncompliant
        return self.x < other.x

Compliant solution

class Point:
    def __init__(self, x, y):
        self.x = x
        self.y = y

    def __lt__(self, other):
        return self.x < other.x

    def __le__(self, other):
        return self.x <= other.x

    def __gt__(self, other):
        return self.x > other.x

    def __ge__(self, other):
        return self.x >= other.x

How does this work?

The @functools.total_ordering decorator automatically generates all missing comparison methods from the ones you define. This ensures consistent and correct comparison behavior across all operations.

Resources

Documentation