24
24
stack(), trace() - get info about frames on the stack or in a traceback
25
25
26
26
signature() - get a Signature object for the callable
27
+
28
+ get_annotations() - safely compute an object's annotations
27
29
"""
28
30
29
31
# This module is in the public domain. No warranties.
60
62
# See Include/object.h
61
63
TPFLAGS_IS_ABSTRACT = 1 << 20
62
64
65
+
66
+ def get_annotations (obj , * , globals = None , locals = None , eval_str = False ):
67
+ """Compute the annotations dict for an object.
68
+
69
+ obj may be a callable, class, or module.
70
+ Passing in an object of any other type raises TypeError.
71
+
72
+ Returns a dict. get_annotations() returns a new dict every time
73
+ it's called; calling it twice on the same object will return two
74
+ different but equivalent dicts.
75
+
76
+ This function handles several details for you:
77
+
78
+ * If eval_str is true, values of type str will
79
+ be un-stringized using eval(). This is intended
80
+ for use with stringized annotations
81
+ ("from __future__ import annotations").
82
+ * If obj doesn't have an annotations dict, returns an
83
+ empty dict. (Functions and methods always have an
84
+ annotations dict; classes, modules, and other types of
85
+ callables may not.)
86
+ * Ignores inherited annotations on classes. If a class
87
+ doesn't have its own annotations dict, returns an empty dict.
88
+ * All accesses to object members and dict values are done
89
+ using getattr() and dict.get() for safety.
90
+ * Always, always, always returns a freshly-created dict.
91
+
92
+ eval_str controls whether or not values of type str are replaced
93
+ with the result of calling eval() on those values:
94
+
95
+ * If eval_str is true, eval() is called on values of type str.
96
+ * If eval_str is false (the default), values of type str are unchanged.
97
+
98
+ globals and locals are passed in to eval(); see the documentation
99
+ for eval() for more information. If either globals or locals is
100
+ None, this function may replace that value with a context-specific
101
+ default, contingent on type(obj):
102
+
103
+ * If obj is a module, globals defaults to obj.__dict__.
104
+ * If obj is a class, globals defaults to
105
+ sys.modules[obj.__module__].__dict__ and locals
106
+ defaults to the obj class namespace.
107
+ * If obj is a callable, globals defaults to obj.__globals__,
108
+ although if obj is a wrapped function (using
109
+ functools.update_wrapper()) it is first unwrapped.
110
+ """
111
+ if isinstance (obj , type ):
112
+ # class
113
+ obj_dict = getattr (obj , '__dict__' , None )
114
+ if obj_dict and hasattr (obj_dict , 'get' ):
115
+ ann = obj_dict .get ('__annotations__' , None )
116
+ if isinstance (ann , types .GetSetDescriptorType ):
117
+ ann = None
118
+ else :
119
+ ann = None
120
+
121
+ obj_globals = None
122
+ module_name = getattr (obj , '__module__' , None )
123
+ if module_name :
124
+ module = sys .modules .get (module_name , None )
125
+ if module :
126
+ obj_globals = getattr (module , '__dict__' , None )
127
+ obj_locals = dict (vars (obj ))
128
+ unwrap = obj
129
+ elif isinstance (obj , types .ModuleType ):
130
+ # module
131
+ ann = getattr (obj , '__annotations__' , None )
132
+ obj_globals = getattr (obj , '__dict__' )
133
+ obj_locals = None
134
+ unwrap = None
135
+ elif callable (obj ):
136
+ # this includes types.Function, types.BuiltinFunctionType,
137
+ # types.BuiltinMethodType, functools.partial, functools.singledispatch,
138
+ # "class funclike" from Lib/test/test_inspect... on and on it goes.
139
+ ann = getattr (obj , '__annotations__' , None )
140
+ obj_globals = getattr (obj , '__globals__' , None )
141
+ obj_locals = None
142
+ unwrap = obj
143
+ else :
144
+ raise TypeError (f"{ obj !r} is not a module, class, or callable." )
145
+
146
+ if ann is None :
147
+ return {}
148
+
149
+ if not isinstance (ann , dict ):
150
+ raise ValueError (f"{ obj !r} .__annotations__ is neither a dict nor None" )
151
+
152
+ if not ann :
153
+ return {}
154
+
155
+ if not eval_str :
156
+ return dict (ann )
157
+
158
+ if unwrap is not None :
159
+ while True :
160
+ if hasattr (unwrap , '__wrapped__' ):
161
+ unwrap = unwrap .__wrapped__
162
+ continue
163
+ if isinstance (unwrap , functools .partial ):
164
+ unwrap = unwrap .func
165
+ continue
166
+ break
167
+ if hasattr (unwrap , "__globals__" ):
168
+ obj_globals = unwrap .__globals__
169
+
170
+ if globals is None :
171
+ globals = obj_globals
172
+ if locals is None :
173
+ locals = obj_locals
174
+
175
+ return_value = {key :
176
+ value if not isinstance (value , str ) else eval (value , globals , locals )
177
+ for key , value in ann .items () }
178
+ return return_value
179
+
180
+
63
181
# ----------------------------------------------------------- type-checking
64
182
def ismodule (object ):
65
183
"""Return true if the object is a module.
@@ -1165,7 +1283,8 @@ def getfullargspec(func):
1165
1283
sig = _signature_from_callable (func ,
1166
1284
follow_wrapper_chains = False ,
1167
1285
skip_bound_arg = False ,
1168
- sigcls = Signature )
1286
+ sigcls = Signature ,
1287
+ eval_str = False )
1169
1288
except Exception as ex :
1170
1289
# Most of the times 'signature' will raise ValueError.
1171
1290
# But, it can also raise AttributeError, and, maybe something
@@ -1898,7 +2017,7 @@ def _signature_is_functionlike(obj):
1898
2017
isinstance (name , str ) and
1899
2018
(defaults is None or isinstance (defaults , tuple )) and
1900
2019
(kwdefaults is None or isinstance (kwdefaults , dict )) and
1901
- isinstance (annotations , dict ))
2020
+ ( isinstance (annotations , ( dict )) or annotations is None ) )
1902
2021
1903
2022
1904
2023
def _signature_get_bound_param (spec ):
@@ -2151,7 +2270,7 @@ def _signature_from_builtin(cls, func, skip_bound_arg=True):
2151
2270
2152
2271
2153
2272
def _signature_from_function (cls , func , skip_bound_arg = True ,
2154
- globalns = None , localns = None ):
2273
+ globals = None , locals = None , eval_str = False ):
2155
2274
"""Private helper: constructs Signature for the given python function."""
2156
2275
2157
2276
is_duck_function = False
@@ -2177,7 +2296,7 @@ def _signature_from_function(cls, func, skip_bound_arg=True,
2177
2296
positional = arg_names [:pos_count ]
2178
2297
keyword_only_count = func_code .co_kwonlyargcount
2179
2298
keyword_only = arg_names [pos_count :pos_count + keyword_only_count ]
2180
- annotations = func . __annotations__
2299
+ annotations = get_annotations ( func , globals = globals , locals = locals , eval_str = eval_str )
2181
2300
defaults = func .__defaults__
2182
2301
kwdefaults = func .__kwdefaults__
2183
2302
@@ -2248,8 +2367,9 @@ def _signature_from_function(cls, func, skip_bound_arg=True,
2248
2367
def _signature_from_callable (obj , * ,
2249
2368
follow_wrapper_chains = True ,
2250
2369
skip_bound_arg = True ,
2251
- globalns = None ,
2252
- localns = None ,
2370
+ globals = None ,
2371
+ locals = None ,
2372
+ eval_str = False ,
2253
2373
sigcls ):
2254
2374
2255
2375
"""Private helper function to get signature for arbitrary
@@ -2259,9 +2379,10 @@ def _signature_from_callable(obj, *,
2259
2379
_get_signature_of = functools .partial (_signature_from_callable ,
2260
2380
follow_wrapper_chains = follow_wrapper_chains ,
2261
2381
skip_bound_arg = skip_bound_arg ,
2262
- globalns = globalns ,
2263
- localns = localns ,
2264
- sigcls = sigcls )
2382
+ globals = globals ,
2383
+ locals = locals ,
2384
+ sigcls = sigcls ,
2385
+ eval_str = eval_str )
2265
2386
2266
2387
if not callable (obj ):
2267
2388
raise TypeError ('{!r} is not a callable object' .format (obj ))
@@ -2330,7 +2451,7 @@ def _signature_from_callable(obj, *,
2330
2451
# of a Python function (Cython functions, for instance), then:
2331
2452
return _signature_from_function (sigcls , obj ,
2332
2453
skip_bound_arg = skip_bound_arg ,
2333
- globalns = globalns , localns = localns )
2454
+ globals = globals , locals = locals , eval_str = eval_str )
2334
2455
2335
2456
if _signature_is_builtin (obj ):
2336
2457
return _signature_from_builtin (sigcls , obj ,
@@ -2854,11 +2975,11 @@ def from_builtin(cls, func):
2854
2975
2855
2976
@classmethod
2856
2977
def from_callable (cls , obj , * ,
2857
- follow_wrapped = True , globalns = None , localns = None ):
2978
+ follow_wrapped = True , globals = None , locals = None , eval_str = False ):
2858
2979
"""Constructs Signature for the given callable object."""
2859
2980
return _signature_from_callable (obj , sigcls = cls ,
2860
2981
follow_wrapper_chains = follow_wrapped ,
2861
- globalns = globalns , localns = localns )
2982
+ globals = globals , locals = locals , eval_str = eval_str )
2862
2983
2863
2984
@property
2864
2985
def parameters (self ):
@@ -3106,10 +3227,10 @@ def __str__(self):
3106
3227
return rendered
3107
3228
3108
3229
3109
- def signature (obj , * , follow_wrapped = True , globalns = None , localns = None ):
3230
+ def signature (obj , * , follow_wrapped = True , globals = None , locals = None , eval_str = False ):
3110
3231
"""Get a signature object for the passed callable."""
3111
3232
return Signature .from_callable (obj , follow_wrapped = follow_wrapped ,
3112
- globalns = globalns , localns = localns )
3233
+ globals = globals , locals = locals , eval_str = eval_str )
3113
3234
3114
3235
3115
3236
def _main ():
0 commit comments