I would like to know if there is an existing implementation that converts the string representation of a type hint (e.g. from a docstring) back to the type (or typing) object. Thereby arbitrary deep nested types should also be supported (see third example).
import typing import List, Optional, Union
converter_function("List[str]") == List[str]
converter_function("int") == int
converter_function("Optional[List[Union[str, float]]]") == Optional[List[Union[str,float]]]
converter_function("foobar") # Exception / None
One option would be to simply use eval, but I would like to avoid that at all costs :D
Edit As background on why I want to do this: I want to write a script that checks if a docstring matches 100% to a function, all types are correct and so on.
The closest thing I can find (except for eval
of course) is typing.get_type_hints
. If your functions are properly type annotated, then typing.get_type_hints
can resolve the annotations. It works for string annotations, arbitrarily nested types, and generic types; basically any valid annotations. For example:
from typing import List, Optional, Union, get_type_hints
def my_func(a: "List[str]", b: "int") -> "Optional[List[Union[str, float]]]":
pass
print(get_type_hints(my_func))
you'd get
{'a': typing.List[str],
'b': <class 'int'>,
'return': typing.Optional[typing.List[typing.Union[str, float]]]}
Internally, get_type_hints
converts the strings into typing.ForwardRef
s and then evaluate them. These are private APIs so they might not be stable across Python versions, but if you only have the annotation strings but not a function, you might try this out:
>>> from typing import ForwardRef, _eval_type
>>> _eval_type(ForwardRef("Optional[List[Union[str, float]]]"), globals(), globals())
typing.Optional[typing.List[typing.Union[str, float]]]
but at this point, you might be better off with eval
:P