19
19
"""
20
20
21
21
from abc import abstractmethod , ABCMeta
22
- import annotationlib
23
- from annotationlib import ForwardRef
24
22
import collections
25
23
from collections import defaultdict
26
24
import collections .abc
163
161
'Unpack' ,
164
162
]
165
163
164
+ class _LazyAnnotationLib :
165
+ def __getattr__ (self , attr ):
166
+ global _lazy_annotationlib
167
+ import annotationlib
168
+ _lazy_annotationlib = annotationlib
169
+ return getattr (annotationlib , attr )
170
+
171
+ _lazy_annotationlib = _LazyAnnotationLib ()
172
+
166
173
167
174
def _type_convert (arg , module = None , * , allow_special_forms = False ):
168
175
"""For converting None to type(None), and strings to ForwardRef."""
@@ -246,7 +253,7 @@ def _type_repr(obj):
246
253
if isinstance (obj , tuple ):
247
254
# Special case for `repr` of types with `ParamSpec`:
248
255
return '[' + ', ' .join (_type_repr (t ) for t in obj ) + ']'
249
- return annotationlib .value_to_string (obj )
256
+ return _lazy_annotationlib .value_to_string (obj )
250
257
251
258
252
259
def _collect_type_parameters (args , * , enforce_default_ordering : bool = True ):
@@ -423,7 +430,7 @@ def __repr__(self):
423
430
424
431
425
432
def _eval_type (t , globalns , localns , type_params = _sentinel , * , recursive_guard = frozenset (),
426
- format = annotationlib . Format . VALUE , owner = None ):
433
+ format = None , owner = None ):
427
434
"""Evaluate all forward references in the given type t.
428
435
429
436
For use of globalns and localns see the docstring for get_type_hints().
@@ -433,7 +440,7 @@ def _eval_type(t, globalns, localns, type_params=_sentinel, *, recursive_guard=f
433
440
if type_params is _sentinel :
434
441
_deprecation_warning_for_no_type_params_passed ("typing._eval_type" )
435
442
type_params = ()
436
- if isinstance (t , ForwardRef ):
443
+ if isinstance (t , _lazy_annotationlib . ForwardRef ):
437
444
# If the forward_ref has __forward_module__ set, evaluate() infers the globals
438
445
# from the module, and it will probably pick better than the globals we have here.
439
446
if t .__forward_module__ is not None :
@@ -930,7 +937,7 @@ def run(arg: Child | Unrelated):
930
937
931
938
932
939
def _make_forward_ref (code , ** kwargs ):
933
- forward_ref = ForwardRef (code , ** kwargs )
940
+ forward_ref = _lazy_annotationlib . ForwardRef (code , ** kwargs )
934
941
# For compatibility, eagerly compile the forwardref's code.
935
942
forward_ref .__forward_code__
936
943
return forward_ref
@@ -943,7 +950,7 @@ def evaluate_forward_ref(
943
950
globals = None ,
944
951
locals = None ,
945
952
type_params = None ,
946
- format = annotationlib . Format . VALUE ,
953
+ format = None ,
947
954
_recursive_guard = frozenset (),
948
955
):
949
956
"""Evaluate a forward reference as a type hint.
@@ -965,10 +972,11 @@ def evaluate_forward_ref(
965
972
evaluating the forward reference. This parameter should be provided (though
966
973
it may be an empty tuple) if *owner* is not given and the forward reference
967
974
does not already have an owner set. *format* specifies the format of the
968
- annotation and is a member of the annotationlib.Format enum.
975
+ annotation and is a member of the annotationlib.Format enum, defaulting to
976
+ VALUE.
969
977
970
978
"""
971
- if format == annotationlib .Format .STRING :
979
+ if format == _lazy_annotationlib .Format .STRING :
972
980
return forward_ref .__forward_arg__
973
981
if forward_ref .__forward_arg__ in _recursive_guard :
974
982
return forward_ref
@@ -977,7 +985,7 @@ def evaluate_forward_ref(
977
985
value = forward_ref .evaluate (globals = globals , locals = locals ,
978
986
type_params = type_params , owner = owner )
979
987
except NameError :
980
- if format == annotationlib .Format .FORWARDREF :
988
+ if format == _lazy_annotationlib .Format .FORWARDREF :
981
989
return forward_ref
982
990
else :
983
991
raise
@@ -2257,7 +2265,7 @@ def greet(name: str) -> None:
2257
2265
2258
2266
2259
2267
def get_type_hints (obj , globalns = None , localns = None , include_extras = False ,
2260
- * , format = annotationlib . Format . VALUE ):
2268
+ * , format = None ):
2261
2269
"""Return type hints for an object.
2262
2270
2263
2271
This is often the same as obj.__annotations__, but it handles
@@ -2290,12 +2298,15 @@ def get_type_hints(obj, globalns=None, localns=None, include_extras=False,
2290
2298
"""
2291
2299
if getattr (obj , '__no_type_check__' , None ):
2292
2300
return {}
2301
+ Format = _lazy_annotationlib .Format
2302
+ if format is None :
2303
+ format = Format .VALUE
2293
2304
# Classes require a special treatment.
2294
2305
if isinstance (obj , type ):
2295
2306
hints = {}
2296
2307
for base in reversed (obj .__mro__ ):
2297
- ann = annotationlib .get_annotations (base , format = format )
2298
- if format == annotationlib . Format .STRING :
2308
+ ann = _lazy_annotationlib .get_annotations (base , format = format )
2309
+ if format == Format .STRING :
2299
2310
hints .update (ann )
2300
2311
continue
2301
2312
if globalns is None :
@@ -2319,12 +2330,12 @@ def get_type_hints(obj, globalns=None, localns=None, include_extras=False,
2319
2330
value = _eval_type (value , base_globals , base_locals , base .__type_params__ ,
2320
2331
format = format , owner = obj )
2321
2332
hints [name ] = value
2322
- if include_extras or format == annotationlib . Format .STRING :
2333
+ if include_extras or format == Format .STRING :
2323
2334
return hints
2324
2335
else :
2325
2336
return {k : _strip_annotations (t ) for k , t in hints .items ()}
2326
2337
2327
- hints = annotationlib .get_annotations (obj , format = format )
2338
+ hints = _lazy_annotationlib .get_annotations (obj , format = format )
2328
2339
if (
2329
2340
not hints
2330
2341
and not isinstance (obj , types .ModuleType )
@@ -2333,7 +2344,7 @@ def get_type_hints(obj, globalns=None, localns=None, include_extras=False,
2333
2344
and not hasattr (obj , '__annotate__' )
2334
2345
):
2335
2346
raise TypeError (f"{ obj !r} is not a module, class, or callable." )
2336
- if format == annotationlib . Format .STRING :
2347
+ if format == Format .STRING :
2337
2348
return hints
2338
2349
2339
2350
if globalns is None :
@@ -2850,10 +2861,10 @@ def _make_eager_annotate(types):
2850
2861
for key , val in types .items ()}
2851
2862
def annotate (format ):
2852
2863
match format :
2853
- case annotationlib .Format .VALUE | annotationlib .Format .FORWARDREF :
2864
+ case _lazy_annotationlib .Format .VALUE | _lazy_annotationlib .Format .FORWARDREF :
2854
2865
return checked_types
2855
- case annotationlib .Format .STRING :
2856
- return annotationlib .annotations_to_string (types )
2866
+ case _lazy_annotationlib .Format .STRING :
2867
+ return _lazy_annotationlib .annotations_to_string (types )
2857
2868
case _:
2858
2869
raise NotImplementedError (format )
2859
2870
return annotate
@@ -2884,16 +2895,18 @@ def __new__(cls, typename, bases, ns):
2884
2895
annotate = _make_eager_annotate (types )
2885
2896
elif "__annotate__" in ns :
2886
2897
original_annotate = ns ["__annotate__" ]
2887
- types = annotationlib .call_annotate_function (original_annotate , annotationlib .Format .FORWARDREF )
2898
+ types = _lazy_annotationlib .call_annotate_function (
2899
+ original_annotate , _lazy_annotationlib .Format .FORWARDREF )
2888
2900
field_names = list (types )
2889
2901
2890
2902
# For backward compatibility, type-check all the types at creation time
2891
2903
for typ in types .values ():
2892
2904
_type_check (typ , "field annotation must be a type" )
2893
2905
2894
2906
def annotate (format ):
2895
- annos = annotationlib .call_annotate_function (original_annotate , format )
2896
- if format != annotationlib .Format .STRING :
2907
+ annos = _lazy_annotationlib .call_annotate_function (
2908
+ original_annotate , format )
2909
+ if format != _lazy_annotationlib .Format .STRING :
2897
2910
return {key : _type_check (val , f"field { key } annotation must be a type" )
2898
2911
for key , val in annos .items ()}
2899
2912
return annos
@@ -3069,8 +3082,8 @@ def __new__(cls, name, bases, ns, total=True):
3069
3082
own_annotations = ns ["__annotations__" ]
3070
3083
elif "__annotate__" in ns :
3071
3084
own_annotate = ns ["__annotate__" ]
3072
- own_annotations = annotationlib .call_annotate_function (
3073
- own_annotate , annotationlib .Format .FORWARDREF , owner = tp_dict
3085
+ own_annotations = _lazy_annotationlib .call_annotate_function (
3086
+ own_annotate , _lazy_annotationlib .Format .FORWARDREF , owner = tp_dict
3074
3087
)
3075
3088
else :
3076
3089
own_annotate = None
@@ -3137,18 +3150,20 @@ def __annotate__(format):
3137
3150
base_annotate = base .__annotate__
3138
3151
if base_annotate is None :
3139
3152
continue
3140
- base_annos = annotationlib .call_annotate_function (base .__annotate__ , format , owner = base )
3153
+ base_annos = _lazy_annotationlib .call_annotate_function (
3154
+ base .__annotate__ , format , owner = base )
3141
3155
annos .update (base_annos )
3142
3156
if own_annotate is not None :
3143
- own = annotationlib .call_annotate_function (own_annotate , format , owner = tp_dict )
3144
- if format != annotationlib .Format .STRING :
3157
+ own = _lazy_annotationlib .call_annotate_function (
3158
+ own_annotate , format , owner = tp_dict )
3159
+ if format != _lazy_annotationlib .Format .STRING :
3145
3160
own = {
3146
3161
n : _type_check (tp , msg , module = tp_dict .__module__ )
3147
3162
for n , tp in own .items ()
3148
3163
}
3149
- elif format == annotationlib .Format .STRING :
3150
- own = annotationlib .annotations_to_string (own_annotations )
3151
- elif format in (annotationlib .Format .FORWARDREF , annotationlib .Format .VALUE ):
3164
+ elif format == _lazy_annotationlib .Format .STRING :
3165
+ own = _lazy_annotationlib .annotations_to_string (own_annotations )
3166
+ elif format in (_lazy_annotationlib .Format .FORWARDREF , _lazy_annotationlib .Format .VALUE ):
3152
3167
own = own_checked_annotations
3153
3168
else :
3154
3169
raise NotImplementedError (format )
@@ -3732,7 +3747,9 @@ def __getattr__(attr):
3732
3747
Soft-deprecated objects which are costly to create
3733
3748
are only created on-demand here.
3734
3749
"""
3735
- if attr in {"Pattern" , "Match" }:
3750
+ if attr == "ForwardRef" :
3751
+ obj = _lazy_annotationlib .ForwardRef
3752
+ elif attr in {"Pattern" , "Match" }:
3736
3753
import re
3737
3754
obj = _alias (getattr (re , attr ), 1 )
3738
3755
elif attr in {"ContextManager" , "AsyncContextManager" }:
0 commit comments