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
164
162
'Unpack' ,
165
163
]
166
164
165
+ class _LazyAnnotationLib :
166
+ def __init__ (self ) -> None :
167
+ self ._annolib = None
168
+
169
+ def __getattr__ (self , attr ):
170
+ if self ._annolib is None :
171
+ import annotationlib
172
+
173
+ self ._annolib = annotationlib
174
+
175
+ value = getattr (self ._annolib , attr )
176
+ setattr (self , attr , value )
177
+ return value
178
+
179
+ _lazy_annotationlib = _LazyAnnotationLib ()
180
+
167
181
168
182
def _type_convert (arg , module = None , * , allow_special_forms = False ):
169
183
"""For converting None to type(None), and strings to ForwardRef."""
@@ -247,7 +261,7 @@ def _type_repr(obj):
247
261
if isinstance (obj , tuple ):
248
262
# Special case for `repr` of types with `ParamSpec`:
249
263
return '[' + ', ' .join (_type_repr (t ) for t in obj ) + ']'
250
- return annotationlib .value_to_string (obj )
264
+ return _lazy_annotationlib .value_to_string (obj )
251
265
252
266
253
267
def _collect_type_parameters (args , * , enforce_default_ordering : bool = True ):
@@ -424,7 +438,7 @@ def __repr__(self):
424
438
425
439
426
440
def _eval_type (t , globalns , localns , type_params = _sentinel , * , recursive_guard = frozenset (),
427
- format = annotationlib . Format . VALUE , owner = None ):
441
+ format = None , owner = None ):
428
442
"""Evaluate all forward references in the given type t.
429
443
430
444
For use of globalns and localns see the docstring for get_type_hints().
@@ -434,7 +448,7 @@ def _eval_type(t, globalns, localns, type_params=_sentinel, *, recursive_guard=f
434
448
if type_params is _sentinel :
435
449
_deprecation_warning_for_no_type_params_passed ("typing._eval_type" )
436
450
type_params = ()
437
- if isinstance (t , ForwardRef ):
451
+ if isinstance (t , _lazy_annotationlib . ForwardRef ):
438
452
# If the forward_ref has __forward_module__ set, evaluate() infers the globals
439
453
# from the module, and it will probably pick better than the globals we have here.
440
454
if t .__forward_module__ is not None :
@@ -931,7 +945,7 @@ def run(arg: Child | Unrelated):
931
945
932
946
933
947
def _make_forward_ref (code , ** kwargs ):
934
- forward_ref = ForwardRef (code , ** kwargs )
948
+ forward_ref = _lazy_annotationlib . ForwardRef (code , ** kwargs )
935
949
# For compatibility, eagerly compile the forwardref's code.
936
950
forward_ref .__forward_code__
937
951
return forward_ref
@@ -944,7 +958,7 @@ def evaluate_forward_ref(
944
958
globals = None ,
945
959
locals = None ,
946
960
type_params = None ,
947
- format = annotationlib . Format . VALUE ,
961
+ format = None ,
948
962
_recursive_guard = frozenset (),
949
963
):
950
964
"""Evaluate a forward reference as a type hint.
@@ -966,10 +980,11 @@ def evaluate_forward_ref(
966
980
evaluating the forward reference. This parameter should be provided (though
967
981
it may be an empty tuple) if *owner* is not given and the forward reference
968
982
does not already have an owner set. *format* specifies the format of the
969
- annotation and is a member of the annotationlib.Format enum.
983
+ annotation and is a member of the annotationlib.Format enum, defaulting to
984
+ VALUE.
970
985
971
986
"""
972
- if format == annotationlib .Format .STRING :
987
+ if format == _lazy_annotationlib .Format .STRING :
973
988
return forward_ref .__forward_arg__
974
989
if forward_ref .__forward_arg__ in _recursive_guard :
975
990
return forward_ref
@@ -978,7 +993,7 @@ def evaluate_forward_ref(
978
993
value = forward_ref .evaluate (globals = globals , locals = locals ,
979
994
type_params = type_params , owner = owner )
980
995
except NameError :
981
- if format == annotationlib .Format .FORWARDREF :
996
+ if format == _lazy_annotationlib .Format .FORWARDREF :
982
997
return forward_ref
983
998
else :
984
999
raise
@@ -2254,7 +2269,7 @@ def greet(name: str) -> None:
2254
2269
2255
2270
2256
2271
def get_type_hints (obj , globalns = None , localns = None , include_extras = False ,
2257
- * , format = annotationlib . Format . VALUE ):
2272
+ * , format = None ):
2258
2273
"""Return type hints for an object.
2259
2274
2260
2275
This is often the same as obj.__annotations__, but it handles
@@ -2287,12 +2302,15 @@ def get_type_hints(obj, globalns=None, localns=None, include_extras=False,
2287
2302
"""
2288
2303
if getattr (obj , '__no_type_check__' , None ):
2289
2304
return {}
2305
+ Format = _lazy_annotationlib .Format
2306
+ if format is None :
2307
+ format = Format .VALUE
2290
2308
# Classes require a special treatment.
2291
2309
if isinstance (obj , type ):
2292
2310
hints = {}
2293
2311
for base in reversed (obj .__mro__ ):
2294
- ann = annotationlib .get_annotations (base , format = format )
2295
- if format == annotationlib . Format .STRING :
2312
+ ann = _lazy_annotationlib .get_annotations (base , format = format )
2313
+ if format == Format .STRING :
2296
2314
hints .update (ann )
2297
2315
continue
2298
2316
if globalns is None :
@@ -2316,12 +2334,12 @@ def get_type_hints(obj, globalns=None, localns=None, include_extras=False,
2316
2334
value = _eval_type (value , base_globals , base_locals , base .__type_params__ ,
2317
2335
format = format , owner = obj )
2318
2336
hints [name ] = value
2319
- if include_extras or format == annotationlib . Format .STRING :
2337
+ if include_extras or format == Format .STRING :
2320
2338
return hints
2321
2339
else :
2322
2340
return {k : _strip_annotations (t ) for k , t in hints .items ()}
2323
2341
2324
- hints = annotationlib .get_annotations (obj , format = format )
2342
+ hints = _lazy_annotationlib .get_annotations (obj , format = format )
2325
2343
if (
2326
2344
not hints
2327
2345
and not isinstance (obj , types .ModuleType )
@@ -2330,7 +2348,7 @@ def get_type_hints(obj, globalns=None, localns=None, include_extras=False,
2330
2348
and not hasattr (obj , '__annotate__' )
2331
2349
):
2332
2350
raise TypeError (f"{ obj !r} is not a module, class, or callable." )
2333
- if format == annotationlib . Format .STRING :
2351
+ if format == Format .STRING :
2334
2352
return hints
2335
2353
2336
2354
if globalns is None :
@@ -2847,10 +2865,10 @@ def _make_eager_annotate(types):
2847
2865
for key , val in types .items ()}
2848
2866
def annotate (format ):
2849
2867
match format :
2850
- case annotationlib .Format .VALUE | annotationlib .Format .FORWARDREF :
2868
+ case _lazy_annotationlib .Format .VALUE | _lazy_annotationlib .Format .FORWARDREF :
2851
2869
return checked_types
2852
- case annotationlib .Format .STRING :
2853
- return annotationlib .annotations_to_string (types )
2870
+ case _lazy_annotationlib .Format .STRING :
2871
+ return _lazy_annotationlib .annotations_to_string (types )
2854
2872
case _:
2855
2873
raise NotImplementedError (format )
2856
2874
return annotate
@@ -2881,16 +2899,18 @@ def __new__(cls, typename, bases, ns):
2881
2899
annotate = _make_eager_annotate (types )
2882
2900
elif "__annotate__" in ns :
2883
2901
original_annotate = ns ["__annotate__" ]
2884
- types = annotationlib .call_annotate_function (original_annotate , annotationlib .Format .FORWARDREF )
2902
+ types = _lazy_annotationlib .call_annotate_function (
2903
+ original_annotate , _lazy_annotationlib .Format .FORWARDREF )
2885
2904
field_names = list (types )
2886
2905
2887
2906
# For backward compatibility, type-check all the types at creation time
2888
2907
for typ in types .values ():
2889
2908
_type_check (typ , "field annotation must be a type" )
2890
2909
2891
2910
def annotate (format ):
2892
- annos = annotationlib .call_annotate_function (original_annotate , format )
2893
- if format != annotationlib .Format .STRING :
2911
+ annos = _lazy_annotationlib .call_annotate_function (
2912
+ original_annotate , format )
2913
+ if format != _lazy_annotationlib .Format .STRING :
2894
2914
return {key : _type_check (val , f"field { key } annotation must be a type" )
2895
2915
for key , val in annos .items ()}
2896
2916
return annos
@@ -3066,8 +3086,8 @@ def __new__(cls, name, bases, ns, total=True):
3066
3086
own_annotations = ns ["__annotations__" ]
3067
3087
elif "__annotate__" in ns :
3068
3088
own_annotate = ns ["__annotate__" ]
3069
- own_annotations = annotationlib .call_annotate_function (
3070
- own_annotate , annotationlib .Format .FORWARDREF , owner = tp_dict
3089
+ own_annotations = _lazy_annotationlib .call_annotate_function (
3090
+ own_annotate , _lazy_annotationlib .Format .FORWARDREF , owner = tp_dict
3071
3091
)
3072
3092
else :
3073
3093
own_annotate = None
@@ -3134,18 +3154,20 @@ def __annotate__(format):
3134
3154
base_annotate = base .__annotate__
3135
3155
if base_annotate is None :
3136
3156
continue
3137
- base_annos = annotationlib .call_annotate_function (base .__annotate__ , format , owner = base )
3157
+ base_annos = _lazy_annotationlib .call_annotate_function (
3158
+ base .__annotate__ , format , owner = base )
3138
3159
annos .update (base_annos )
3139
3160
if own_annotate is not None :
3140
- own = annotationlib .call_annotate_function (own_annotate , format , owner = tp_dict )
3141
- if format != annotationlib .Format .STRING :
3161
+ own = _lazy_annotationlib .call_annotate_function (
3162
+ own_annotate , format , owner = tp_dict )
3163
+ if format != _lazy_annotationlib .Format .STRING :
3142
3164
own = {
3143
3165
n : _type_check (tp , msg , module = tp_dict .__module__ )
3144
3166
for n , tp in own .items ()
3145
3167
}
3146
- elif format == annotationlib .Format .STRING :
3147
- own = annotationlib .annotations_to_string (own_annotations )
3148
- elif format in (annotationlib .Format .FORWARDREF , annotationlib .Format .VALUE ):
3168
+ elif format == _lazy_annotationlib .Format .STRING :
3169
+ own = _lazy_annotationlib .annotations_to_string (own_annotations )
3170
+ elif format in (_lazy_annotationlib .Format .FORWARDREF , _lazy_annotationlib .Format .VALUE ):
3149
3171
own = own_checked_annotations
3150
3172
else :
3151
3173
raise NotImplementedError (format )
@@ -3729,7 +3751,9 @@ def __getattr__(attr):
3729
3751
Soft-deprecated objects which are costly to create
3730
3752
are only created on-demand here.
3731
3753
"""
3732
- if attr in {"Pattern" , "Match" }:
3754
+ if attr == "ForwardRef" :
3755
+ obj = _lazy_annotationlib .ForwardRef
3756
+ elif attr in {"Pattern" , "Match" }:
3733
3757
import re
3734
3758
obj = _alias (getattr (re , attr ), 1 )
3735
3759
elif attr in {"ContextManager" , "AsyncContextManager" }:
0 commit comments