https://github.com/python/cpython/commit/347f53853faa4777e3e63a8a58a0d5e926bd3e54
commit: 347f53853faa4777e3e63a8a58a0d5e926bd3e54
branch: main
author: sobolevn <[email protected]>
committer: JelleZijlstra <[email protected]>
date: 2026-05-06T12:58:45Z
summary:
gh-149415: Replace `typing._LazyAnnotationLib` with `lazy import` (#149416)
files:
M Lib/typing.py
diff --git a/Lib/typing.py b/Lib/typing.py
index e7563a53878da5..5b1e223d59641e 100644
--- a/Lib/typing.py
+++ b/Lib/typing.py
@@ -28,6 +28,7 @@
import sys
import types
from types import GenericAlias
+lazy import annotationlib
from _typing import (
_idfunc,
@@ -163,15 +164,6 @@
'Unpack',
]
-class _LazyAnnotationLib:
- def __getattr__(self, attr):
- global _lazy_annotationlib
- import annotationlib
- _lazy_annotationlib = annotationlib
- return getattr(annotationlib, attr)
-
-_lazy_annotationlib = _LazyAnnotationLib()
-
def _type_convert(arg, module=None, *, allow_special_forms=False, owner=None):
"""For converting None to type(None), and strings to ForwardRef."""
@@ -255,7 +247,7 @@ def _type_repr(obj):
if isinstance(obj, tuple):
# Special case for `repr` of types with `ParamSpec`:
return '[' + ', '.join(_type_repr(t) for t in obj) + ']'
- return _lazy_annotationlib.type_repr(obj)
+ return annotationlib.type_repr(obj)
def _collect_type_parameters(
@@ -463,7 +455,7 @@ def _eval_type(t, globalns, localns, type_params, *,
recursive_guard=frozenset()
recursive_guard is used to prevent infinite recursion with a recursive
ForwardRef.
"""
- if isinstance(t, _lazy_annotationlib.ForwardRef):
+ if isinstance(t, annotationlib.ForwardRef):
# If the forward_ref has __forward_module__ set, evaluate() infers the
globals
# from the module, and it will probably pick better than the globals
we have here.
# We do this only for calls from get_type_hints() (which opts in
through the
@@ -1004,7 +996,7 @@ def _make_forward_ref(code, *, parent_fwdref=None,
**kwargs):
kwargs['module'] = parent_fwdref.__forward_module__
if parent_fwdref.__owner__ is not None:
kwargs['owner'] = parent_fwdref.__owner__
- forward_ref = _lazy_annotationlib.ForwardRef(code, **kwargs)
+ forward_ref = annotationlib.ForwardRef(code, **kwargs)
# For compatibility, eagerly compile the forwardref's code.
forward_ref.__forward_code__
return forward_ref
@@ -1039,18 +1031,18 @@ def evaluate_forward_ref(
VALUE.
"""
- if format == _lazy_annotationlib.Format.STRING:
+ if format == annotationlib.Format.STRING:
return forward_ref.__forward_arg__
if forward_ref.__forward_arg__ in _recursive_guard:
return forward_ref
if format is None:
- format = _lazy_annotationlib.Format.VALUE
+ format = annotationlib.Format.VALUE
value = forward_ref.evaluate(globals=globals, locals=locals,
type_params=type_params, owner=owner,
format=format)
- if (isinstance(value, _lazy_annotationlib.ForwardRef)
- and format == _lazy_annotationlib.Format.FORWARDREF):
+ if (isinstance(value, annotationlib.ForwardRef)
+ and format == annotationlib.Format.FORWARDREF):
return value
if isinstance(value, str):
@@ -1891,8 +1883,8 @@ def _get_protocol_attrs(cls):
annotations = base.__annotations__
except Exception:
# Only go through annotationlib to handle deferred annotations if
we need to
- annotations = _lazy_annotationlib.get_annotations(
- base, format=_lazy_annotationlib.Format.FORWARDREF
+ annotations = annotationlib.get_annotations(
+ base, format=annotationlib.Format.FORWARDREF
)
for attr in (*base.__dict__, *annotations):
if not attr.startswith('_abc_') and attr not in
EXCLUDED_ATTRIBUTES:
@@ -2140,8 +2132,8 @@ def _proto_hook(cls, other):
try:
annos = base.__annotations__
except Exception:
- annos = _lazy_annotationlib.get_annotations(
- base, format=_lazy_annotationlib.Format.FORWARDREF
+ annos = annotationlib.get_annotations(
+ base, format=annotationlib.Format.FORWARDREF
)
if attr in annos:
break
@@ -2428,14 +2420,14 @@ def get_type_hints(obj, globalns=None, localns=None,
include_extras=False,
"""
if getattr(obj, '__no_type_check__', None):
return {}
- Format = _lazy_annotationlib.Format
+ Format = annotationlib.Format
if format is None:
format = Format.VALUE
# Classes require a special treatment.
if isinstance(obj, type):
hints = {}
for base in reversed(obj.__mro__):
- ann = _lazy_annotationlib.get_annotations(base, format=format)
+ ann = annotationlib.get_annotations(base, format=format)
if format == Format.STRING:
hints.update(ann)
continue
@@ -2468,7 +2460,7 @@ def get_type_hints(obj, globalns=None, localns=None,
include_extras=False,
else:
return {k: _strip_annotations(t) for k, t in hints.items()}
- hints = _lazy_annotationlib.get_annotations(obj, format=format)
+ hints = annotationlib.get_annotations(obj, format=format)
if (
not hints
and not isinstance(obj, types.ModuleType)
@@ -3020,10 +3012,10 @@ def _make_eager_annotate(types):
for key, val in types.items()}
def annotate(format):
match format:
- case _lazy_annotationlib.Format.VALUE |
_lazy_annotationlib.Format.FORWARDREF:
+ case annotationlib.Format.VALUE | annotationlib.Format.FORWARDREF:
return checked_types
- case _lazy_annotationlib.Format.STRING:
- return _lazy_annotationlib.annotations_to_string(types)
+ case annotationlib.Format.STRING:
+ return annotationlib.annotations_to_string(types)
case _:
raise NotImplementedError(format)
return annotate
@@ -3053,9 +3045,9 @@ def __new__(cls, typename, bases, ns):
types = ns["__annotations__"]
field_names = list(types)
annotate = _make_eager_annotate(types)
- elif (original_annotate :=
_lazy_annotationlib.get_annotate_from_class_namespace(ns)) is not None:
- types = _lazy_annotationlib.call_annotate_function(
- original_annotate, _lazy_annotationlib.Format.FORWARDREF)
+ elif (original_annotate :=
annotationlib.get_annotate_from_class_namespace(ns)) is not None:
+ types = annotationlib.call_annotate_function(
+ original_annotate, annotationlib.Format.FORWARDREF)
field_names = list(types)
# For backward compatibility, type-check all the types at creation
time
@@ -3063,9 +3055,9 @@ def __new__(cls, typename, bases, ns):
_type_check(typ, "field annotation must be a type")
def annotate(format):
- annos = _lazy_annotationlib.call_annotate_function(
+ annos = annotationlib.call_annotate_function(
original_annotate, format)
- if format != _lazy_annotationlib.Format.STRING:
+ if format != annotationlib.Format.STRING:
return {key: _type_check(val, f"field {key} annotation
must be a type")
for key, val in annos.items()}
return annos
@@ -3207,9 +3199,9 @@ def __new__(cls, name, bases, ns, total=True, closed=None,
if ns_annotations is not None:
own_annotate = None
own_annotations = ns_annotations
- elif (own_annotate :=
_lazy_annotationlib.get_annotate_from_class_namespace(ns)) is not None:
- own_annotations = _lazy_annotationlib.call_annotate_function(
- own_annotate, _lazy_annotationlib.Format.FORWARDREF,
owner=tp_dict
+ elif (own_annotate :=
annotationlib.get_annotate_from_class_namespace(ns)) is not None:
+ own_annotations = annotationlib.call_annotate_function(
+ own_annotate, annotationlib.Format.FORWARDREF, owner=tp_dict
)
else:
own_annotate = None
@@ -3276,20 +3268,20 @@ def __annotate__(format):
base_annotate = base.__annotate__
if base_annotate is None:
continue
- base_annos = _lazy_annotationlib.call_annotate_function(
+ base_annos = annotationlib.call_annotate_function(
base_annotate, format, owner=base)
annos.update(base_annos)
if own_annotate is not None:
- own = _lazy_annotationlib.call_annotate_function(
+ own = annotationlib.call_annotate_function(
own_annotate, format, owner=tp_dict)
- if format != _lazy_annotationlib.Format.STRING:
+ if format != annotationlib.Format.STRING:
own = {
n: _type_check(tp, msg, module=tp_dict.__module__)
for n, tp in own.items()
}
- elif format == _lazy_annotationlib.Format.STRING:
- own =
_lazy_annotationlib.annotations_to_string(own_annotations)
- elif format in (_lazy_annotationlib.Format.FORWARDREF,
_lazy_annotationlib.Format.VALUE):
+ elif format == annotationlib.Format.STRING:
+ own = annotationlib.annotations_to_string(own_annotations)
+ elif format in (annotationlib.Format.FORWARDREF,
annotationlib.Format.VALUE):
own = own_checked_annotations
else:
raise NotImplementedError(format)
@@ -3886,7 +3878,7 @@ def __getattr__(attr):
are only created on-demand here.
"""
if attr == "ForwardRef":
- obj = _lazy_annotationlib.ForwardRef
+ obj = annotationlib.ForwardRef
elif attr in {"Pattern", "Match"}:
import re
obj = _alias(getattr(re, attr), 1)
_______________________________________________
Python-checkins mailing list -- [email protected]
To unsubscribe send an email to [email protected]
https://mail.python.org/mailman3//lists/python-checkins.python.org
Member address: [email protected]