You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
Mark Shannon came up with an example I don't know how to handle. Support we were to stubify collections.UserDict. This is a container class, its implementation inherits from collections.abc.MutableMapping. Let's assume we don't want to modify the implementation at all. In the stub file (collections.pyi) we go like this:
from typing import MutableMapping
class UserDict(MutableMapping[KT, VT]):
...
Now let's say we have some application code that uses UserDict and we want to annotate this:
from collections.abc import UserDict
def something(x: UserDict[int, str]):
...
Unfortunately, this code doesn't actually work, because the implementation UserDict class isn't generic (since collections.abc.MutableMapping isn't). But to a type checker this is what you're supposed to write -- the typechecker sees the UserDict from the stub, which is generic.
I'm stumped. Mark's suggestion is to have a dedicated function in the typing module (he calls it Type()) that could be used, e.g.:
from typing import Type
from collections.abc import UserDict
def something(x:Type(UserDict)[int, str]):
...
Or perhaps Type() should take an additional parameter to indicate how many type parameters it takes, e.g. Type(UserDict, 2).
I've come across this same issue. This is actually a common thing and applies to list vs. List as well. Note that this is a related to the representation of types such as typing.Pattern[AnyStr] but a bit different.
Currently you can use string literal types to encode this information, though this is not yet enforced by mypy (mypy accepts an ordinary type expression UserDict[...], but it will fail at runtime):
We could tag some generic types in stubs as requiring string literal escaping if using <type>[...].
Another potential alternative is to create a wrapper type such as typing.collections.abc.UserDict that supports indexing but also supports everything that UserDict does. Not sure if that's even possible to implement.
A final option would be to have two UserDict classes, one for use in a type annotation and the other for use in other contexts (e.g., constructing an instance), a bit like Mark's suggestion (and like List vs list). For example:
from collections.abc import UserDict
from typing.collections.abc import UserDictType
def f() -> UserDictType[int, str]:
return UserDict(...)
I see this has been closed for some time and that we can use string literals to annotate function parameters, but what about for the key and value type of UserDict subclasses?
Activity
JukkaL commentedon Mar 20, 2015
I've come across this same issue. This is actually a common thing and applies to
listvs.Listas well. Note that this is a related to the representation of types such astyping.Pattern[AnyStr]but a bit different.Currently you can use string literal types to encode this information, though this is not yet enforced by mypy (mypy accepts an ordinary type expression
UserDict[...], but it will fail at runtime):We could tag some generic types in stubs as requiring string literal escaping if using
<type>[...].Another potential alternative is to create a wrapper type such as
typing.collections.abc.UserDictthat supports indexing but also supports everything thatUserDictdoes. Not sure if that's even possible to implement.A final option would be to have two
UserDictclasses, one for use in a type annotation and the other for use in other contexts (e.g., constructing an instance), a bit like Mark's suggestion (and likeListvslist). For example:gvanrossum commentedon Mar 23, 2015
I like the solution of using string literals when this comes up.
JukkaL commentedon Apr 14, 2015
Me, Mark and Andrey agreed that using string literals is the way to go. Stubs can be an exception (no need to ever use string literals in stubs).
e-kosten commentedon Mar 24, 2021
I see this has been closed for some time and that we can use string literals to annotate function parameters, but what about for the key and value type of UserDict subclasses?
For example, suppose we have the simple class
If we try to do
MyPy correctly warns that
However, at runtime, this fails and we instead need to define the class as
in which case MyPy fails to identify any problems with
ssbarnea commentedon Jun 28, 2021
What is the correct way subclass UserDict and keep mypy happy? At this moment
gives:
JelleZijlstra commentedon Jun 28, 2021
You need to use
if TYPE_CHECKING, unfortunately. Something like: