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.ForwardRefs 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
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