Repository navigation
Lazy imports and resolving type hints #156924
Copy link
Copy link
Closed
Labels
3.15bugs and security fixesbugs and security fixestopic-lazy-importstopic-typingtype-featureA feature request or enhancementA feature request or enhancement
Description
Feature or enhancement
Proposal:
annotationlib implements an optimization to resolve forward references in ForwardRef.evaluate(), by doing a simple lookup in the namespace:
Lines 193 to 210 in 112560e
| if arg.isidentifier() and not keyword.iskeyword(arg): | |
| if arg in locals: | |
| return locals[arg] | |
| elif arg in globals: | |
| return globals[arg] | |
| elif hasattr(builtins, arg): | |
| return getattr(builtins, arg) | |
| elif is_forwardref_format: | |
| return self | |
| else: | |
| raise NameError(_NAME_ERROR_MSG.format(name=arg), name=arg) | |
| else: | |
| code = self.__forward_code__ | |
| try: | |
| return eval(code, globals=globals, locals=locals) | |
| except Exception: | |
| if not is_forwardref_format: | |
| raise |
This gives slightly inconsistent results with lazy imports that fail to resolve:
# lazy_mod.py
Alias = list
raise Exception()from annotationlib import Format, get_annotations
lazy from lazy_mod import Alias
class A:
a: Alias
class B:
a: Alias[int]
get_annotations(A, format=Format.FORWARDREF)
#> {'a': <lazy_import 'failing_mod.Alias'>}
get_annotations(B, format=Format.FORWARDREF)
#> {'a': ForwardRef('Alias[int]', is_class=True, owner=<class '__main__.B'>)}I'm wondering if for A, it should instead wrap a's annotation in a ForwardRef, so that users can then call evaluate() on it (e.g. with Format.VALUE) so that the exception from lazy_mod gets raised accordingly. Alternatively, the lazy import instance could be kept as is, but it would be great to document the resolve() method on types.LazyImportType.
Has this already been discussed elsewhere?
This is a minor feature, which does not need previous discussion elsewhere
Links to previous discussion of this feature:
No response
Linked PRs
Reactions are currently unavailable
Metadata
Metadata
Assignees
Labels
3.15bugs and security fixesbugs and security fixestopic-lazy-importstopic-typingtype-featureA feature request or enhancementA feature request or enhancement
Activity
JelleZijlstra commentedon Sep 4, 2026
Good catch, I think we should solve this before 3.15 final. My preferred solution would be to wrap LazyImportType instances in a ForwardRef (as you suggest). That way, we'll need some special casing inside annotationlib, but LazyImportType objects won't escape to callers.
94mbi7 commentedon Sep 7, 2026
can i work on it if its still open
johnslavik commentedon Sep 7, 2026
I'm surprised it wasn't documented.
gh-156924: Try reifying lazy imports in `ForwarRef.evaluate()` (#156940)
[3.15] gh-156924: Try reifying lazy imports in `ForwarRef.evaluate()` (…
Merge branch 'main' into tachyon-native-callable
pythongh-156924: Try reifying lazy imports in `ForwarRef.evaluate()` (p…
pythongh-156924: Try reifying lazy imports in `ForwarRef.evaluate()` (p…
[3.15] pythongh-156924: Try reifying lazy imports in `ForwarRef.evalu…