Simplified reflect#resolve_signature
@@ -29,7 +29,7 @@ EMPTY: typing.Final[inspect.Parameter.empty] = inspect.Parameter.empty
"""A singleton that empty annotations will be set to in `resolve_signature`."""
-def resolve_signature(func: typing.Callable) -> inspect.Signature:
+def resolve_signature(func: typing.Callable[..., typing.Any]) -> inspect.Signature:
"""Get the `inspect.Signature` of `func` with resolved forward annotations.
Parameters
@@ -37,6 +37,11 @@ def resolve_signature(func: typing.Callable) -> inspect.Signature:
func : typing.Callable[[...], ...]
The function to get the resolved annotations from.
+ !!! warning
+ This will use `eval` to resolve string typehints and forward references.
+ This has a slight performance overhead, so attempt to cache this info
+ as much as possible.
+
Returns
-------
typing.Signature
@@ -44,29 +49,13 @@ def resolve_signature(func: typing.Callable) -> inspect.Signature:
resolved.
"""
signature = inspect.signature(func)
- resolved_type_hints = None
- parameters = []
- for key, value in signature.parameters.items():
- if isinstance(value.annotation, str):
- if resolved_type_hints is None:
- resolved_type_hints = typing.get_type_hints(func)
- value = value.replace(annotation=resolved_type_hints[key])
-
- if value is type(None):
- value = None
-
- parameters.append(value)
- signature = signature.replace(parameters=parameters)
-
- if isinstance(signature.return_annotation, str):
- if resolved_type_hints is None:
- return_annotation = typing.get_type_hints(func)["return"]
- else:
- return_annotation = resolved_type_hints["return"]
-
- if return_annotation is type(None):
- return_annotation = None
+ resolved_typehints = typing.get_type_hints(func)
+ return_annotation = resolved_typehints.pop("return") if "return" in resolved_typehints else EMPTY
+ params = []
- signature = signature.replace(return_annotation=return_annotation)
+ for name, param in signature.parameters.items():
+ if isinstance(param.annotation, str):
+ param = param.replace(annotation=resolved_typehints[name] if name in resolved_typehints else EMPTY)
+ params.append(param)
- return signature
+ return signature.replace(parameters=params, return_annotation=return_annotation)
