mkrieger1
mkrieger1

Reputation: 23250

How can I make mypy tell me I am using features that are unsupported in older Python versions?

As an example, executing this code with Python versions older than 3.9 will raise an exception:

from concurrent.futures import Future

f: Future[int]

TypeError: 'type' object is not subscriptable

But mypy will not complain (I'm using mypy 0.910):

Success: no issues found in 1 source file

Explicitly specifiying the Python version that mypy will use (e.g. --python-version=3.8) does not change this.

Numerous times I have fallen into the trap of writing code that uses features from newer Python versions, assuming that mypy will tell me if I made any errors, to then discover these errors only later at runtime.

How can I tell mypy to not assume features from certain Python versions (which I don't even have installed) to exist?

Upvotes: 0

Views: 635

Answers (2)

mkrieger1
mkrieger1

Reputation: 23250

Mypy seems to already work as expected with built-in types, but fails in other cases, like Future above, or queue.Queue.

After reading Mypy docs – Annotation issues at runtime and Issue #7907 – Implement PEP 585 I'm not sure if this is a bug or intentional. Maybe the assumption is that the runtime errors can be avoided by using from __future__ import annotations.

After reading this answer it might be that this is a flaw in the Python standard library, or rather its typeshed, which promises more than is actually implemented, and mypy can't do anything about it.

Works:

# example1.py
x: list[int]
$ mypy --python-version=3.8 example1.py 
example1.py:1: error: "list" is not subscriptable, use "typing.List" instead

$ mypy --python-version=3.9 example1.py 
Success: no issues found in 1 source file

Works:

# example2.py
d: dict[str, int]
$ mypy --python-version=3.8 example2.py 
example2.py:1: error: "dict" is not subscriptable, use "typing.Dict" instead

$ mypy --python-version=3.9 example2.py 
Success: no issues found in 1 source file

Fails:

# example3.py
from queue import Queue
q: Queue[int]
$ mypy --python-version=3.8 example3.py 
Success: no issues found in 1 source file

$ python3.8 example3.py
Traceback (most recent call last):
  File "example3.py", line 2, in <module>
    q: Queue[int]
TypeError: 'type' object is not subscriptable

Workaround:

# example4.py
from __future__ import annotations
from queue import Queue
q: Queue[int]
print('ok')
$ mypy --python-version=3.8 example4.py 
Success: no issues found in 1 source file

$ python3.8 example4.py
ok

Upvotes: 0

joel
joel

Reputation: 7877

I'll take a guess: by running it with older mypy versions.

You could set up CI to run with every mypy version you require, and locally use virtual envs for each version

Upvotes: 1

Related Questions