@@ -272,6 +272,7 @@ def iscode(object):
272
272
| 16=nested | 32=generator | 64=nofree | 128=coroutine
273
273
| 256=iterable_coroutine | 512=async_generator
274
274
co_freevars tuple of names of free variables
275
+ co_posonlyargcount number of positional only arguments
275
276
co_kwonlyargcount number of keyword only arguments (not including ** arg)
276
277
co_lnotab encoded mapping of line numbers to bytecode indices
277
278
co_name name with which this code object was defined
@@ -1031,8 +1032,8 @@ def getargs(co):
1031
1032
'args' is the list of argument names. Keyword-only arguments are
1032
1033
appended. 'varargs' and 'varkw' are the names of the * and **
1033
1034
arguments or None."""
1034
- args , varargs , kwonlyargs , varkw = _getfullargs (co )
1035
- return Arguments (args + kwonlyargs , varargs , varkw )
1035
+ args , varargs , posonlyargs , kwonlyargs , varkw = _getfullargs (co )
1036
+ return Arguments (posonlyargs + args + kwonlyargs , varargs , varkw )
1036
1037
1037
1038
def _getfullargs (co ):
1038
1039
"""Get information about the arguments accepted by a code object.
@@ -1044,13 +1045,17 @@ def _getfullargs(co):
1044
1045
if not iscode (co ):
1045
1046
raise TypeError ('{!r} is not a code object' .format (co ))
1046
1047
1047
- nargs = co .co_argcount
1048
1048
names = co .co_varnames
1049
+ nargs = co .co_argcount
1050
+ nposonlyargs = co .co_posonlyargcount
1049
1051
nkwargs = co .co_kwonlyargcount
1050
- args = list (names [:nargs ])
1051
- kwonlyargs = list (names [nargs :nargs + nkwargs ])
1052
+ nposargs = nargs + nposonlyargs
1053
+ posonlyargs = list (names [:nposonlyargs ])
1054
+ args = list (names [nposonlyargs :nposonlyargs + nargs ])
1055
+ kwonlyargs = list (names [nposargs :nposargs + nkwargs ])
1052
1056
step = 0
1053
1057
1058
+ nargs += nposonlyargs
1054
1059
nargs += nkwargs
1055
1060
varargs = None
1056
1061
if co .co_flags & CO_VARARGS :
@@ -1059,7 +1064,7 @@ def _getfullargs(co):
1059
1064
varkw = None
1060
1065
if co .co_flags & CO_VARKEYWORDS :
1061
1066
varkw = co .co_varnames [nargs ]
1062
- return args , varargs , kwonlyargs , varkw
1067
+ return args , varargs , posonlyargs , kwonlyargs , varkw
1063
1068
1064
1069
1065
1070
ArgSpec = namedtuple ('ArgSpec' , 'args varargs keywords defaults' )
@@ -1087,15 +1092,16 @@ def getargspec(func):
1087
1092
warnings .warn ("inspect.getargspec() is deprecated since Python 3.0, "
1088
1093
"use inspect.signature() or inspect.getfullargspec()" ,
1089
1094
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" )
1095
+ args , varargs , varkw , defaults , posonlyargs , kwonlyargs , \
1096
+ kwonlydefaults , ann = getfullargspec (func )
1097
+ if posonlyargs or kwonlyargs or ann :
1098
+ raise ValueError ("Function has positional-only, keyword-only parameters"
1099
+ " or annotations, use getfullargspec() API which can"
1100
+ " support them" )
1095
1101
return ArgSpec (args , varargs , varkw , defaults )
1096
1102
1097
1103
FullArgSpec = namedtuple ('FullArgSpec' ,
1098
- 'args, varargs, varkw, defaults, kwonlyargs, kwonlydefaults, annotations' )
1104
+ 'args, varargs, varkw, defaults, posonlyargs, kwonlyargs, kwonlydefaults, annotations' )
1099
1105
1100
1106
def getfullargspec (func ):
1101
1107
"""Get the names and default values of a callable object's parameters.
@@ -1145,6 +1151,7 @@ def getfullargspec(func):
1145
1151
args = []
1146
1152
varargs = None
1147
1153
varkw = None
1154
+ posonlyargs = []
1148
1155
kwonlyargs = []
1149
1156
defaults = ()
1150
1157
annotations = {}
@@ -1159,7 +1166,9 @@ def getfullargspec(func):
1159
1166
name = param .name
1160
1167
1161
1168
if kind is _POSITIONAL_ONLY :
1162
- args .append (name )
1169
+ posonlyargs .append (name )
1170
+ if param .default is not param .empty :
1171
+ defaults += (param .default ,)
1163
1172
elif kind is _POSITIONAL_OR_KEYWORD :
1164
1173
args .append (name )
1165
1174
if param .default is not param .empty :
@@ -1185,7 +1194,7 @@ def getfullargspec(func):
1185
1194
defaults = None
1186
1195
1187
1196
return FullArgSpec (args , varargs , varkw , defaults ,
1188
- kwonlyargs , kwdefaults , annotations )
1197
+ posonlyargs , kwonlyargs , kwdefaults , annotations )
1189
1198
1190
1199
1191
1200
ArgInfo = namedtuple ('ArgInfo' , 'args varargs keywords locals' )
@@ -1216,7 +1225,8 @@ def _formatannotation(annotation):
1216
1225
return _formatannotation
1217
1226
1218
1227
def formatargspec (args , varargs = None , varkw = None , defaults = None ,
1219
- kwonlyargs = (), kwonlydefaults = {}, annotations = {},
1228
+ posonlyargs = (), kwonlyargs = (), kwonlydefaults = {},
1229
+ annotations = {},
1220
1230
formatarg = str ,
1221
1231
formatvarargs = lambda name : '*' + name ,
1222
1232
formatvarkw = lambda name : '**' + name ,
@@ -1249,12 +1259,17 @@ def formatargandannotation(arg):
1249
1259
return result
1250
1260
specs = []
1251
1261
if defaults :
1252
- firstdefault = len (args ) - len (defaults )
1253
- for i , arg in enumerate (args ):
1262
+ firstdefault = len (posonlyargs ) + len (args ) - len (defaults )
1263
+ posonly_left = len (posonlyargs )
1264
+ for i , arg in enumerate (list (posonlyargs ) + list (args )):
1254
1265
spec = formatargandannotation (arg )
1255
1266
if defaults and i >= firstdefault :
1256
1267
spec = spec + formatvalue (defaults [i - firstdefault ])
1257
1268
specs .append (spec )
1269
+ posonly_left -= 1
1270
+ if posonlyargs and posonly_left == 0 :
1271
+ specs .append ('/' )
1272
+
1258
1273
if varargs is not None :
1259
1274
specs .append (formatvarargs (formatargandannotation (varargs )))
1260
1275
else :
@@ -1342,7 +1357,8 @@ def getcallargs(*func_and_positional, **named):
1342
1357
func = func_and_positional [0 ]
1343
1358
positional = func_and_positional [1 :]
1344
1359
spec = getfullargspec (func )
1345
- args , varargs , varkw , defaults , kwonlyargs , kwonlydefaults , ann = spec
1360
+ (args , varargs , varkw , defaults , posonlyargs ,
1361
+ kwonlyargs , kwonlydefaults , ann ) = spec
1346
1362
f_name = func .__name__
1347
1363
arg2value = {}
1348
1364
@@ -1351,12 +1367,16 @@ def getcallargs(*func_and_positional, **named):
1351
1367
# implicit 'self' (or 'cls' for classmethods) argument
1352
1368
positional = (func .__self__ ,) + positional
1353
1369
num_pos = len (positional )
1370
+ num_posonlyargs = len (posonlyargs )
1354
1371
num_args = len (args )
1355
1372
num_defaults = len (defaults ) if defaults else 0
1356
1373
1374
+ n = min (num_pos , num_posonlyargs )
1375
+ for i in range (num_posonlyargs ):
1376
+ arg2value [posonlyargs [i ]] = positional [i ]
1357
1377
n = min (num_pos , num_args )
1358
1378
for i in range (n ):
1359
- arg2value [args [i ]] = positional [i ]
1379
+ arg2value [args [i ]] = positional [num_posonlyargs + i ]
1360
1380
if varargs :
1361
1381
arg2value [varargs ] = tuple (positional [n :])
1362
1382
possible_kwargs = set (args + kwonlyargs )
@@ -2137,9 +2157,12 @@ def _signature_from_function(cls, func):
2137
2157
func_code = func .__code__
2138
2158
pos_count = func_code .co_argcount
2139
2159
arg_names = func_code .co_varnames
2140
- positional = tuple (arg_names [:pos_count ])
2160
+ posonly_count = func_code .co_posonlyargcount
2161
+ positional_count = posonly_count + pos_count
2162
+ positional_only = tuple (arg_names [:posonly_count ])
2163
+ positional = tuple (arg_names [posonly_count :positional_count ])
2141
2164
keyword_only_count = func_code .co_kwonlyargcount
2142
- keyword_only = arg_names [pos_count :( pos_count + keyword_only_count )]
2165
+ keyword_only = arg_names [positional_count :( positional_count + keyword_only_count )]
2143
2166
annotations = func .__annotations__
2144
2167
defaults = func .__defaults__
2145
2168
kwdefaults = func .__kwdefaults__
@@ -2151,23 +2174,33 @@ def _signature_from_function(cls, func):
2151
2174
2152
2175
parameters = []
2153
2176
2177
+ non_default_count = positional_count - pos_default_count
2178
+ all_positional = positional_only + positional
2179
+
2180
+ posonly_left = posonly_count
2181
+
2154
2182
# Non-keyword-only parameters w/o defaults.
2155
- non_default_count = pos_count - pos_default_count
2156
- for name in positional [: non_default_count ]:
2183
+ for name in all_positional [: non_default_count ]:
2184
+ kind = _POSITIONAL_ONLY if posonly_left else _POSITIONAL_OR_KEYWORD
2157
2185
annotation = annotations .get (name , _empty )
2158
2186
parameters .append (Parameter (name , annotation = annotation ,
2159
- kind = _POSITIONAL_OR_KEYWORD ))
2187
+ kind = kind ))
2188
+ if posonly_left :
2189
+ posonly_left -= 1
2160
2190
2161
2191
# ... w/ defaults.
2162
- for offset , name in enumerate (positional [non_default_count :]):
2192
+ for offset , name in enumerate (all_positional [non_default_count :]):
2193
+ kind = _POSITIONAL_ONLY if posonly_left else _POSITIONAL_OR_KEYWORD
2163
2194
annotation = annotations .get (name , _empty )
2164
2195
parameters .append (Parameter (name , annotation = annotation ,
2165
- kind = _POSITIONAL_OR_KEYWORD ,
2196
+ kind = kind ,
2166
2197
default = defaults [offset ]))
2198
+ if posonly_left :
2199
+ posonly_left -= 1
2167
2200
2168
2201
# *args
2169
2202
if func_code .co_flags & CO_VARARGS :
2170
- name = arg_names [pos_count + keyword_only_count ]
2203
+ name = arg_names [positional_count + keyword_only_count ]
2171
2204
annotation = annotations .get (name , _empty )
2172
2205
parameters .append (Parameter (name , annotation = annotation ,
2173
2206
kind = _VAR_POSITIONAL ))
@@ -2184,7 +2217,7 @@ def _signature_from_function(cls, func):
2184
2217
default = default ))
2185
2218
# **kwargs
2186
2219
if func_code .co_flags & CO_VARKEYWORDS :
2187
- index = pos_count + keyword_only_count
2220
+ index = positional_count + keyword_only_count
2188
2221
if func_code .co_flags & CO_VARARGS :
2189
2222
index += 1
2190
2223
0 commit comments