X Tutup
The Wayback Machine - https://web.archive.org/web/20201019100835/https://github.com/python/typing/issues/760
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

Add SupportsLessThan to typing and typing_extensions #760

Open
hauntsaninja opened this issue Oct 13, 2020 · 9 comments
Open

Add SupportsLessThan to typing and typing_extensions #760

hauntsaninja opened this issue Oct 13, 2020 · 9 comments

Comments

@hauntsaninja
Copy link

@hauntsaninja hauntsaninja commented Oct 13, 2020

The latest version of mypy / typeshed uses a protocol for things passed to sorted / sort. As measured by mypy_primer, this was a fairly disruptive change. To correctly type some usage of sort / sorted, you need the protocol, and it's pretty hard for users to figure this out, eg: elastic/eland#283 (comment)
Adding the protocol to typing / typing_extensions would make this solution more discoverable and involve less end user protocol redefinition boilerplate when used.

@srittau
Copy link
Contributor

@srittau srittau commented Oct 14, 2020

Sounds like a good idea. In fact, adding protocols for other dunder protocols makes sense, too. See for example the dunder protocols in builtins.

@JelleZijlstra
Copy link
Contributor

@JelleZijlstra JelleZijlstra commented Oct 14, 2020

Adding it to typing(_extensions) is relatively painful though because it ties us to Python's release cycle. An alternative could be to release our _typeshed stub-only module as a PyPI package with a runtime component. On the plus side for adding these things to typing though, it's more discoverable for users than a new package.

@srittau
Copy link
Contributor

@srittau srittau commented Oct 14, 2020

Oops, I was misreading this. I was talking about _typeshed, not typing(_extensions), although I'm +0 to add it to the latter as well.

@V1NAY8
Copy link

@V1NAY8 V1NAY8 commented Oct 14, 2020

The Example given above was this

Item = TypeVar("Item")
def try_sort(iterable: Iterable[Item]) -> Iterable[Item]:
    # Pulled from pandas.core.common since
    # it was deprecated and removed in 1.1
    listed = list(iterable)
    try:
        return sorted(listed)
    except TypeError:
        return listed
  • mypy says: Value of type variable "_LT" of "sorted" cannot be "Item"

So, I changed it to str and it worked 😮

def try_sort(iterable: Iterable[str]) -> Iterable[str]:
    # Pulled from pandas.core.common since
    # it was deprecated and removed in 1.1
    listed = list(iterable)
    try:
        return sorted(listed)
    except TypeError:
        return listed

I am trying to figure out what was the general solution to this issue?

@gvanrossum
Copy link
Member

@gvanrossum gvanrossum commented Oct 14, 2020

Adding it to typing(_extensions) is relatively painful though because it ties us to Python's release cycle.

Note that typing_extensions is not tied to the CPython release cycle.

@hauntsaninja
Copy link
Author

@hauntsaninja hauntsaninja commented Oct 14, 2020

@V1NAY8

The general solution if we add this to typing(_extensions) is:

SupportsLessThanT = typing.TypeVar("SupportsLessThanT", bound=typing.SupportsLessThan)
def function_that_wraps_sort(iterable: SupportsLessThanT) -> SupportsLessThanT: ...

If this isn't added to typing(_extensions), you'll need to define the SupportsLessThan protocol yourself , which looks like this.

But now that I'm looking closely at your code, some more comments:

  • What mypy does now is try to ensure that arguments to sorted are comparable. The above "general" solution will try to ensure that arguments to try_sort are comparable. But that doesn't seem to be what you want... your try_sort expects to raise a TypeError sometimes, which is naturally something that mypy should complain about! So I would continue to use your Item TypeVar and just type: ignore the sorted line, as you would if you were doing: try: 1 + sometimes_int_sometimes_str() except: TypeError: ...
  • In your case, if you can change the type to Iterable[str] without mypy complaining, it might mean you don't actually need try_sort and can just use sorted everywhere.

@everyoneelse

It sounds like no one is opposed, but no one feels strongly either? In that case, maybe we hold off and see if people complain, rather than presumptively making a decision based on mypy_primer.
It's also not clear to me what, if any, the process here is.

@guilhermeleobas
Copy link

@guilhermeleobas guilhermeleobas commented Oct 16, 2020

@hauntsaninja, I am facing the same problem with min:

torch/distributions/kl.py:112: error: Value of type variable "_LT" of "min" cannot be "_Match"  [type-var]
torch/distributions/kl.py:113: error: Value of type variable "_LT" of "min" cannot be "_Match"  [type-var]

The lines involved are the ones below
https://github.com/pytorch/pytorch/blob/146721f1dfe29786f5d25a9e2a2c2227dfa85f76/torch/distributions/kl.py#L107-L108

@hauntsaninja
Copy link
Author

@hauntsaninja hauntsaninja commented Oct 16, 2020

@guilhermeleobas Hmm, your false positive is a little tricky. The problem is that there isn't a good way to type the return type of functools.total_ordering (python/mypy#4610 / intersection types), so mypy don't see that _Match does have __lt__ and things are in fact okay.

Some possibilities:

  • If we were to add SupportsLessThan to typing(_extensions) / if you define it yourself, you can do cast(SupportsLessThan, Match(...)) for m in matches)
  • You can use the implementation details of functools.total_ordering to somewhat sketchily add __lt__: Callable = None # type: ignore to the _Match class.
  • You can type ignore
@guilhermeleobas
Copy link

@guilhermeleobas guilhermeleobas commented Oct 16, 2020

Thanks @hauntsaninja, I will give it a try.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Linked pull requests

Successfully merging a pull request may close this issue.

None yet
6 participants
You can’t perform that action at this time.
X Tutup