How to seamlessly support typing.Protocol
on Python versions older and newer than 3.8. At the same time.
typing.Protocol
has been added in Python 3.8. Therefore if want to use structural subtyping using it on both Python versions older and newer than 3.8 within the same code base, you need to get it from typing-extensions pre-3.8, and from typing
on 3.8 and later.1
The most obvious – and arguably most Pythonic – way would be:
try:
from typing import Protocol
except ImportError:
from typing_extensions import Protocol
However, mypy will fail with a rather inscrutable error:
error: Incompatible import of "Protocol" (imported name has type "typing_extensions._SpecialForm", local name has type "typing._SpecialForm")
The way to guard imports from typing
that mypy understands is to check the Python version:
import sys
if sys.version_info >= (3, 8):
from typing import Protocol
else:
from typing_extensions import Protocol
Therefore, the brand-new ParamSpec
works like this:
import sys
if sys.version_info >= (3, 10):
from typing import ParamSpec
else:
from typing_extensions import ParamSpec
If you want to prevent having an unnecessary dependency, that is. ↩︎