Skip to content

Unexpected sorted result #130823

@mwtoews

Description

@mwtoews

Bug report

Bug description:

Python 3.13 breaks the sorted() built-in using a custom class key. Here is some demo code to show it:

class Within:
    def __init__(self, o):
        self.o = o
    def __lt__(self, other):
        print("{}.issubset({}): {}".format(self.o, other.o, self.o.issubset(other.o)))
        return self.o.issubset(other.o)

a = set([1])
b = set([1, 2])
c = set([1, 2, 3])
d = set([4])
actual = sorted([c, a, d, b, c], key=Within)
expected = [a, b, c, c, d]
print("(actual == expected):", actual == expected)

The Within class defines if a set is "within" another via issubset (or <= operator) method in __lt__, which also prints the comparison to show what the sort algorithm is comparing.

Testing with Python 3.3 to Python 3.12 via docker, the expected output is:

{1}.issubset({1, 2, 3}): True
{4}.issubset({1}): False
{4}.issubset({1, 2, 3}): False
{1, 2}.issubset({1, 2, 3}): True
{1, 2}.issubset({1}): False
{1, 2, 3}.issubset({1, 2, 3}): True
{1, 2, 3}.issubset({1, 2}): False
(actual == expected): True

But with Python 3.13.0 to 3.13.2 via docker, the output is unexpected:

{1}.issubset({1, 2, 3}): True
{4}.issubset({1}): False
{1}.issubset({4}): False
{1, 2}.issubset({4}): False
{4}.issubset({1, 2}): False
{1, 2, 3}.issubset({1, 2}): False
{1, 2}.issubset({1, 2, 3}): True
{1, 2, 3}.issubset({1, 2, 3}): True
{1, 2, 3}.issubset({1, 2}): False
{1, 2, 3}.issubset({1, 2, 3}): True
(actual == expected): False

The result ([a, d, b, c, c]) is incorrect and takes longer (more comparison combinations requested). Some of the comparisons are done more than once (e.g. {1, 2, 3}.issubset({1, 2, 3}) and {1, 2, 3}.issubset({1, 2}) each appear twice), but this is perhaps because c appears twice.

The background for this issue is that I discovered it while looking at upgrading doctesting for this shapely manual using Python 3.13.1. The example make a custom class that uses a geospatial "contains" method for __lt__.

CPython versions tested on:

3.13

Operating systems tested on:

Linux

Metadata

Metadata

Assignees

No one assigned

    Labels

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions