I'm trying to implement type annotations in a current project, and am receiving errors from mypy that I don't understand.
I'm using Python 2.7.11, and newly installed mypy in my base virtualenv. The following program runs fine:
from __future__ import print_function
from types import StringTypes
from typing import List, Union, Callable
def f(value): # type: (StringTypes) -> StringTypes
return value
if __name__ == '__main__':
print("{}".format(f('some text')))
print("{}".format(f(u'some unicode text')))
But running mypy --py2 -s mypy_issue.py
returns the following:
mypy_issue.py: note: In function "f":
mypy_issue.py:8: error: Invalid type "types.StringTypes"
The above types appear to be in Typeshed... the mypy documentation says "Mypy incorporates the typeshed project, which contains library stubs for the Python builtins and the standard library. "... Not sure what "incorporates" means - do I need to do something to "activate", or provide a path to, Typeshed? Do I need to download and install(?) Typeshed locally?
The problem is that types.StringTypes
is defined to be a sequence of types -- the formal type signature on Typeshed is:
StringTypes = (StringType, UnicodeType)
This corresponds to the official documentation, which states that the StringTypes
constant is "a sequence containing StringType
and UnicodeType
"...
So then, this explains the error you're getting -- StringTypes
isn't an actual class (it's probably a tuple) and so mypy doesn't recognize it as a valid type.
There are several possible fixes for this.
The first way would probably be to use typing.AnyStr
which is defined as AnyStr = TypeVar('AnyStr', bytes, unicode)
. Although AnyStr
is included within the typing
module, it is, unfortunately, somewhat poorly documented as of now -- you can find more detailed information about what it does within the mypy docs.
A slightly less cleaner way of expression this would be to do:
from types import StringType, UnicodeType
from typing import Union
MyStringTypes = Union[StringType, UnicodeType]
def f(value):
# type: (MyStringTypes) -> MyStringTypes
return value
This also works, but is less desirable because the return type is no longer obligated to be the same thing as the input type which is usually not what you want when working with different kinds of strings.
And as for typeshed -- it's bundled by default when you install mypy. In an ideal world, you shouldn't need to worry about typeshed at all, but since mypy is in beta and so typeshed is being frequently updated to account for missing modules or incorrect type annotations, it might be worth installing mypy directly from the Github repo and installing typeshed locally if you find yourself frequently running into bugs with typeshed.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With