[issue44605] functools.total_ordering doesn't work with metaclasses

Glyph Lefkowitz report at bugs.python.org
Mon Jul 12 01:21:05 EDT 2021


New submission from Glyph Lefkowitz <glyph at twistedmatrix.com>:

Consider the following example that attempts to make a series of types sortable by their class name:




from functools import total_ordering

@total_ordering
class SortableMeta(type):
    def __new__(cls, name, bases, ns):
        return super().__new__(cls, name, bases, ns)

    def __lt__(self, other):
        if not isinstance(other, SortableMeta):
            pass
        return self.__name__ < other.__name__

    def __eq__(self, other):
        if not isinstance(other, SortableMeta):
            pass
        return self.__name__ == other.__name__

class B(metaclass=SortableMeta):
    pass

class A(metaclass=SortableMeta):
    pass


print(A < B)
print(A > B)


This should just print "True", "False", but instead the second comparison raises this exception:

Traceback (most recent call last):
  File "total_ordering_metaclass.py", line 27, in <module>
    print(A > B)
  File "lib/python3.9/functools.py", line 91, in _gt_from_lt
    op_result = self.__lt__(other)
TypeError: expected 1 argument, got 0


The problem here is that functools considers .__special__ to be equivalent to operator.special.  I'm pretty sure this should be invoking "self < other" rather than self.__lt__(other).

----------
components: Library (Lib)
messages: 397278
nosy: glyph
priority: normal
severity: normal
stage: needs patch
status: open
title: functools.total_ordering doesn't work with metaclasses
type: behavior
versions: Python 3.7, Python 3.8, Python 3.9

_______________________________________
Python tracker <report at bugs.python.org>
<https://bugs.python.org/issue44605>
_______________________________________


More information about the Python-bugs-list mailing list