Mypy: `OrderedDict` fails disallow_any_generics, but `OrderedDict[Any, Any]` doesn't run

Created on 20 Sep 2019  路  9Comments  路  Source: python/mypy

I've been trying to introduce disallow_any_generics = true to an already extensively typed code base of ~48kSLOC, and the only remaining issue is typing OrderedDicts.

Actual behaviour

Given this configuration:

[mypy]
check_untyped_defs = true
disallow_any_generics = true
disallow_untyped_defs = true
ignore_missing_imports = true
no_implicit_optional = true
warn_redundant_casts = true
warn_return_any = true
warn_unused_ignores = true

Code with implicit Any:

from collections import OrderedDict
from typing import Any

def name(value: OrderedDict) -> None:
    pass

This fails validation because of disallow_any_generics = true:

$ mypy example.py
example.py:4: error: Missing type parameters for generic type

Code with typed OrderedDict:

from collections import OrderedDict
from typing import Any

def name(value: OrderedDict[Any, Any]) -> None:
    pass

This passes validation, but doesn't run:

$ python example.py 
Traceback (most recent call last):
  File "example.py", line 4, in <module>
    def name(value: OrderedDict[Any, Any]) -> None:
TypeError: 'type' object is not subscriptable

Versions:

$ python --version
Python 3.6.8
$ mypy --version
mypy 0.720

(Also failed on mypy 0.711.)

Expected behaviour

I'd expect either the first snippet to be valid or the second snippet to run. As it is I'm stuck for how to proceed.

good-first-issue priority-1-normal topic-usability

Most helpful comment

You can use string literal escapes, such as value: 'OrderedDict[Any, Any]'. Another option is from __future__ import annotations (introduced in Python 3.7).

All 9 comments

You can use string literal escapes, such as value: 'OrderedDict[Any, Any]'. Another option is from __future__ import annotations (introduced in Python 3.7).

@JukkaL Is there no way to do this without quoting the type? Because even if I if TYPE_CHECKING: from collections import OrderedDict that triggers an issue in flake8:

F401 'collections.OrderedDict' imported but unused

You can use from __future__ import annotations in 3.7+.

do you want typing.OrderedDict and not collections.OrderedDict for that annotation?

I was going to say that too but it turns out there is no typing.OrderedDict.

there is in 3.7 iirc

Oh, you're right, it is in 3.7 (https://github.com/python/cpython/blob/3.7/Lib/typing.py) but not in the typing repo (https://github.com/python/typing/blob/master/src/typing.py) where I checked first. I filed python/typing#679 to add it.

If mypy sees that OrderedDict (or another class that doesn't support indexing at runtime) is missing required generic type args, we could give a better error message that suggests using string literal escaping.

Relevant docs https://mypy.readthedocs.io/en/latest/common_issues.html#using-classes-that-are-generic-in-stubs-but-not-at-runtime

Was this page helpful?
0 / 5 - 0 ratings