25
25
import keyword
26
26
import pydoc
27
27
import re
28
- from collections import namedtuple
29
28
from dataclasses import dataclass
30
29
from typing import Any , Callable , Optional , Type , Dict , List
31
30
from types import MemberDescriptorType , TracebackType
37
36
from .lazyre import LazyReCompile
38
37
39
38
40
- ArgSpec = namedtuple (
41
- "ArgSpec" ,
42
- [
43
- "args" ,
44
- "varargs" ,
45
- "varkwargs" ,
46
- "defaults" ,
47
- "kwonly" ,
48
- "kwonly_defaults" ,
49
- "annotations" ,
50
- ],
51
- )
39
+ @dataclass
40
+ class ArgSpec :
41
+ args : List [str ]
42
+ varargs : Optional [str ]
43
+ varkwargs : Optional [str ]
44
+ defaults : Optional [List [Any ]]
45
+ kwonly : List [str ]
46
+ kwonly_defaults : Optional [Dict [str , Any ]]
47
+ annotations : Optional [Dict [str , Any ]]
52
48
53
49
54
50
@dataclass
@@ -171,32 +167,33 @@ def parsekeywordpairs(signature: str) -> Dict[str, str]:
171
167
return {item [0 ]: "" .join (item [2 :]) for item in stack if len (item ) >= 3 }
172
168
173
169
174
- def fixlongargs (f , argspec ) :
170
+ def fixlongargs (f : Callable , argspec : ArgSpec ) -> ArgSpec :
175
171
"""Functions taking default arguments that are references to other objects
176
172
whose str() is too big will cause breakage, so we swap out the object
177
173
itself with the name it was referenced with in the source by parsing the
178
174
source itself !"""
179
- if argspec [ 3 ] is None :
175
+ if argspec . defaults is None :
180
176
# No keyword args, no need to do anything
181
- return
182
- values = list (argspec [ 3 ] )
177
+ return argspec
178
+ values = list (argspec . defaults )
183
179
if not values :
184
- return
185
- keys = argspec [ 0 ] [- len (values ) :]
180
+ return argspec
181
+ keys = argspec . args [- len (values ) :]
186
182
try :
187
183
src = inspect .getsourcelines (f )
188
184
except (OSError , IndexError ):
189
185
# IndexError is raised in inspect.findsource(), can happen in
190
186
# some situations. See issue #94.
191
- return
187
+ return argspec
192
188
signature = "" .join (src [0 ])
193
189
kwparsed = parsekeywordpairs (signature )
194
190
195
191
for i , (key , value ) in enumerate (zip (keys , values )):
196
192
if len (repr (value )) != len (kwparsed [key ]):
197
193
values [i ] = _Repr (kwparsed [key ])
198
194
199
- argspec [3 ] = values
195
+ argspec .defaults = values
196
+ return argspec
200
197
201
198
202
199
getpydocspec_re = LazyReCompile (
@@ -247,7 +244,7 @@ def getpydocspec(f, func):
247
244
)
248
245
249
246
250
- def getfuncprops (func , f ) :
247
+ def getfuncprops (func : str , f : Callable ) -> Optional [ FuncProps ] :
251
248
# Check if it's a real bound method or if it's implicitly calling __init__
252
249
# (i.e. FooClass(...) and not FooClass.__init__(...) -- the former would
253
250
# not take 'self', the latter would:
@@ -268,9 +265,8 @@ def getfuncprops(func, f):
268
265
# '__init__' throws xmlrpclib.Fault (see #202)
269
266
return None
270
267
try :
271
- argspec = get_argspec_from_signature (f )
272
- fixlongargs (f , argspec )
273
- argspec = ArgSpec (* argspec )
268
+ argspec = _get_argspec_from_signature (f )
269
+ argspec = fixlongargs (f , argspec )
274
270
fprops = FuncProps (func , argspec , is_bound_method )
275
271
except (TypeError , KeyError , ValueError ):
276
272
argspec = getpydocspec (f , func )
@@ -289,7 +285,7 @@ def is_eval_safe_name(string: str) -> bool:
289
285
)
290
286
291
287
292
- def get_argspec_from_signature ( f ) :
288
+ def _get_argspec_from_signature ( f : Callable ) -> ArgSpec :
293
289
"""Get callable signature from inspect.signature in argspec format.
294
290
295
291
inspect.signature is a Python 3 only function that returns the signature of
@@ -324,26 +320,15 @@ def get_argspec_from_signature(f):
324
320
elif parameter .kind == inspect .Parameter .VAR_KEYWORD :
325
321
varkwargs = parameter .name
326
322
327
- # inspect.getfullargspec returns None for 'defaults', 'kwonly_defaults' and
328
- # 'annotations' if there are no values for them.
329
- if not defaults :
330
- defaults = None
331
-
332
- if not kwonly_defaults :
333
- kwonly_defaults = None
334
-
335
- if not annotations :
336
- annotations = None
337
-
338
- return [
323
+ return ArgSpec (
339
324
args ,
340
325
varargs ,
341
326
varkwargs ,
342
- defaults ,
327
+ defaults if defaults else None ,
343
328
kwonly ,
344
- kwonly_defaults ,
345
- annotations ,
346
- ]
329
+ kwonly_defaults if kwonly_defaults else None ,
330
+ annotations if annotations else None ,
331
+ )
347
332
348
333
349
334
get_encoding_line_re = LazyReCompile (r"^.*coding[:=]\s*([-\w.]+).*$" )
0 commit comments