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")
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 https://github.com/python/mypy/issues/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??
From reading #452, this can be solved by renaming
Protocolto_Protocolin the stub, and also in semantic analysis whentyping.Protocolis 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.
What is the correct workaround to this problem? I'm doing this now:
from typing import *
from typing_extensions import Protocol #type: ignore
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
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
@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.
@GPHemsley @eblume does using sys.version_info checks work? Mypy is better able to reason about things if you use version checks.
@ethanhs sys.version_info seems to works just fine. Thanks!
Most helpful comment
Is there a way to avoid this error when writing something like the follow?