bpo-37122: Make co->co_argcount represent the total number of positonal arguments in the code object (GH-13726)
This commit is contained in:
parent
059b9ea5ac
commit
cd74e66a8c
|
@ -42,6 +42,8 @@ bound into a function.
|
||||||
|
|
||||||
.. versionchanged:: 3.8
|
.. versionchanged:: 3.8
|
||||||
An extra parameter is required (*posonlyargcount*) to support :PEP:`570`.
|
An extra parameter is required (*posonlyargcount*) to support :PEP:`570`.
|
||||||
|
The first parameter (*argcount*) now represents the total number of positional arguments,
|
||||||
|
including positional-only.
|
||||||
|
|
||||||
.. audit-event:: code.__new__ "code filename name argcount kwonlyargcount nlocals stacksize flags"
|
.. audit-event:: code.__new__ "code filename name argcount kwonlyargcount nlocals stacksize flags"
|
||||||
|
|
||||||
|
|
|
@ -907,24 +907,26 @@ Internal types
|
||||||
single: co_freevars (code object attribute)
|
single: co_freevars (code object attribute)
|
||||||
|
|
||||||
Special read-only attributes: :attr:`co_name` gives the function name;
|
Special read-only attributes: :attr:`co_name` gives the function name;
|
||||||
:attr:`co_argcount` is the number of positional arguments (including arguments
|
:attr:`co_argcount` is the total number of positional arguments
|
||||||
with default values); :attr:`co_posonlyargcount` is the number of
|
(including positional-only arguments and arguments with default values);
|
||||||
positional-only arguments (including arguments with default values);
|
:attr:`co_posonlyargcount` is the number of positional-only arguments
|
||||||
:attr:`co_kwonlyargcount` is the number of keyword-only arguments (including
|
(including arguments with default values); :attr:`co_kwonlyargcount` is
|
||||||
arguments with default values); :attr:`co_nlocals` is the number of local
|
the number of keyword-only arguments (including arguments with default
|
||||||
variables used by the function (including arguments); :attr:`co_varnames` is a
|
values); :attr:`co_nlocals` is the number of local variables used by the
|
||||||
tuple containing the names of the local variables (starting with the argument
|
function (including arguments); :attr:`co_varnames` is a tuple containing
|
||||||
names); :attr:`co_cellvars` is a tuple containing the names of local variables
|
the names of the local variables (starting with the argument names);
|
||||||
|
:attr:`co_cellvars` is a tuple containing the names of local variables
|
||||||
that are referenced by nested functions; :attr:`co_freevars` is a tuple
|
that are referenced by nested functions; :attr:`co_freevars` is a tuple
|
||||||
containing the names of free variables; :attr:`co_code` is a string representing
|
containing the names of free variables; :attr:`co_code` is a string
|
||||||
the sequence of bytecode instructions; :attr:`co_consts` is a tuple containing
|
representing the sequence of bytecode instructions; :attr:`co_consts` is
|
||||||
the literals used by the bytecode; :attr:`co_names` is a tuple containing the
|
a tuple containing the literals used by the bytecode; :attr:`co_names` is
|
||||||
names used by the bytecode; :attr:`co_filename` is the filename from which the
|
a tuple containing the names used by the bytecode; :attr:`co_filename` is
|
||||||
code was compiled; :attr:`co_firstlineno` is the first line number of the
|
the filename from which the code was compiled; :attr:`co_firstlineno` is
|
||||||
function; :attr:`co_lnotab` is a string encoding the mapping from bytecode
|
the first line number of the function; :attr:`co_lnotab` is a string
|
||||||
offsets to line numbers (for details see the source code of the interpreter);
|
encoding the mapping from bytecode offsets to line numbers (for details
|
||||||
:attr:`co_stacksize` is the required stack size (including local variables);
|
see the source code of the interpreter); :attr:`co_stacksize` is the
|
||||||
:attr:`co_flags` is an integer encoding a number of flags for the interpreter.
|
required stack size (including local variables); :attr:`co_flags` is an
|
||||||
|
integer encoding a number of flags for the interpreter.
|
||||||
|
|
||||||
.. index:: object: generator
|
.. index:: object: generator
|
||||||
|
|
||||||
|
|
|
@ -1177,8 +1177,10 @@ Changes in the Python API
|
||||||
|
|
||||||
* :class:`types.CodeType` has a new parameter in the second position of the
|
* :class:`types.CodeType` has a new parameter in the second position of the
|
||||||
constructor (*posonlyargcount*) to support positional-only arguments defined
|
constructor (*posonlyargcount*) to support positional-only arguments defined
|
||||||
in :pep:`570`. A new ``replace()`` method of :class:`types.CodeType` can be
|
in :pep:`570`. The first argument (*argcount*) now represents the total
|
||||||
used to make the code future-proof.
|
number of positional arguments (including positional-only arguments). A new
|
||||||
|
``replace()`` method of :class:`types.CodeType` can be used to make the code
|
||||||
|
future-proof.
|
||||||
|
|
||||||
|
|
||||||
Changes in the C API
|
Changes in the C API
|
||||||
|
|
|
@ -1037,15 +1037,11 @@ def getargs(co):
|
||||||
|
|
||||||
names = co.co_varnames
|
names = co.co_varnames
|
||||||
nargs = co.co_argcount
|
nargs = co.co_argcount
|
||||||
nposonlyargs = co.co_posonlyargcount
|
|
||||||
nkwargs = co.co_kwonlyargcount
|
nkwargs = co.co_kwonlyargcount
|
||||||
nposargs = nargs + nposonlyargs
|
args = list(names[:nargs])
|
||||||
posonlyargs = list(names[:nposonlyargs])
|
kwonlyargs = list(names[nargs:nargs+nkwargs])
|
||||||
args = list(names[nposonlyargs:nposonlyargs+nargs])
|
|
||||||
kwonlyargs = list(names[nposargs:nposargs+nkwargs])
|
|
||||||
step = 0
|
step = 0
|
||||||
|
|
||||||
nargs += nposonlyargs
|
|
||||||
nargs += nkwargs
|
nargs += nkwargs
|
||||||
varargs = None
|
varargs = None
|
||||||
if co.co_flags & CO_VARARGS:
|
if co.co_flags & CO_VARARGS:
|
||||||
|
@ -1054,7 +1050,7 @@ def getargs(co):
|
||||||
varkw = None
|
varkw = None
|
||||||
if co.co_flags & CO_VARKEYWORDS:
|
if co.co_flags & CO_VARKEYWORDS:
|
||||||
varkw = co.co_varnames[nargs]
|
varkw = co.co_varnames[nargs]
|
||||||
return Arguments(posonlyargs + args + kwonlyargs, varargs, varkw)
|
return Arguments(args + kwonlyargs, varargs, varkw)
|
||||||
|
|
||||||
ArgSpec = namedtuple('ArgSpec', 'args varargs keywords defaults')
|
ArgSpec = namedtuple('ArgSpec', 'args varargs keywords defaults')
|
||||||
|
|
||||||
|
@ -2136,11 +2132,9 @@ def _signature_from_function(cls, func, skip_bound_arg=True):
|
||||||
pos_count = func_code.co_argcount
|
pos_count = func_code.co_argcount
|
||||||
arg_names = func_code.co_varnames
|
arg_names = func_code.co_varnames
|
||||||
posonly_count = func_code.co_posonlyargcount
|
posonly_count = func_code.co_posonlyargcount
|
||||||
positional_count = posonly_count + pos_count
|
positional = arg_names[:pos_count]
|
||||||
positional_only = tuple(arg_names[:posonly_count])
|
|
||||||
positional = tuple(arg_names[posonly_count:positional_count])
|
|
||||||
keyword_only_count = func_code.co_kwonlyargcount
|
keyword_only_count = func_code.co_kwonlyargcount
|
||||||
keyword_only = arg_names[positional_count:(positional_count + keyword_only_count)]
|
keyword_only = arg_names[pos_count:pos_count + keyword_only_count]
|
||||||
annotations = func.__annotations__
|
annotations = func.__annotations__
|
||||||
defaults = func.__defaults__
|
defaults = func.__defaults__
|
||||||
kwdefaults = func.__kwdefaults__
|
kwdefaults = func.__kwdefaults__
|
||||||
|
@ -2152,13 +2146,11 @@ def _signature_from_function(cls, func, skip_bound_arg=True):
|
||||||
|
|
||||||
parameters = []
|
parameters = []
|
||||||
|
|
||||||
non_default_count = positional_count - pos_default_count
|
non_default_count = pos_count - pos_default_count
|
||||||
all_positional = positional_only + positional
|
|
||||||
|
|
||||||
posonly_left = posonly_count
|
posonly_left = posonly_count
|
||||||
|
|
||||||
# Non-keyword-only parameters w/o defaults.
|
# Non-keyword-only parameters w/o defaults.
|
||||||
for name in all_positional[:non_default_count]:
|
for name in positional[:non_default_count]:
|
||||||
kind = _POSITIONAL_ONLY if posonly_left else _POSITIONAL_OR_KEYWORD
|
kind = _POSITIONAL_ONLY if posonly_left else _POSITIONAL_OR_KEYWORD
|
||||||
annotation = annotations.get(name, _empty)
|
annotation = annotations.get(name, _empty)
|
||||||
parameters.append(Parameter(name, annotation=annotation,
|
parameters.append(Parameter(name, annotation=annotation,
|
||||||
|
@ -2167,7 +2159,7 @@ def _signature_from_function(cls, func, skip_bound_arg=True):
|
||||||
posonly_left -= 1
|
posonly_left -= 1
|
||||||
|
|
||||||
# ... w/ defaults.
|
# ... w/ defaults.
|
||||||
for offset, name in enumerate(all_positional[non_default_count:]):
|
for offset, name in enumerate(positional[non_default_count:]):
|
||||||
kind = _POSITIONAL_ONLY if posonly_left else _POSITIONAL_OR_KEYWORD
|
kind = _POSITIONAL_ONLY if posonly_left else _POSITIONAL_OR_KEYWORD
|
||||||
annotation = annotations.get(name, _empty)
|
annotation = annotations.get(name, _empty)
|
||||||
parameters.append(Parameter(name, annotation=annotation,
|
parameters.append(Parameter(name, annotation=annotation,
|
||||||
|
@ -2178,7 +2170,7 @@ def _signature_from_function(cls, func, skip_bound_arg=True):
|
||||||
|
|
||||||
# *args
|
# *args
|
||||||
if func_code.co_flags & CO_VARARGS:
|
if func_code.co_flags & CO_VARARGS:
|
||||||
name = arg_names[positional_count + keyword_only_count]
|
name = arg_names[pos_count + keyword_only_count]
|
||||||
annotation = annotations.get(name, _empty)
|
annotation = annotations.get(name, _empty)
|
||||||
parameters.append(Parameter(name, annotation=annotation,
|
parameters.append(Parameter(name, annotation=annotation,
|
||||||
kind=_VAR_POSITIONAL))
|
kind=_VAR_POSITIONAL))
|
||||||
|
@ -2195,7 +2187,7 @@ def _signature_from_function(cls, func, skip_bound_arg=True):
|
||||||
default=default))
|
default=default))
|
||||||
# **kwargs
|
# **kwargs
|
||||||
if func_code.co_flags & CO_VARKEYWORDS:
|
if func_code.co_flags & CO_VARKEYWORDS:
|
||||||
index = positional_count + keyword_only_count
|
index = pos_count + keyword_only_count
|
||||||
if func_code.co_flags & CO_VARARGS:
|
if func_code.co_flags & CO_VARARGS:
|
||||||
index += 1
|
index += 1
|
||||||
|
|
||||||
|
|
|
@ -1132,7 +1132,7 @@ class Pdb(bdb.Bdb, cmd.Cmd):
|
||||||
"""
|
"""
|
||||||
co = self.curframe.f_code
|
co = self.curframe.f_code
|
||||||
dict = self.curframe_locals
|
dict = self.curframe_locals
|
||||||
n = co.co_argcount + co.co_posonlyargcount + co.co_kwonlyargcount
|
n = co.co_argcount + co.co_kwonlyargcount
|
||||||
if co.co_flags & inspect.CO_VARARGS: n = n+1
|
if co.co_flags & inspect.CO_VARARGS: n = n+1
|
||||||
if co.co_flags & inspect.CO_VARKEYWORDS: n = n+1
|
if co.co_flags & inspect.CO_VARKEYWORDS: n = n+1
|
||||||
for i in range(n):
|
for i in range(n):
|
||||||
|
|
|
@ -112,7 +112,7 @@ consts: ('None',)
|
||||||
|
|
||||||
>>> dump(posonly_args.__code__)
|
>>> dump(posonly_args.__code__)
|
||||||
name: posonly_args
|
name: posonly_args
|
||||||
argcount: 1
|
argcount: 3
|
||||||
posonlyargcount: 2
|
posonlyargcount: 2
|
||||||
kwonlyargcount: 0
|
kwonlyargcount: 0
|
||||||
names: ()
|
names: ()
|
||||||
|
|
|
@ -640,7 +640,7 @@ def tricky(a, b, /, x, y, z=True, *args, c, d, e=[], **kwds):
|
||||||
code_info_tricky = """\
|
code_info_tricky = """\
|
||||||
Name: tricky
|
Name: tricky
|
||||||
Filename: (.*)
|
Filename: (.*)
|
||||||
Argument count: 3
|
Argument count: 5
|
||||||
Positional-only arguments: 2
|
Positional-only arguments: 2
|
||||||
Kw-only arguments: 3
|
Kw-only arguments: 3
|
||||||
Number of locals: 10
|
Number of locals: 10
|
||||||
|
|
|
@ -100,14 +100,14 @@ class PositionalOnlyTestCase(unittest.TestCase):
|
||||||
def f(a, b, c, /, d, e=1, *, f, g=2):
|
def f(a, b, c, /, d, e=1, *, f, g=2):
|
||||||
pass
|
pass
|
||||||
|
|
||||||
self.assertEqual(2, f.__code__.co_argcount) # 2 "standard args"
|
self.assertEqual(5, f.__code__.co_argcount) # 3 posonly + 2 "standard args"
|
||||||
self.assertEqual(3, f.__code__.co_posonlyargcount)
|
self.assertEqual(3, f.__code__.co_posonlyargcount)
|
||||||
self.assertEqual((1,), f.__defaults__)
|
self.assertEqual((1,), f.__defaults__)
|
||||||
|
|
||||||
def f(a, b, c=1, /, d=2, e=3, *, f, g=4):
|
def f(a, b, c=1, /, d=2, e=3, *, f, g=4):
|
||||||
pass
|
pass
|
||||||
|
|
||||||
self.assertEqual(2, f.__code__.co_argcount) # 2 "standard args"
|
self.assertEqual(5, f.__code__.co_argcount) # 3 posonly + 2 "standard args"
|
||||||
self.assertEqual(3, f.__code__.co_posonlyargcount)
|
self.assertEqual(3, f.__code__.co_posonlyargcount)
|
||||||
self.assertEqual((1, 2, 3), f.__defaults__)
|
self.assertEqual((1, 2, 3), f.__defaults__)
|
||||||
|
|
||||||
|
|
|
@ -0,0 +1,5 @@
|
||||||
|
Make the *co_argcount* attribute of code objects represent the total number
|
||||||
|
of positional arguments (including positional-only arguments). The value of
|
||||||
|
*co_posonlyargcount* can be used to distinguish which arguments are
|
||||||
|
positional only, and the difference (*co_argcount* - *co_posonlyargcount*)
|
||||||
|
is the number of positional-or-keyword arguments. Patch by Pablo Galindo.
|
|
@ -308,11 +308,11 @@ _PyFunction_FastCallDict(PyObject *func, PyObject *const *args, Py_ssize_t nargs
|
||||||
(co->co_flags & ~PyCF_MASK) == (CO_OPTIMIZED | CO_NEWLOCALS | CO_NOFREE))
|
(co->co_flags & ~PyCF_MASK) == (CO_OPTIMIZED | CO_NEWLOCALS | CO_NOFREE))
|
||||||
{
|
{
|
||||||
/* Fast paths */
|
/* Fast paths */
|
||||||
if (argdefs == NULL && co->co_argcount + co->co_posonlyargcount == nargs) {
|
if (argdefs == NULL && co->co_argcount == nargs) {
|
||||||
return function_code_fastcall(co, args, nargs, globals);
|
return function_code_fastcall(co, args, nargs, globals);
|
||||||
}
|
}
|
||||||
else if (nargs == 0 && argdefs != NULL
|
else if (nargs == 0 && argdefs != NULL
|
||||||
&& co->co_argcount + co->co_posonlyargcount == PyTuple_GET_SIZE(argdefs)) {
|
&& co->co_argcount == PyTuple_GET_SIZE(argdefs)) {
|
||||||
/* function called with no arguments, but all parameters have
|
/* function called with no arguments, but all parameters have
|
||||||
a default value: use default values as arguments .*/
|
a default value: use default values as arguments .*/
|
||||||
args = _PyTuple_ITEMS(argdefs);
|
args = _PyTuple_ITEMS(argdefs);
|
||||||
|
@ -396,11 +396,11 @@ _PyFunction_Vectorcall(PyObject *func, PyObject* const* stack,
|
||||||
if (co->co_kwonlyargcount == 0 && nkwargs == 0 &&
|
if (co->co_kwonlyargcount == 0 && nkwargs == 0 &&
|
||||||
(co->co_flags & ~PyCF_MASK) == (CO_OPTIMIZED | CO_NEWLOCALS | CO_NOFREE))
|
(co->co_flags & ~PyCF_MASK) == (CO_OPTIMIZED | CO_NEWLOCALS | CO_NOFREE))
|
||||||
{
|
{
|
||||||
if (argdefs == NULL && co->co_argcount + co->co_posonlyargcount== nargs) {
|
if (argdefs == NULL && co->co_argcount == nargs) {
|
||||||
return function_code_fastcall(co, stack, nargs, globals);
|
return function_code_fastcall(co, stack, nargs, globals);
|
||||||
}
|
}
|
||||||
else if (nargs == 0 && argdefs != NULL
|
else if (nargs == 0 && argdefs != NULL
|
||||||
&& co->co_argcount + co->co_posonlyargcount == PyTuple_GET_SIZE(argdefs)) {
|
&& co->co_argcount == PyTuple_GET_SIZE(argdefs)) {
|
||||||
/* function called with no arguments, but all parameters have
|
/* function called with no arguments, but all parameters have
|
||||||
a default value: use default values as arguments .*/
|
a default value: use default values as arguments .*/
|
||||||
stack = _PyTuple_ITEMS(argdefs);
|
stack = _PyTuple_ITEMS(argdefs);
|
||||||
|
|
|
@ -114,8 +114,9 @@ PyCode_New(int argcount, int posonlyargcount, int kwonlyargcount,
|
||||||
Py_ssize_t i, n_cellvars, n_varnames, total_args;
|
Py_ssize_t i, n_cellvars, n_varnames, total_args;
|
||||||
|
|
||||||
/* Check argument types */
|
/* Check argument types */
|
||||||
if (argcount < 0 || posonlyargcount < 0 || kwonlyargcount < 0 ||
|
if (argcount < posonlyargcount || posonlyargcount < 0 ||
|
||||||
nlocals < 0 || stacksize < 0 || flags < 0 ||
|
kwonlyargcount < 0 || nlocals < 0 ||
|
||||||
|
stacksize < 0 || flags < 0 ||
|
||||||
code == NULL || !PyBytes_Check(code) ||
|
code == NULL || !PyBytes_Check(code) ||
|
||||||
consts == NULL || !PyTuple_Check(consts) ||
|
consts == NULL || !PyTuple_Check(consts) ||
|
||||||
names == NULL || !PyTuple_Check(names) ||
|
names == NULL || !PyTuple_Check(names) ||
|
||||||
|
@ -152,11 +153,9 @@ PyCode_New(int argcount, int posonlyargcount, int kwonlyargcount,
|
||||||
}
|
}
|
||||||
|
|
||||||
n_varnames = PyTuple_GET_SIZE(varnames);
|
n_varnames = PyTuple_GET_SIZE(varnames);
|
||||||
if (posonlyargcount + argcount <= n_varnames
|
if (argcount <= n_varnames && kwonlyargcount <= n_varnames) {
|
||||||
&& kwonlyargcount <= n_varnames) {
|
|
||||||
/* Never overflows. */
|
/* Never overflows. */
|
||||||
total_args = (Py_ssize_t)posonlyargcount + (Py_ssize_t)argcount
|
total_args = (Py_ssize_t)argcount + (Py_ssize_t)kwonlyargcount +
|
||||||
+ (Py_ssize_t)kwonlyargcount +
|
|
||||||
((flags & CO_VARARGS) != 0) + ((flags & CO_VARKEYWORDS) != 0);
|
((flags & CO_VARARGS) != 0) + ((flags & CO_VARKEYWORDS) != 0);
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
|
|
|
@ -7807,7 +7807,7 @@ super_init(PyObject *self, PyObject *args, PyObject *kwds)
|
||||||
"super(): no code object");
|
"super(): no code object");
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
if (co->co_posonlyargcount + co->co_argcount == 0) {
|
if (co->co_argcount == 0) {
|
||||||
PyErr_SetString(PyExc_RuntimeError,
|
PyErr_SetString(PyExc_RuntimeError,
|
||||||
"super(): no arguments");
|
"super(): no arguments");
|
||||||
return -1;
|
return -1;
|
||||||
|
|
|
@ -3757,10 +3757,10 @@ missing_arguments(PyThreadState *tstate, PyCodeObject *co,
|
||||||
return;
|
return;
|
||||||
if (positional) {
|
if (positional) {
|
||||||
start = 0;
|
start = 0;
|
||||||
end = co->co_posonlyargcount + co->co_argcount - defcount;
|
end = co->co_argcount - defcount;
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
start = co->co_posonlyargcount + co->co_argcount;
|
start = co->co_argcount;
|
||||||
end = start + co->co_kwonlyargcount;
|
end = start + co->co_kwonlyargcount;
|
||||||
}
|
}
|
||||||
for (i = start; i < end; i++) {
|
for (i = start; i < end; i++) {
|
||||||
|
@ -3788,25 +3788,23 @@ too_many_positional(PyThreadState *tstate, PyCodeObject *co,
|
||||||
Py_ssize_t kwonly_given = 0;
|
Py_ssize_t kwonly_given = 0;
|
||||||
Py_ssize_t i;
|
Py_ssize_t i;
|
||||||
PyObject *sig, *kwonly_sig;
|
PyObject *sig, *kwonly_sig;
|
||||||
Py_ssize_t co_posonlyargcount = co->co_posonlyargcount;
|
|
||||||
Py_ssize_t co_argcount = co->co_argcount;
|
Py_ssize_t co_argcount = co->co_argcount;
|
||||||
Py_ssize_t total_positional = co_argcount + co_posonlyargcount;
|
|
||||||
|
|
||||||
assert((co->co_flags & CO_VARARGS) == 0);
|
assert((co->co_flags & CO_VARARGS) == 0);
|
||||||
/* Count missing keyword-only args. */
|
/* Count missing keyword-only args. */
|
||||||
for (i = total_positional; i < total_positional + co->co_kwonlyargcount; i++) {
|
for (i = co_argcount; i < co_argcount + co->co_kwonlyargcount; i++) {
|
||||||
if (GETLOCAL(i) != NULL) {
|
if (GETLOCAL(i) != NULL) {
|
||||||
kwonly_given++;
|
kwonly_given++;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (defcount) {
|
if (defcount) {
|
||||||
Py_ssize_t atleast = total_positional - defcount;
|
Py_ssize_t atleast = co_argcount - defcount;
|
||||||
plural = 1;
|
plural = 1;
|
||||||
sig = PyUnicode_FromFormat("from %zd to %zd", atleast, total_positional);
|
sig = PyUnicode_FromFormat("from %zd to %zd", atleast, co_argcount);
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
plural = (total_positional != 1);
|
plural = (co_argcount != 1);
|
||||||
sig = PyUnicode_FromFormat("%zd", total_positional);
|
sig = PyUnicode_FromFormat("%zd", co_argcount);
|
||||||
}
|
}
|
||||||
if (sig == NULL)
|
if (sig == NULL)
|
||||||
return;
|
return;
|
||||||
|
@ -3917,7 +3915,7 @@ _PyEval_EvalCodeWithName(PyObject *_co, PyObject *globals, PyObject *locals,
|
||||||
PyObject *retval = NULL;
|
PyObject *retval = NULL;
|
||||||
PyObject **fastlocals, **freevars;
|
PyObject **fastlocals, **freevars;
|
||||||
PyObject *x, *u;
|
PyObject *x, *u;
|
||||||
const Py_ssize_t total_args = co->co_argcount + co->co_kwonlyargcount + co->co_posonlyargcount;
|
const Py_ssize_t total_args = co->co_argcount + co->co_kwonlyargcount;
|
||||||
Py_ssize_t i, j, n;
|
Py_ssize_t i, j, n;
|
||||||
PyObject *kwdict;
|
PyObject *kwdict;
|
||||||
|
|
||||||
|
@ -3953,9 +3951,9 @@ _PyEval_EvalCodeWithName(PyObject *_co, PyObject *globals, PyObject *locals,
|
||||||
kwdict = NULL;
|
kwdict = NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Copy positional only arguments into local variables */
|
/* Copy all positional arguments into local variables */
|
||||||
if (argcount > co->co_argcount + co->co_posonlyargcount) {
|
if (argcount > co->co_argcount) {
|
||||||
n = co->co_posonlyargcount;
|
n = co->co_argcount;
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
n = argcount;
|
n = argcount;
|
||||||
|
@ -3966,20 +3964,6 @@ _PyEval_EvalCodeWithName(PyObject *_co, PyObject *globals, PyObject *locals,
|
||||||
SETLOCAL(j, x);
|
SETLOCAL(j, x);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/* Copy positional arguments into local variables */
|
|
||||||
if (argcount > co->co_argcount + co->co_posonlyargcount) {
|
|
||||||
n += co->co_argcount;
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
n = argcount;
|
|
||||||
}
|
|
||||||
for (i = j; i < n; i++) {
|
|
||||||
x = args[i];
|
|
||||||
Py_INCREF(x);
|
|
||||||
SETLOCAL(i, x);
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Pack other positional arguments into the *args argument */
|
/* Pack other positional arguments into the *args argument */
|
||||||
if (co->co_flags & CO_VARARGS) {
|
if (co->co_flags & CO_VARARGS) {
|
||||||
u = _PyTuple_FromArray(args + n, argcount - n);
|
u = _PyTuple_FromArray(args + n, argcount - n);
|
||||||
|
@ -4059,14 +4043,14 @@ _PyEval_EvalCodeWithName(PyObject *_co, PyObject *globals, PyObject *locals,
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Check the number of positional arguments */
|
/* Check the number of positional arguments */
|
||||||
if ((argcount > co->co_argcount + co->co_posonlyargcount) && !(co->co_flags & CO_VARARGS)) {
|
if ((argcount > co->co_argcount) && !(co->co_flags & CO_VARARGS)) {
|
||||||
too_many_positional(tstate, co, argcount, defcount, fastlocals);
|
too_many_positional(tstate, co, argcount, defcount, fastlocals);
|
||||||
goto fail;
|
goto fail;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Add missing positional arguments (copy default values from defs) */
|
/* Add missing positional arguments (copy default values from defs) */
|
||||||
if (argcount < co->co_posonlyargcount + co->co_argcount) {
|
if (argcount < co->co_argcount) {
|
||||||
Py_ssize_t m = co->co_posonlyargcount + co->co_argcount - defcount;
|
Py_ssize_t m = co->co_argcount - defcount;
|
||||||
Py_ssize_t missing = 0;
|
Py_ssize_t missing = 0;
|
||||||
for (i = argcount; i < m; i++) {
|
for (i = argcount; i < m; i++) {
|
||||||
if (GETLOCAL(i) == NULL) {
|
if (GETLOCAL(i) == NULL) {
|
||||||
|
@ -4093,7 +4077,7 @@ _PyEval_EvalCodeWithName(PyObject *_co, PyObject *globals, PyObject *locals,
|
||||||
/* Add missing keyword arguments (copy default values from kwdefs) */
|
/* Add missing keyword arguments (copy default values from kwdefs) */
|
||||||
if (co->co_kwonlyargcount > 0) {
|
if (co->co_kwonlyargcount > 0) {
|
||||||
Py_ssize_t missing = 0;
|
Py_ssize_t missing = 0;
|
||||||
for (i = co->co_posonlyargcount + co->co_argcount; i < total_args; i++) {
|
for (i = co->co_argcount; i < total_args; i++) {
|
||||||
PyObject *name;
|
PyObject *name;
|
||||||
if (GETLOCAL(i) != NULL)
|
if (GETLOCAL(i) != NULL)
|
||||||
continue;
|
continue;
|
||||||
|
|
|
@ -5764,7 +5764,7 @@ makecode(struct compiler *c, struct assembler *a)
|
||||||
Py_ssize_t nlocals;
|
Py_ssize_t nlocals;
|
||||||
int nlocals_int;
|
int nlocals_int;
|
||||||
int flags;
|
int flags;
|
||||||
int argcount, posonlyargcount, kwonlyargcount, maxdepth;
|
int posorkeywordargcount, posonlyargcount, kwonlyargcount, maxdepth;
|
||||||
|
|
||||||
consts = consts_dict_keys_inorder(c->u->u_consts);
|
consts = consts_dict_keys_inorder(c->u->u_consts);
|
||||||
names = dict_keys_inorder(c->u->u_names, 0);
|
names = dict_keys_inorder(c->u->u_names, 0);
|
||||||
|
@ -5808,15 +5808,15 @@ makecode(struct compiler *c, struct assembler *a)
|
||||||
goto error;
|
goto error;
|
||||||
}
|
}
|
||||||
|
|
||||||
argcount = Py_SAFE_DOWNCAST(c->u->u_argcount, Py_ssize_t, int);
|
|
||||||
posonlyargcount = Py_SAFE_DOWNCAST(c->u->u_posonlyargcount, Py_ssize_t, int);
|
posonlyargcount = Py_SAFE_DOWNCAST(c->u->u_posonlyargcount, Py_ssize_t, int);
|
||||||
|
posorkeywordargcount = Py_SAFE_DOWNCAST(c->u->u_argcount, Py_ssize_t, int);
|
||||||
kwonlyargcount = Py_SAFE_DOWNCAST(c->u->u_kwonlyargcount, Py_ssize_t, int);
|
kwonlyargcount = Py_SAFE_DOWNCAST(c->u->u_kwonlyargcount, Py_ssize_t, int);
|
||||||
maxdepth = stackdepth(c);
|
maxdepth = stackdepth(c);
|
||||||
if (maxdepth < 0) {
|
if (maxdepth < 0) {
|
||||||
goto error;
|
goto error;
|
||||||
}
|
}
|
||||||
co = PyCode_New(argcount, posonlyargcount, kwonlyargcount,
|
co = PyCode_New(posonlyargcount+posorkeywordargcount, posonlyargcount,
|
||||||
nlocals_int, maxdepth, flags,
|
kwonlyargcount, nlocals_int, maxdepth, flags,
|
||||||
bytecode, consts, names, varnames,
|
bytecode, consts, names, varnames,
|
||||||
freevars, cellvars,
|
freevars, cellvars,
|
||||||
c->c_filename, c->u->u_name,
|
c->c_filename, c->u->u_name,
|
||||||
|
|
Loading…
Reference in New Issue