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

isinstance(x, Tuple) fails when equivalent expressions don't #6680

Open
lbenezriravin opened this issue Apr 16, 2019 · 11 comments
Open

isinstance(x, Tuple) fails when equivalent expressions don't #6680

lbenezriravin opened this issue Apr 16, 2019 · 11 comments
Labels
bug mypy got something wrong false-positive mypy gave an error on correct code priority-2-low topic-runtime-semantics mypy doesn't model runtime semantics correctly

Comments

@lbenezriravin
Copy link

reproducer

from typing import Any, Dict, Tuple

x = (1,2)
isinstance(x, tuple)
isinstance(x, Tuple[Any, ...])
isinstance(x, Tuple)

observed behavior

$ pipenv run mypy test.py 
test.py:6: error: Argument 2 to "isinstance" has incompatible type "_SpecialForm"; expected "Union[type, Tuple[Union[type, Tuple[Any, ...]], ...]]"

expected behavior
The python documentation states

A plain Tuple is equivalent to Tuple[Any, ...], and in turn to tuple.

If the above is true, IMO either all of the examples should raise errors, or none of them should. Only the third example is raising an error right now. I'm not quite sure what the error means in any case.

environment
master as of 2019-04-15

$ pipenv graph
mypy==0.710+dev.2c8a809693cf5be0b29d272d7f0711521bd4a55a
  - mypy-extensions [required: >=0.4.0,<0.5.0, installed: 0.4.1]
  - typed-ast [required: >=1.3.1,<1.4.0, installed: 1.3.1]

As always, thanks for all the work you do here!

@gvanrossum gvanrossum added the bug mypy got something wrong label Apr 16, 2019
@gvanrossum
Copy link
Member

I am guessing the sentence you quote from the docs applies to its use in type annotations, not in isinstance(). In that case IMO only tuple should be allowed, because at runtime the other use of Tuple raises a TypeError. IMO it's a mypy bug that it doesn't report both uses of Tuple as errors. (I'm too lazy to look up what the mypy docs say about this -- they tend to be more correct than the Python docs about type checking matters.)

@lbenezriravin
Copy link
Author

Ah, I see that now. If you don't mind me asking, why does Tuple behave differently from other superficially similar generics? For example,

y = {1: 1}
isinstance(y, Dict)
isinstance(y, Sequence)

don't raise TypeErrors unless I parameterize the generics.

@gvanrossum
Copy link
Member

Because Tuple is not a generic class, it's a special form. This is so that it can take a variable number of parameters.

@lbenezriravin
Copy link
Author

That makes sense. Thanks for the guidance!

@ilevkivskyi
Copy link
Member

Essentially, the mypy behavior is opposite to what happens at runtime:

isinstance((), Tuple)  # Works at runtime, error in mypy
isinstance((), Tuple[Any, ...])  # Error at runtime, no error in mypy

I think however this is a low priority, you should really just use tuple.

@AlexWaygood
Copy link
Member

AlexWaygood commented Mar 29, 2022

On 0.941, mypy now correctly emits an error for isinstance(x, Tuple[Any, ...]). It still gives a false-positive error for isinstance(x, Tuple), though:

from typing import Any, Tuple

x = (1,2)
isinstance(x, tuple)
isinstance(x, Tuple[Any, ...])  # error: Argument 2 to "isinstance" has incompatible type "object"; expected "Union[type, UnionType, Tuple[Union[type, UnionType, Tuple[Any, ...]], ...]]"
isinstance(x, Tuple)  # error: Argument 2 to "isinstance" has incompatible type "_SpecialForm"; expected "Union[type, UnionType, Tuple[Union[type, UnionType, Tuple[Any, ...]], ...]]"

@AlexWaygood
Copy link
Member

(Closed by accident)

@gvanrossum
Copy link
Member

So what's to do here? The OP is about runtime behavior, which should not be discussed in the mypy tracker.

@AlexWaygood
Copy link
Member

AlexWaygood commented Mar 29, 2022

I read the OP as being about the false-positive error mypy emits on this snippet of code:

from typing import Tuple
isinstance(x, Tuple)

This works fine at runtime, but mypy 0.942 reports:

error: Argument 2 to "isinstance" has incompatible type "_SpecialForm"; expected "Union[type, UnionType, Tuple[Union[type, UnionType, Tuple[Any, ...]], ...]]"

It's hardly a priority to fix, but it does seem to me to be a legitimate bug?

@AlexWaygood
Copy link
Member

I've just closed #6864 as a duplicate -- #6864 is about isinstance(x, collections.abc.Callable) causing mypy to error out, with exactly the same error message. (That also works fine at runtime.)

@AlexWaygood AlexWaygood added the topic-runtime-semantics mypy doesn't model runtime semantics correctly label Mar 29, 2022
@randolf-scholz
Copy link
Contributor

#14014 is likely also a duplicate. This issue persists when checking against Callable class pattern in match-case statements

match x:
    case collections.abc.Callable() as func:
        ...

Literally all other classes in collections.abc seem to work without problem.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
bug mypy got something wrong false-positive mypy gave an error on correct code priority-2-low topic-runtime-semantics mypy doesn't model runtime semantics correctly
Projects
None yet
Development

No branches or pull requests

5 participants