Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

input to sorted is treated differently based on where the output is passed. #5394

Closed
lengau opened this issue Jun 27, 2023 · 1 comment
Closed
Labels
as designed Not a bug, working as intended bug Something isn't working

Comments

@lengau
Copy link

lengau commented Jun 27, 2023

Describe the bug
The same input to sorted can produce (or not produce) an error depending on how the output is used.

To Reproduce
A minimal reproducer is included below. This behaviour appears to have changed in version 1.1.281, as version 1.1.280 does not behave this way.

Expected behavior
I believe the correct behaviour is to not bring up an error in either of the cases below. However, it's possible that both cases should result in the error. I think that pyright is using the SupportsRichComparisonT overload of sorted in the case that raises the error and the Iterable[_T] overload in that case that does not.

Code or Screenshots
Minimal reproducer.

import operator
from typing import Any, Iterable, Mapping

def do_a_thing(data: Iterable[Iterable[Any]]):
    pass


track_table = [
    [
        "name",
        "status",
    ]
]

# Produces an error: Argument of type "itemgetter[int]" cannot be assigned to parameter "key" of type "(_T@sorted) -> SupportsRichComparison" in function "sorted"
do_a_thing(sorted(track_table, key=operator.itemgetter(0)))

# Does not produce an error.
sorted_list = sorted(track_table, key=operator.itemgetter(0))
do_a_thing(sorted_list)

VS Code extension or command-line
CLI tool. Occurs with the reproducer above starting in version 1.1.281, occurs with tabulate.tabulate starting at version 1.1.315. We're using tabulate v0.9.0.

Additional context
We discovered this after updating our CI to v1.1.315, which causes existing code (circa April 2022) to bring this error. This code uses tabulate.tabulate: https://github.com/snapcore/snapcraft/blob/main/snapcraft/commands/names.py#L140

@lengau lengau added the bug Something isn't working label Jun 27, 2023
lengau added a commit to lengau/snapcraft that referenced this issue Jun 27, 2023
@erictraut
Copy link
Collaborator

This isn't a bug. Pyright is doing the correct thing here given the definition of sorted. Not surprisingly, mypy produces the same error in this case.

There are two overloads provided for sorted. The first applies only when key is omitted. The second is the one that applies to your code samples above:

def sorted(__iter: Iterable[T], *, key: Callable[[T], SupportsRichComparison]) -> list[T]:
    ...

It includes both an Iterable and a SupportsRichComparison.

The reason you're seeing different behaviors (an error in one case and not in the other) is because of bidirectional type inference. The type of the parameter data influences the way that the expression sorted(track_table, key=operator.itemgetter(0)) is evaluated. If you change your second example (the one the doesn't include an error) to include an explicit type annotation, you'll see that the same error is reported.

sorted_list: Iterable[Iterable[Any]] = sorted(track_table, key=operator.itemgetter(0))

If you omit the annotation for sorted_list or change it to Iterable[list[Any]], the error will go away.

@erictraut erictraut added the as designed Not a bug, working as intended label Jun 28, 2023
lengau added a commit to canonical/snapcraft that referenced this issue Jun 28, 2023
mr-cal pushed a commit to canonical/snapcraft that referenced this issue Jun 29, 2023
sergiusens pushed a commit to canonical/snapcraft that referenced this issue Jun 29, 2023
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
as designed Not a bug, working as intended bug Something isn't working
Projects
None yet
Development

No branches or pull requests

2 participants