When this pattern is checked in py2 mode (or really any pre-3.5 version)
try:
from inspect import isawaitable # py35+
except ImportError:
from backports_abc import isawaitable
it raises an error tornado/gen.py:118: error: Module has no attribute 'isawaitable'. Instead, mypy should recognize that this is within a try/except block that catches the ImportError and choose the alternate path instead.
This falls under the umbrella of #1297 but I couldn't find an exact match for this issue.
Yup. (Can you shut it up using # type: ignore?)
Yes, # type: ignore works here (as long as I ignore both branches)
This is also the case with attribute access in try/except block, not only imports, e.g.:
try:
foo = sys._MEIPASS
except AttributeError:
foo = '.'
causes mypy to fail with error: Module has no attribute "_MEIPASS", even though it looks like a reasonable approach. Ignoring with # type: ignore comment silences it.
We encountered this in Twine with importlib.metadata.metadata vs importlib_metadata.metadata, but only as of mypy 0.750. There's a fix pending in https://github.com/pypa/twine/pull/551 (which also covers an instance of #1153).
I made a repository to reproduce the errors and try out some fixes: https://github.com/bhrutledge/mypy-importlib-metadata. That's currently passing, but the commit history has more details.
The change is likely due to a change in typeshed (adding importlib_metadata I presume). I would recommend using if sys.version_info... checks to tell mypy what Python version is being used in each case so it doesn't misunderstand the code.
@ethanhs Thanks! I didn't know that mypy would use sys.version_info as a hint.
I would recommend using if
sys.version_info...
This approach is less desirable than using the try/except pattern. In particular, one must (a) import sys, (b) parse/compare sys.version_info, and (c) encode availability of module features to their various versions (which may not be a simple >= comparison).
Is the implication of this recommendation that try/except for imports is deprecated/discouraged, or is this recommendation just a temporary workaround for an acknowledged problem?
A workaround is needed because of a missing mypy feature. I don't know when the feature might be implemented, though.
Perhaps a naive question: If mypy recognized a "try/except ImportError", could it set the type of the module object to something like Union[Module1, Module2] (or Optional[Module] in case the except does mod = None)?
@The-Compiler sadly that probably wouldn't work, as you want to make sure the same module is used throughout. We would probably want something closer to a type variable I believe.
Most helpful comment
Perhaps a naive question: If mypy recognized a "try/except ImportError", could it set the type of the module object to something like
Union[Module1, Module2](orOptional[Module]in case theexceptdoesmod = None)?