|
31 | 31 | from IPython.utils.decorators import undoc |
32 | 32 |
|
33 | 33 |
|
34 | | -from typing import Self, LiteralString |
| 34 | +from typing import Self, LiteralString, get_type_hints |
35 | 35 |
|
36 | 36 | if sys.version_info < (3, 12): |
37 | 37 | from typing_extensions import TypeAliasType |
@@ -1036,6 +1036,22 @@ def dummy_function(*args, **kwargs): |
1036 | 1036 | value = eval_node(node.value, context) |
1037 | 1037 | if policy.can_get_attr(value, node.attr): |
1038 | 1038 | return getattr(value, node.attr) |
| 1039 | + try: |
| 1040 | + cls = ( |
| 1041 | + value if isinstance(value, type) else getattr(value, "__class__", None) |
| 1042 | + ) |
| 1043 | + if cls is not None: |
| 1044 | + resolved_hints = get_type_hints( |
| 1045 | + cls, |
| 1046 | + globalns=(context.globals or {}), |
| 1047 | + localns=(context.locals or {}), |
| 1048 | + ) |
| 1049 | + if node.attr in resolved_hints: |
| 1050 | + annotated = resolved_hints[node.attr] |
| 1051 | + return _resolve_annotation(annotated, context) |
| 1052 | + except Exception: |
| 1053 | + # Fall through to the guard rejection |
| 1054 | + pass |
1039 | 1055 | raise GuardRejection( |
1040 | 1056 | "Attribute access (`__getattr__`) for", |
1041 | 1057 | type(value), # not joined to avoid calling `repr` |
|
0 commit comments