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

Import of Protocol is broken aftre form typing import * #4427

Closed
ilevkivskyi opened this issue Jan 3, 2018 · 10 comments
Closed

Import of Protocol is broken aftre form typing import * #4427

ilevkivskyi opened this issue Jan 3, 2018 · 10 comments
Labels

Comments

@ilevkivskyi
Copy link
Member

This code:

from typing import *
from typing_extensions import Protocol

leads to a weird error:

Incompatible import of "Protocol" (imported name has type "typing_extensions._SpecialForm", local name has type "typing._SpecialForm")
@elliott-beach
Copy link
Contributor

elliott-beach commented Jan 4, 2018

This happens because the typing stub exposes a Protocol type (https://github.com/python/typeshed/blob/fb2c7b34e27232198b7b742bca93640c5b77c26f/stdlib/3/typing.pyi#L22), even though the actual _Protocol class is internal to the typing module (not in __all__).

So another example is that

from typing import *
class MyProtocol(Protocol):
    pass

passes mypy even though it will fail to run because Protocol is undefined.

From reading #452, this can be solved by renaming Protocol to _Protocol in the stub, and also in semantic analysis when typing.Protocol is mentioned. Should I open a PR?

An alternative solution might be importing Protocol from a separate stub, taking advantage of special rules for imports??

@ilevkivskyi
Copy link
Member Author

From reading #452, this can be solved by renaming Protocol to _Protocol in the stub, and also in semantic analysis when typing.Protocol is mentioned. Should I open a PR?

It also appears in several other places, so it will be hard to rename all of them. In addition, this is kind of intentional, as a first step of moving Protocol to typing. I think a better solution may be to just add a line from typing import Protocol as Protocol to typing_extensions stub.

@mortoray
Copy link

What is the correct workaround to this problem? I'm doing this now:

from typing import *
from typing_extensions import Protocol #type: ignore

@ilevkivskyi
Copy link
Member Author

Not using star imports is the best way. Also Protocol is in typing in Python 3.8, so you will not need the second line. Finally, there is a dirty trick:

from typing import *
if not TYPE_CHECKING:
    from typing_extensions import Protocol

@GPHemsley
Copy link

Is there a way to avoid this error when writing something like the follow?

# Protocol is only available in Python 3.8+.
try:
    from typing import Protocol
except ImportError:
    from typing_extensions import Protocol

@eblume
Copy link

eblume commented Dec 21, 2019

@GPHemsley I wrote that exact same snippet of code and landed on this page trying to fix the resulting typing error. I'm going to unstick myself by simply adding # type: ignore to each of those imports, and check back when my project can move to 3.8 properly.

@ethanhs
Copy link
Collaborator

ethanhs commented Dec 22, 2019

@GPHemsley @eblume does using sys.version_info checks work? Mypy is better able to reason about things if you use version checks.

@unmade
Copy link

unmade commented Jan 4, 2020

@ethanhs sys.version_info seems to works just fine. Thanks!

mcmtroffaes added a commit to mcmtroffaes/rite that referenced this issue Jan 18, 2021
mkhorton added a commit to materialsproject/pymatgen that referenced this issue Jun 8, 2021
@TonyLHansen
Copy link

As @eblume intimated, this seems to be forward compatible AND eliminates the error message:

try:
    from typing import Protocol
except ImportError:
    from typing_extensions import Protocol # type: ignore

I did not put the #type: ignore on the first import because that one SHOULD be compatible.

Hopefully someone will find this explicit example helpful.

@hauntsaninja
Copy link
Collaborator

For all the random people landing up on this issue:

if sys.version_info >= (3, 8):
    from typing import Protocol
else:
    from typing_extensions import Protocol

As for the original issue, closing as won't fix. This doesn't happen often, it's tricky to fix the lie in typeshed, the problem will go away on its own next year

@hauntsaninja hauntsaninja closed this as not planned Won't fix, can't repro, duplicate, stale Aug 3, 2022
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Projects
None yet
Development

No branches or pull requests

9 participants