Skip to content

Commit

Permalink
add get_type_annotations
Browse files Browse the repository at this point in the history
  • Loading branch information
Aran-Fey committed Mar 10, 2024
1 parent 0ddc5a5 commit 281ddec
Show file tree
Hide file tree
Showing 4 changed files with 41 additions and 9 deletions.
2 changes: 1 addition & 1 deletion introspection/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@
New and improved introspection functions
"""

__version__ = "1.7.10"
__version__ = "1.7.11"

from .parameter import *
from .signature_ import *
Expand Down
1 change: 1 addition & 0 deletions introspection/typing/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -4,4 +4,5 @@
from .subtype_check import *
from .type_compat import *
from .misc import *
from .misc2 import *
from .i_hate_circular_imports import *
28 changes: 28 additions & 0 deletions introspection/typing/misc2.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
from typing import Dict, cast

from .type_info import TypeInfo
from ..misc import static_mro, static_vars
from ..types import TypeAnnotation


__all__ = ["get_type_annotations"]


def get_type_annotations(cls: type) -> Dict[str, TypeInfo]:
"""
Similar to `typing.get_type_hints`, but returns the annotations as `TypeInfo` objects.
"""
result: Dict[str, TypeInfo] = {}

for class_ in static_mro(cls):
cls_vars = static_vars(class_)
try:
annotations = cast(Dict[str, TypeAnnotation], cls_vars["__annotations__"])
except KeyError:
continue

for attr_name, annotation in annotations.items():
if attr_name not in result:
result[attr_name] = TypeInfo(annotation)

return result
19 changes: 11 additions & 8 deletions introspection/typing/type_info.py
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@
get_generic_base_class,
get_type_parameters,
)
from .misc import annotation_to_string
from .type_compat import to_python
from ..errors import NotAGeneric
from ..types import Type_, TypeAnnotation, ForwardRefContext, TypeParameter
Expand All @@ -27,25 +28,29 @@ def __init__(
forward_ref_context: ForwardRefContext = None,
treat_name_errors_as_imports: bool = False,
):
self.raw = type_

resolved_type: Type_ = resolve_at_least_1_level_of_forward_refs(
type_, forward_ref_context, treat_name_errors_as_imports
)

self.annotations = []
annotations: typing.List[object] = []

args = None
while is_parameterized_generic(resolved_type):
args = get_type_arguments(resolved_type)
resolved_type = get_generic_base_class(resolved_type)

if resolved_type is typing_extensions.Annotated:
self.annotations += args[1:]
annotations += args[1:]
resolved_type = resolve_at_least_1_level_of_forward_refs(
args[0], # type: ignore
forward_ref_context,
treat_name_errors_as_imports,
)
args = None

self.annotations = tuple(annotations)
self.type: Type_ = to_python(resolved_type, strict=False)
self._arguments = args
self._context = forward_ref_context
Expand All @@ -57,12 +62,6 @@ def parameters(self) -> typing.Optional[typing.Tuple[TypeParameter, ...]]:
except NotAGeneric:
return None

# @cached_property
# def arguments(self) -> typing.Optional[typing.Tuple[object, ...]]:
# if self._arguments is None:
# return None

# return tuple(Annotation(arg, context=self._context) for arg in self._arguments)
@property
def arguments(self) -> typing.Optional[typing.Tuple[object, ...]]:
return self._arguments
Expand All @@ -74,3 +73,7 @@ def is_generic(self) -> bool:
@property
def is_fully_parameterized_generic(self) -> bool:
return self.parameters == ()

def __repr__(self) -> str:
cls_name = type(self).__qualname__
return f"{cls_name}({self.raw})"

0 comments on commit 281ddec

Please sign in to comment.