@@ -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,26 +1032,20 @@ 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 )
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
-
1044
1035
if not iscode (co ):
1045
1036
raise TypeError ('{!r} is not a code object' .format (co ))
1046
1037
1047
- nargs = co .co_argcount
1048
1038
names = co .co_varnames
1039
+ nargs = co .co_argcount
1040
+ nposonlyargs = co .co_posonlyargcount
1049
1041
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 ])
1052
1046
step = 0
1053
1047
1048
+ nargs += nposonlyargs
1054
1049
nargs += nkwargs
1055
1050
varargs = None
1056
1051
if co .co_flags & CO_VARARGS :
@@ -1059,8 +1054,7 @@ def _getfullargs(co):
1059
1054
varkw = None
1060
1055
if co .co_flags & CO_VARKEYWORDS :
1061
1056
varkw = co .co_varnames [nargs ]
1062
- return args , varargs , kwonlyargs , varkw
1063
-
1057
+ return Arguments (posonlyargs + args + kwonlyargs , varargs , varkw )
1064
1058
1065
1059
ArgSpec = namedtuple ('ArgSpec' , 'args varargs keywords defaults' )
1066
1060
@@ -1087,15 +1081,16 @@ def getargspec(func):
1087
1081
warnings .warn ("inspect.getargspec() is deprecated since Python 3.0, "
1088
1082
"use inspect.signature() or inspect.getfullargspec()" ,
1089
1083
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" )
1095
1090
return ArgSpec (args , varargs , varkw , defaults )
1096
1091
1097
1092
FullArgSpec = namedtuple ('FullArgSpec' ,
1098
- 'args, varargs, varkw, defaults, kwonlyargs, kwonlydefaults, annotations' )
1093
+ 'args, varargs, varkw, defaults, posonlyargs, kwonlyargs, kwonlydefaults, annotations' )
1099
1094
1100
1095
def getfullargspec (func ):
1101
1096
"""Get the names and default values of a callable object's parameters.
@@ -1145,6 +1140,7 @@ def getfullargspec(func):
1145
1140
args = []
1146
1141
varargs = None
1147
1142
varkw = None
1143
+ posonlyargs = []
1148
1144
kwonlyargs = []
1149
1145
defaults = ()
1150
1146
annotations = {}
@@ -1159,7 +1155,9 @@ def getfullargspec(func):
1159
1155
name = param .name
1160
1156
1161
1157
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 ,)
1163
1161
elif kind is _POSITIONAL_OR_KEYWORD :
1164
1162
args .append (name )
1165
1163
if param .default is not param .empty :
@@ -1185,7 +1183,7 @@ def getfullargspec(func):
1185
1183
defaults = None
1186
1184
1187
1185
return FullArgSpec (args , varargs , varkw , defaults ,
1188
- kwonlyargs , kwdefaults , annotations )
1186
+ posonlyargs , kwonlyargs , kwdefaults , annotations )
1189
1187
1190
1188
1191
1189
ArgInfo = namedtuple ('ArgInfo' , 'args varargs keywords locals' )
@@ -1216,7 +1214,8 @@ def _formatannotation(annotation):
1216
1214
return _formatannotation
1217
1215
1218
1216
def formatargspec (args , varargs = None , varkw = None , defaults = None ,
1219
- kwonlyargs = (), kwonlydefaults = {}, annotations = {},
1217
+ posonlyargs = (), kwonlyargs = (), kwonlydefaults = {},
1218
+ annotations = {},
1220
1219
formatarg = str ,
1221
1220
formatvarargs = lambda name : '*' + name ,
1222
1221
formatvarkw = lambda name : '**' + name ,
@@ -1249,12 +1248,17 @@ def formatargandannotation(arg):
1249
1248
return result
1250
1249
specs = []
1251
1250
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 ]):
1254
1254
spec = formatargandannotation (arg )
1255
1255
if defaults and i >= firstdefault :
1256
1256
spec = spec + formatvalue (defaults [i - firstdefault ])
1257
1257
specs .append (spec )
1258
+ posonly_left -= 1
1259
+ if posonlyargs and posonly_left == 0 :
1260
+ specs .append ('/' )
1261
+
1258
1262
if varargs is not None :
1259
1263
specs .append (formatvarargs (formatargandannotation (varargs )))
1260
1264
else :
@@ -1342,7 +1346,8 @@ def getcallargs(*func_and_positional, **named):
1342
1346
func = func_and_positional [0 ]
1343
1347
positional = func_and_positional [1 :]
1344
1348
spec = getfullargspec (func )
1345
- args , varargs , varkw , defaults , kwonlyargs , kwonlydefaults , ann = spec
1349
+ (args , varargs , varkw , defaults , posonlyargs ,
1350
+ kwonlyargs , kwonlydefaults , ann ) = spec
1346
1351
f_name = func .__name__
1347
1352
arg2value = {}
1348
1353
@@ -1351,12 +1356,16 @@ def getcallargs(*func_and_positional, **named):
1351
1356
# implicit 'self' (or 'cls' for classmethods) argument
1352
1357
positional = (func .__self__ ,) + positional
1353
1358
num_pos = len (positional )
1359
+ num_posonlyargs = len (posonlyargs )
1354
1360
num_args = len (args )
1355
1361
num_defaults = len (defaults ) if defaults else 0
1356
1362
1363
+ n = min (num_pos , num_posonlyargs )
1364
+ for i in range (num_posonlyargs ):
1365
+ arg2value [posonlyargs [i ]] = positional [i ]
1357
1366
n = min (num_pos , num_args )
1358
1367
for i in range (n ):
1359
- arg2value [args [i ]] = positional [i ]
1368
+ arg2value [args [i ]] = positional [num_posonlyargs + i ]
1360
1369
if varargs :
1361
1370
arg2value [varargs ] = tuple (positional [n :])
1362
1371
possible_kwargs = set (args + kwonlyargs )
@@ -2137,9 +2146,12 @@ def _signature_from_function(cls, func):
2137
2146
func_code = func .__code__
2138
2147
pos_count = func_code .co_argcount
2139
2148
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 ])
2141
2153
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 )]
2143
2155
annotations = func .__annotations__
2144
2156
defaults = func .__defaults__
2145
2157
kwdefaults = func .__kwdefaults__
@@ -2151,23 +2163,33 @@ def _signature_from_function(cls, func):
2151
2163
2152
2164
parameters = []
2153
2165
2166
+ non_default_count = positional_count - pos_default_count
2167
+ all_positional = positional_only + positional
2168
+
2169
+ posonly_left = posonly_count
2170
+
2154
2171
# 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
2157
2174
annotation = annotations .get (name , _empty )
2158
2175
parameters .append (Parameter (name , annotation = annotation ,
2159
- kind = _POSITIONAL_OR_KEYWORD ))
2176
+ kind = kind ))
2177
+ if posonly_left :
2178
+ posonly_left -= 1
2160
2179
2161
2180
# ... 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
2163
2183
annotation = annotations .get (name , _empty )
2164
2184
parameters .append (Parameter (name , annotation = annotation ,
2165
- kind = _POSITIONAL_OR_KEYWORD ,
2185
+ kind = kind ,
2166
2186
default = defaults [offset ]))
2187
+ if posonly_left :
2188
+ posonly_left -= 1
2167
2189
2168
2190
# *args
2169
2191
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 ]
2171
2193
annotation = annotations .get (name , _empty )
2172
2194
parameters .append (Parameter (name , annotation = annotation ,
2173
2195
kind = _VAR_POSITIONAL ))
@@ -2184,7 +2206,7 @@ def _signature_from_function(cls, func):
2184
2206
default = default ))
2185
2207
# **kwargs
2186
2208
if func_code .co_flags & CO_VARKEYWORDS :
2187
- index = pos_count + keyword_only_count
2209
+ index = positional_count + keyword_only_count
2188
2210
if func_code .co_flags & CO_VARARGS :
2189
2211
index += 1
2190
2212
0 commit comments