Skip to content

isinstance(..., collections.abc.Callable) complains about "_SpecialForm" #6864

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

Closed
asottile opened this issue May 19, 2019 · 9 comments
Closed
Labels
bug mypy got something wrong false-positive mypy gave an error on correct code priority-2-low

Comments

@asottile
Copy link
Contributor

input

from collections.abc import Callable

def f(): pass

print(isinstance(f, Callable))

output

$ mypy t.py
t.py:5: error: Argument 2 to "isinstance" has incompatible type "_SpecialForm"; expected "Union[type, Tuple[Union[type, Tuple[Any, ...]], ...]]"
$ mypy --version
mypy 0.701

fix (for me)

the fix for me is to just use callable(...), however in some cases this wasn't possible and so for now I'm # type: ignoreing

@ilevkivskyi
Copy link
Member

however in some cases this wasn't possible

Why it was not possible? Generally I think we should try to limit "leaking" the internal things like _SpecialForm, but OTOH, I don't think this is high priority ATM.

@ilevkivskyi ilevkivskyi added bug mypy got something wrong false-positive mypy gave an error on correct code priority-2-low labels May 19, 2019
@asottile
Copy link
Contributor Author

there were a few cases where the abc types were used as a first-class object

Here's a contrived minimal example that's similar and also has the same failure mode:

from typing import Tuple, Type
from collections.abc import Callable
from collections.abc import Sized

classifier: Tuple[Tuple[str, Type], ...] = (
    ('callable', Callable),
    ('sized', Sized),
)
$ ./venv/bin/mypy t.py
t.py:5: error: Incompatible types in assignment (expression has type "Tuple[Tuple[str, _SpecialForm], Tuple[str, Type[Sized]]]", variable has type "Tuple[Tuple[str, Type[Any]], ...]")

@AlexWaygood
Copy link
Member

I'm going to close this as a duplicate of #6680 (it's the same bug), and add a comment to that issue.

@asottile
Copy link
Contributor Author

I think that's slightly different -- that one is about typing types (which aren't supposed to be used for isinstance afaik), and this is about collections.abc types (which are)

@AlexWaygood
Copy link
Member

AlexWaygood commented Mar 29, 2022

I think that's slightly different -- that one is about typing types (which aren't supposed to be used for isinstance afaik), and this is about collections.abc types (which are)

They look pretty similar to me at runtime:

Python 3.10.3 (tags/v3.10.3:a342a49, Mar 16 2022, 13:07:40) [MSC v.1929 64 bit (AMD64)] on win32
Type "help", "copyright", "credits" or "license" for more information.
>>> from collections.abc import Callable
>>> isinstance(lambda x: x, Callable[[object], object])
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
TypeError: isinstance() argument 2 cannot be a parameterized generic
>>> isinstance(lambda x: x, Callable)
True
>>> from typing import Tuple
>>> isinstance((1, 2), Tuple[int, int])
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
  File "C:\Users\alexw\AppData\Local\Programs\Python\Python310\lib\typing.py", line 994, in __instancecheck__
    return self.__subclasscheck__(type(obj))
  File "C:\Users\alexw\AppData\Local\Programs\Python\Python310\lib\typing.py", line 997, in __subclasscheck__
    raise TypeError("Subscripted generics cannot be used with"
TypeError: Subscripted generics cannot be used with class and instance checks
>>> isinstance((1, 2), Tuple)
True
>>>

And from mypy's perspective, they're identical, since typeshed just does from typing import Callable as Callable in the stub for collections.abc.

@asottile
Copy link
Contributor Author

this issue predates PEP 585 and doesn't involve generics

@AlexWaygood
Copy link
Member

AlexWaygood commented Mar 29, 2022

this issue predates PEP 585 and doesn't involve generics

I'm aware of that. But if you read my example in full, I show that isinstance(x, typing.Tuple) succeeds at runtime just like isinstance(x, collections.abc.Callable). Yet mypy emits the same false-positive error for both of them.

For both typing.Tuple and collections.abc.Callable, it is only the subscripted version of the special form that fails when passed to isinstance() at runtime.

@asottile
Copy link
Contributor Author

For both typing.Tuple and collections.abc.Callable, it is only the subscripted version of the special form that fails when passed to isinstance() at runtime.

yeah that's precisely my point -- this issue doesn't involve subscripted isinstance at all whereas the other issue is focused on that

but you're the triager I'm just a rando so feel free to ignore me 👍

@AlexWaygood
Copy link
Member

AlexWaygood commented Mar 29, 2022

The other issue is actually now only being kept open because of the false-positive when an unsubscripted typing.Tuple is passed to isinstance(). Mypy now emits a true-positive error when passing a subscripted typing.Tuple to isinstance(), so that part of the issue's now resolved.

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
Projects
None yet
Development

No branches or pull requests

3 participants