@@ -272,6 +272,7 @@ def iscode(object):
272272 | 16=nested | 32=generator | 64=nofree | 128=coroutine
273273 | 256=iterable_coroutine | 512=async_generator
274274 co_freevars tuple of names of free variables
275+ co_posonlyargcount number of positional only arguments
275276 co_kwonlyargcount number of keyword only arguments (not including ** arg)
276277 co_lnotab encoded mapping of line numbers to bytecode indices
277278 co_name name with which this code object was defined
@@ -1031,26 +1032,20 @@ def getargs(co):
10311032 'args' is the list of argument names. Keyword-only arguments are
10321033 appended. 'varargs' and 'varkw' are the names of the * and **
10331034 arguments or None."""
1034- args , varargs , kwonlyargs , varkw = _getfullargs (co )
1035- return Arguments (args + kwonlyargs , varargs , varkw )
1036-
1037- def _getfullargs (co ):
1038- """Get information about the arguments accepted by a code object.
1039-
1040- Four things are returned: (args, varargs, kwonlyargs, varkw), where
1041- 'args' and 'kwonlyargs' are lists of argument names, and 'varargs'
1042- and 'varkw' are the names of the * and ** arguments or None."""
1043-
10441035 if not iscode (co ):
10451036 raise TypeError ('{!r} is not a code object' .format (co ))
10461037
1047- nargs = co .co_argcount
10481038 names = co .co_varnames
1039+ nargs = co .co_argcount
1040+ nposonlyargs = co .co_posonlyargcount
10491041 nkwargs = co .co_kwonlyargcount
1050- args = list (names [:nargs ])
1051- kwonlyargs = list (names [nargs :nargs + nkwargs ])
1042+ nposargs = nargs + nposonlyargs
1043+ posonlyargs = list (names [:nposonlyargs ])
1044+ args = list (names [nposonlyargs :nposonlyargs + nargs ])
1045+ kwonlyargs = list (names [nposargs :nposargs + nkwargs ])
10521046 step = 0
10531047
1048+ nargs += nposonlyargs
10541049 nargs += nkwargs
10551050 varargs = None
10561051 if co .co_flags & CO_VARARGS :
@@ -1059,8 +1054,7 @@ def _getfullargs(co):
10591054 varkw = None
10601055 if co .co_flags & CO_VARKEYWORDS :
10611056 varkw = co .co_varnames [nargs ]
1062- return args , varargs , kwonlyargs , varkw
1063-
1057+ return Arguments (posonlyargs + args + kwonlyargs , varargs , varkw )
10641058
10651059ArgSpec = namedtuple ('ArgSpec' , 'args varargs keywords defaults' )
10661060
@@ -1087,15 +1081,16 @@ def getargspec(func):
10871081 warnings .warn ("inspect.getargspec() is deprecated since Python 3.0, "
10881082 "use inspect.signature() or inspect.getfullargspec()" ,
10891083 DeprecationWarning , stacklevel = 2 )
1090- args , varargs , varkw , defaults , kwonlyargs , kwonlydefaults , ann = \
1091- getfullargspec (func )
1092- if kwonlyargs or ann :
1093- raise ValueError ("Function has keyword-only parameters or annotations"
1094- ", use getfullargspec() API which can support them" )
1084+ args , varargs , varkw , defaults , posonlyargs , kwonlyargs , \
1085+ kwonlydefaults , ann = getfullargspec (func )
1086+ if posonlyargs or kwonlyargs or ann :
1087+ raise ValueError ("Function has positional-only, keyword-only parameters"
1088+ " or annotations, use getfullargspec() API which can"
1089+ " support them" )
10951090 return ArgSpec (args , varargs , varkw , defaults )
10961091
10971092FullArgSpec = namedtuple ('FullArgSpec' ,
1098- 'args, varargs, varkw, defaults, kwonlyargs, kwonlydefaults, annotations' )
1093+ 'args, varargs, varkw, defaults, posonlyargs, kwonlyargs, kwonlydefaults, annotations' )
10991094
11001095def getfullargspec (func ):
11011096 """Get the names and default values of a callable object's parameters.
@@ -1145,6 +1140,7 @@ def getfullargspec(func):
11451140 args = []
11461141 varargs = None
11471142 varkw = None
1143+ posonlyargs = []
11481144 kwonlyargs = []
11491145 defaults = ()
11501146 annotations = {}
@@ -1159,7 +1155,9 @@ def getfullargspec(func):
11591155 name = param .name
11601156
11611157 if kind is _POSITIONAL_ONLY :
1162- args .append (name )
1158+ posonlyargs .append (name )
1159+ if param .default is not param .empty :
1160+ defaults += (param .default ,)
11631161 elif kind is _POSITIONAL_OR_KEYWORD :
11641162 args .append (name )
11651163 if param .default is not param .empty :
@@ -1185,7 +1183,7 @@ def getfullargspec(func):
11851183 defaults = None
11861184
11871185 return FullArgSpec (args , varargs , varkw , defaults ,
1188- kwonlyargs , kwdefaults , annotations )
1186+ posonlyargs , kwonlyargs , kwdefaults , annotations )
11891187
11901188
11911189ArgInfo = namedtuple ('ArgInfo' , 'args varargs keywords locals' )
@@ -1216,7 +1214,8 @@ def _formatannotation(annotation):
12161214 return _formatannotation
12171215
12181216def formatargspec (args , varargs = None , varkw = None , defaults = None ,
1219- kwonlyargs = (), kwonlydefaults = {}, annotations = {},
1217+ posonlyargs = (), kwonlyargs = (), kwonlydefaults = {},
1218+ annotations = {},
12201219 formatarg = str ,
12211220 formatvarargs = lambda name : '*' + name ,
12221221 formatvarkw = lambda name : '**' + name ,
@@ -1249,12 +1248,17 @@ def formatargandannotation(arg):
12491248 return result
12501249 specs = []
12511250 if defaults :
1252- firstdefault = len (args ) - len (defaults )
1253- for i , arg in enumerate (args ):
1251+ firstdefault = len (posonlyargs ) + len (args ) - len (defaults )
1252+ posonly_left = len (posonlyargs )
1253+ for i , arg in enumerate ([* posonlyargs , * args ]):
12541254 spec = formatargandannotation (arg )
12551255 if defaults and i >= firstdefault :
12561256 spec = spec + formatvalue (defaults [i - firstdefault ])
12571257 specs .append (spec )
1258+ posonly_left -= 1
1259+ if posonlyargs and posonly_left == 0 :
1260+ specs .append ('/' )
1261+
12581262 if varargs is not None :
12591263 specs .append (formatvarargs (formatargandannotation (varargs )))
12601264 else :
@@ -1342,7 +1346,8 @@ def getcallargs(*func_and_positional, **named):
13421346 func = func_and_positional [0 ]
13431347 positional = func_and_positional [1 :]
13441348 spec = getfullargspec (func )
1345- args , varargs , varkw , defaults , kwonlyargs , kwonlydefaults , ann = spec
1349+ (args , varargs , varkw , defaults , posonlyargs ,
1350+ kwonlyargs , kwonlydefaults , ann ) = spec
13461351 f_name = func .__name__
13471352 arg2value = {}
13481353
@@ -1351,12 +1356,16 @@ def getcallargs(*func_and_positional, **named):
13511356 # implicit 'self' (or 'cls' for classmethods) argument
13521357 positional = (func .__self__ ,) + positional
13531358 num_pos = len (positional )
1359+ num_posonlyargs = len (posonlyargs )
13541360 num_args = len (args )
13551361 num_defaults = len (defaults ) if defaults else 0
13561362
1363+ n = min (num_pos , num_posonlyargs )
1364+ for i in range (num_posonlyargs ):
1365+ arg2value [posonlyargs [i ]] = positional [i ]
13571366 n = min (num_pos , num_args )
13581367 for i in range (n ):
1359- arg2value [args [i ]] = positional [i ]
1368+ arg2value [args [i ]] = positional [num_posonlyargs + i ]
13601369 if varargs :
13611370 arg2value [varargs ] = tuple (positional [n :])
13621371 possible_kwargs = set (args + kwonlyargs )
@@ -2137,9 +2146,12 @@ def _signature_from_function(cls, func):
21372146 func_code = func .__code__
21382147 pos_count = func_code .co_argcount
21392148 arg_names = func_code .co_varnames
2140- positional = tuple (arg_names [:pos_count ])
2149+ posonly_count = func_code .co_posonlyargcount
2150+ positional_count = posonly_count + pos_count
2151+ positional_only = tuple (arg_names [:posonly_count ])
2152+ positional = tuple (arg_names [posonly_count :positional_count ])
21412153 keyword_only_count = func_code .co_kwonlyargcount
2142- keyword_only = arg_names [pos_count :( pos_count + keyword_only_count )]
2154+ keyword_only = arg_names [positional_count :( positional_count + keyword_only_count )]
21432155 annotations = func .__annotations__
21442156 defaults = func .__defaults__
21452157 kwdefaults = func .__kwdefaults__
@@ -2151,23 +2163,33 @@ def _signature_from_function(cls, func):
21512163
21522164 parameters = []
21532165
2166+ non_default_count = positional_count - pos_default_count
2167+ all_positional = positional_only + positional
2168+
2169+ posonly_left = posonly_count
2170+
21542171 # Non-keyword-only parameters w/o defaults.
2155- non_default_count = pos_count - pos_default_count
2156- for name in positional [: non_default_count ]:
2172+ for name in all_positional [: non_default_count ]:
2173+ kind = _POSITIONAL_ONLY if posonly_left else _POSITIONAL_OR_KEYWORD
21572174 annotation = annotations .get (name , _empty )
21582175 parameters .append (Parameter (name , annotation = annotation ,
2159- kind = _POSITIONAL_OR_KEYWORD ))
2176+ kind = kind ))
2177+ if posonly_left :
2178+ posonly_left -= 1
21602179
21612180 # ... w/ defaults.
2162- for offset , name in enumerate (positional [non_default_count :]):
2181+ for offset , name in enumerate (all_positional [non_default_count :]):
2182+ kind = _POSITIONAL_ONLY if posonly_left else _POSITIONAL_OR_KEYWORD
21632183 annotation = annotations .get (name , _empty )
21642184 parameters .append (Parameter (name , annotation = annotation ,
2165- kind = _POSITIONAL_OR_KEYWORD ,
2185+ kind = kind ,
21662186 default = defaults [offset ]))
2187+ if posonly_left :
2188+ posonly_left -= 1
21672189
21682190 # *args
21692191 if func_code .co_flags & CO_VARARGS :
2170- name = arg_names [pos_count + keyword_only_count ]
2192+ name = arg_names [positional_count + keyword_only_count ]
21712193 annotation = annotations .get (name , _empty )
21722194 parameters .append (Parameter (name , annotation = annotation ,
21732195 kind = _VAR_POSITIONAL ))
@@ -2184,7 +2206,7 @@ def _signature_from_function(cls, func):
21842206 default = default ))
21852207 # **kwargs
21862208 if func_code .co_flags & CO_VARKEYWORDS :
2187- index = pos_count + keyword_only_count
2209+ index = positional_count + keyword_only_count
21882210 if func_code .co_flags & CO_VARARGS :
21892211 index += 1
21902212
0 commit comments