mirror of
https://github.com/python/cpython.git
synced 2025-08-31 14:07:50 +00:00
bpo-36540: PEP 570 -- Implementation (GH-12701)
This commit contains the implementation of PEP570: Python positional-only parameters. * Update Grammar/Grammar with new typedarglist and varargslist * Regenerate grammar files * Update and regenerate AST related files * Update code object * Update marshal.c * Update compiler and symtable * Regenerate importlib files * Update callable objects * Implement positional-only args logic in ceval.c * Regenerate frozen data * Update standard library to account for positional-only args * Add test file for positional-only args * Update other test files to account for positional-only args * Add News entry * Update inspect module and related tests
This commit is contained in:
parent
99fcc616d4
commit
8c77b8cb91
38 changed files with 5771 additions and 4710 deletions
50
Python/Python-ast.c
generated
50
Python/Python-ast.c
generated
|
@ -469,6 +469,7 @@ static char *ExceptHandler_fields[]={
|
|||
};
|
||||
static PyTypeObject *arguments_type;
|
||||
static PyObject* ast2obj_arguments(void*);
|
||||
_Py_IDENTIFIER(posonlyargs);
|
||||
_Py_IDENTIFIER(vararg);
|
||||
_Py_IDENTIFIER(kwonlyargs);
|
||||
_Py_IDENTIFIER(kw_defaults);
|
||||
|
@ -476,6 +477,7 @@ _Py_IDENTIFIER(kwarg);
|
|||
_Py_IDENTIFIER(defaults);
|
||||
static char *arguments_fields[]={
|
||||
"args",
|
||||
"posonlyargs",
|
||||
"vararg",
|
||||
"kwonlyargs",
|
||||
"kw_defaults",
|
||||
|
@ -1141,7 +1143,7 @@ static int init_types(void)
|
|||
ExceptHandler_type = make_type("ExceptHandler", excepthandler_type,
|
||||
ExceptHandler_fields, 3);
|
||||
if (!ExceptHandler_type) return 0;
|
||||
arguments_type = make_type("arguments", &AST_type, arguments_fields, 6);
|
||||
arguments_type = make_type("arguments", &AST_type, arguments_fields, 7);
|
||||
if (!arguments_type) return 0;
|
||||
if (!add_attributes(arguments_type, NULL, 0)) return 0;
|
||||
arg_type = make_type("arg", &AST_type, arg_fields, 3);
|
||||
|
@ -2569,14 +2571,16 @@ ExceptHandler(expr_ty type, identifier name, asdl_seq * body, int lineno, int
|
|||
}
|
||||
|
||||
arguments_ty
|
||||
arguments(asdl_seq * args, arg_ty vararg, asdl_seq * kwonlyargs, asdl_seq *
|
||||
kw_defaults, arg_ty kwarg, asdl_seq * defaults, PyArena *arena)
|
||||
arguments(asdl_seq * args, asdl_seq * posonlyargs, arg_ty vararg, asdl_seq *
|
||||
kwonlyargs, asdl_seq * kw_defaults, arg_ty kwarg, asdl_seq *
|
||||
defaults, PyArena *arena)
|
||||
{
|
||||
arguments_ty p;
|
||||
p = (arguments_ty)PyArena_Malloc(arena, sizeof(*p));
|
||||
if (!p)
|
||||
return NULL;
|
||||
p->args = args;
|
||||
p->posonlyargs = posonlyargs;
|
||||
p->vararg = vararg;
|
||||
p->kwonlyargs = kwonlyargs;
|
||||
p->kw_defaults = kw_defaults;
|
||||
|
@ -3954,6 +3958,11 @@ ast2obj_arguments(void* _o)
|
|||
if (_PyObject_SetAttrId(result, &PyId_args, value) == -1)
|
||||
goto failed;
|
||||
Py_DECREF(value);
|
||||
value = ast2obj_list(o->posonlyargs, ast2obj_arg);
|
||||
if (!value) goto failed;
|
||||
if (_PyObject_SetAttrId(result, &PyId_posonlyargs, value) == -1)
|
||||
goto failed;
|
||||
Py_DECREF(value);
|
||||
value = ast2obj_arg(o->vararg);
|
||||
if (!value) goto failed;
|
||||
if (_PyObject_SetAttrId(result, &PyId_vararg, value) == -1)
|
||||
|
@ -8267,6 +8276,7 @@ obj2ast_arguments(PyObject* obj, arguments_ty* out, PyArena* arena)
|
|||
{
|
||||
PyObject* tmp = NULL;
|
||||
asdl_seq* args;
|
||||
asdl_seq* posonlyargs;
|
||||
arg_ty vararg;
|
||||
asdl_seq* kwonlyargs;
|
||||
asdl_seq* kw_defaults;
|
||||
|
@ -8303,6 +8313,36 @@ obj2ast_arguments(PyObject* obj, arguments_ty* out, PyArena* arena)
|
|||
}
|
||||
Py_CLEAR(tmp);
|
||||
}
|
||||
if (_PyObject_LookupAttrId(obj, &PyId_posonlyargs, &tmp) < 0) {
|
||||
return 1;
|
||||
}
|
||||
if (tmp == NULL) {
|
||||
PyErr_SetString(PyExc_TypeError, "required field \"posonlyargs\" missing from arguments");
|
||||
return 1;
|
||||
}
|
||||
else {
|
||||
int res;
|
||||
Py_ssize_t len;
|
||||
Py_ssize_t i;
|
||||
if (!PyList_Check(tmp)) {
|
||||
PyErr_Format(PyExc_TypeError, "arguments field \"posonlyargs\" must be a list, not a %.200s", tmp->ob_type->tp_name);
|
||||
goto failed;
|
||||
}
|
||||
len = PyList_GET_SIZE(tmp);
|
||||
posonlyargs = _Py_asdl_seq_new(len, arena);
|
||||
if (posonlyargs == NULL) goto failed;
|
||||
for (i = 0; i < len; i++) {
|
||||
arg_ty val;
|
||||
res = obj2ast_arg(PyList_GET_ITEM(tmp, i), &val, arena);
|
||||
if (res != 0) goto failed;
|
||||
if (len != PyList_GET_SIZE(tmp)) {
|
||||
PyErr_SetString(PyExc_RuntimeError, "arguments field \"posonlyargs\" changed size during iteration");
|
||||
goto failed;
|
||||
}
|
||||
asdl_seq_SET(posonlyargs, i, val);
|
||||
}
|
||||
Py_CLEAR(tmp);
|
||||
}
|
||||
if (_PyObject_LookupAttrId(obj, &PyId_vararg, &tmp) < 0) {
|
||||
return 1;
|
||||
}
|
||||
|
@ -8419,8 +8459,8 @@ obj2ast_arguments(PyObject* obj, arguments_ty* out, PyArena* arena)
|
|||
}
|
||||
Py_CLEAR(tmp);
|
||||
}
|
||||
*out = arguments(args, vararg, kwonlyargs, kw_defaults, kwarg, defaults,
|
||||
arena);
|
||||
*out = arguments(args, posonlyargs, vararg, kwonlyargs, kw_defaults, kwarg,
|
||||
defaults, arena);
|
||||
return 0;
|
||||
failed:
|
||||
Py_XDECREF(tmp);
|
||||
|
|
100
Python/ast.c
100
Python/ast.c
|
@ -110,8 +110,9 @@ expr_context_name(expr_context_ty ctx)
|
|||
static int
|
||||
validate_arguments(arguments_ty args)
|
||||
{
|
||||
if (!validate_args(args->args))
|
||||
if (!validate_args(args->posonlyargs) || !validate_args(args->args)) {
|
||||
return 0;
|
||||
}
|
||||
if (args->vararg && args->vararg->annotation
|
||||
&& !validate_expr(args->vararg->annotation, Load)) {
|
||||
return 0;
|
||||
|
@ -1431,31 +1432,73 @@ ast_for_arguments(struct compiling *c, const node *n)
|
|||
and varargslist (lambda definition).
|
||||
|
||||
parameters: '(' [typedargslist] ')'
|
||||
typedargslist: (tfpdef ['=' test] (',' tfpdef ['=' test])* [',' [
|
||||
'*' [tfpdef] (',' tfpdef ['=' test])* [',' ['**' tfpdef [',']]]
|
||||
| '**' tfpdef [',']]]
|
||||
| '*' [tfpdef] (',' tfpdef ['=' test])* [',' ['**' tfpdef [',']]]
|
||||
| '**' tfpdef [','])
|
||||
|
||||
The following definition for typedarglist is equivalent to this set of rules:
|
||||
|
||||
arguments = argument (',' [TYPE_COMMENT] argument)*
|
||||
argument = tfpdef ['=' test]
|
||||
kwargs = '**' tfpdef [','] [TYPE_COMMENT]
|
||||
args = '*' [tfpdef]
|
||||
kwonly_kwargs = (',' [TYPE_COMMENT] argument)* (TYPE_COMMENT | [','
|
||||
[TYPE_COMMENT] [kwargs]])
|
||||
args_kwonly_kwargs = args kwonly_kwargs | kwargs
|
||||
poskeyword_args_kwonly_kwargs = arguments ( TYPE_COMMENT | [','
|
||||
[TYPE_COMMENT] [args_kwonly_kwargs]])
|
||||
typedargslist_no_posonly = poskeyword_args_kwonly_kwargs | args_kwonly_kwargs
|
||||
typedarglist = (arguments ',' [TYPE_COMMENT] '/' [',' [[TYPE_COMMENT]
|
||||
typedargslist_no_posonly]])|(typedargslist_no_posonly)"
|
||||
|
||||
typedargslist: ( (tfpdef ['=' test] (',' [TYPE_COMMENT] tfpdef ['=' test])*
|
||||
',' [TYPE_COMMENT] '/' [',' [ [TYPE_COMMENT] tfpdef ['=' test] ( ','
|
||||
[TYPE_COMMENT] tfpdef ['=' test])* (TYPE_COMMENT | [',' [TYPE_COMMENT] [ '*'
|
||||
[tfpdef] (',' [TYPE_COMMENT] tfpdef ['=' test])* (TYPE_COMMENT | [','
|
||||
[TYPE_COMMENT] ['**' tfpdef [','] [TYPE_COMMENT]]]) | '**' tfpdef [',']
|
||||
[TYPE_COMMENT]]]) | '*' [tfpdef] (',' [TYPE_COMMENT] tfpdef ['=' test])*
|
||||
(TYPE_COMMENT | [',' [TYPE_COMMENT] ['**' tfpdef [','] [TYPE_COMMENT]]]) |
|
||||
'**' tfpdef [','] [TYPE_COMMENT]]] ) | (tfpdef ['=' test] (','
|
||||
[TYPE_COMMENT] tfpdef ['=' test])* (TYPE_COMMENT | [',' [TYPE_COMMENT] [ '*'
|
||||
[tfpdef] (',' [TYPE_COMMENT] tfpdef ['=' test])* (TYPE_COMMENT | [','
|
||||
[TYPE_COMMENT] ['**' tfpdef [','] [TYPE_COMMENT]]]) | '**' tfpdef [',']
|
||||
[TYPE_COMMENT]]]) | '*' [tfpdef] (',' [TYPE_COMMENT] tfpdef ['=' test])*
|
||||
(TYPE_COMMENT | [',' [TYPE_COMMENT] ['**' tfpdef [','] [TYPE_COMMENT]]]) |
|
||||
'**' tfpdef [','] [TYPE_COMMENT]))
|
||||
|
||||
tfpdef: NAME [':' test]
|
||||
varargslist: (vfpdef ['=' test] (',' vfpdef ['=' test])* [',' [
|
||||
'*' [vfpdef] (',' vfpdef ['=' test])* [',' ['**' vfpdef [',']]]
|
||||
| '**' vfpdef [',']]]
|
||||
| '*' [vfpdef] (',' vfpdef ['=' test])* [',' ['**' vfpdef [',']]]
|
||||
| '**' vfpdef [',']
|
||||
)
|
||||
|
||||
The following definition for varargslist is equivalent to this set of rules:
|
||||
|
||||
arguments = argument (',' argument )*
|
||||
argument = vfpdef ['=' test]
|
||||
kwargs = '**' vfpdef [',']
|
||||
args = '*' [vfpdef]
|
||||
kwonly_kwargs = (',' argument )* [',' [kwargs]]
|
||||
args_kwonly_kwargs = args kwonly_kwargs | kwargs
|
||||
poskeyword_args_kwonly_kwargs = arguments [',' [args_kwonly_kwargs]]
|
||||
vararglist_no_posonly = poskeyword_args_kwonly_kwargs | args_kwonly_kwargs
|
||||
varargslist = arguments ',' '/' [','[(vararglist_no_posonly)]] |
|
||||
(vararglist_no_posonly)
|
||||
|
||||
varargslist: vfpdef ['=' test ](',' vfpdef ['=' test])* ',' '/' [',' [ (vfpdef ['='
|
||||
test] (',' vfpdef ['=' test])* [',' [ '*' [vfpdef] (',' vfpdef ['=' test])* [','
|
||||
['**' vfpdef [',']]] | '**' vfpdef [',']]] | '*' [vfpdef] (',' vfpdef ['=' test])*
|
||||
[',' ['**' vfpdef [',']]] | '**' vfpdef [',']) ]] | (vfpdef ['=' test] (',' vfpdef
|
||||
['=' test])* [',' [ '*' [vfpdef] (',' vfpdef ['=' test])* [',' ['**' vfpdef [',']]]
|
||||
| '**' vfpdef [',']]] | '*' [vfpdef] (',' vfpdef ['=' test])* [',' ['**' vfpdef
|
||||
[',']]] | '**' vfpdef [','])
|
||||
|
||||
vfpdef: NAME
|
||||
|
||||
*/
|
||||
int i, j, k, nposargs = 0, nkwonlyargs = 0;
|
||||
int i, j, k, l, nposonlyargs=0, nposargs = 0, nkwonlyargs = 0;
|
||||
int nposdefaults = 0, found_default = 0;
|
||||
asdl_seq *posargs, *posdefaults, *kwonlyargs, *kwdefaults;
|
||||
asdl_seq *posonlyargs, *posargs, *posdefaults, *kwonlyargs, *kwdefaults;
|
||||
arg_ty vararg = NULL, kwarg = NULL;
|
||||
arg_ty arg = NULL;
|
||||
node *ch;
|
||||
|
||||
if (TYPE(n) == parameters) {
|
||||
if (NCH(n) == 2) /* () as argument list */
|
||||
return arguments(NULL, NULL, NULL, NULL, NULL, NULL, c->c_arena);
|
||||
return arguments(NULL, NULL, NULL, NULL, NULL, NULL, NULL, c->c_arena);
|
||||
n = CHILD(n, 1);
|
||||
}
|
||||
assert(TYPE(n) == typedargslist || TYPE(n) == varargslist);
|
||||
|
@ -1479,6 +1522,10 @@ ast_for_arguments(struct compiling *c, const node *n)
|
|||
if (TYPE(ch) == DOUBLESTAR) break;
|
||||
if (TYPE(ch) == vfpdef || TYPE(ch) == tfpdef) nposargs++;
|
||||
if (TYPE(ch) == EQUAL) nposdefaults++;
|
||||
if (TYPE(ch) == SLASH ) {
|
||||
nposonlyargs = nposargs;
|
||||
nposargs = 0;
|
||||
}
|
||||
}
|
||||
/* count the number of keyword only args &
|
||||
defaults for keyword only args */
|
||||
|
@ -1487,6 +1534,10 @@ ast_for_arguments(struct compiling *c, const node *n)
|
|||
if (TYPE(ch) == DOUBLESTAR) break;
|
||||
if (TYPE(ch) == tfpdef || TYPE(ch) == vfpdef) nkwonlyargs++;
|
||||
}
|
||||
posonlyargs = (nposonlyargs ? _Py_asdl_seq_new(nposonlyargs, c->c_arena) : NULL);
|
||||
if (!posonlyargs && nposonlyargs) {
|
||||
return NULL;
|
||||
}
|
||||
posargs = (nposargs ? _Py_asdl_seq_new(nposargs, c->c_arena) : NULL);
|
||||
if (!posargs && nposargs)
|
||||
return NULL;
|
||||
|
@ -1512,6 +1563,7 @@ ast_for_arguments(struct compiling *c, const node *n)
|
|||
i = 0;
|
||||
j = 0; /* index for defaults */
|
||||
k = 0; /* index for args */
|
||||
l = 0; /* index for posonlyargs */
|
||||
while (i < NCH(n)) {
|
||||
ch = CHILD(n, i);
|
||||
switch (TYPE(ch)) {
|
||||
|
@ -1537,11 +1589,23 @@ ast_for_arguments(struct compiling *c, const node *n)
|
|||
arg = ast_for_arg(c, ch);
|
||||
if (!arg)
|
||||
return NULL;
|
||||
asdl_seq_SET(posargs, k++, arg);
|
||||
if (l < nposonlyargs) {
|
||||
asdl_seq_SET(posonlyargs, l++, arg);
|
||||
} else {
|
||||
asdl_seq_SET(posargs, k++, arg);
|
||||
}
|
||||
i += 1; /* the name */
|
||||
if (i < NCH(n) && TYPE(CHILD(n, i)) == COMMA)
|
||||
i += 1; /* the comma, if present */
|
||||
break;
|
||||
case SLASH:
|
||||
/* Advance the slash and the comma. If there are more names
|
||||
* after the slash there will be a comma so we are advancing
|
||||
* the correct number of nodes. If the slash is the last item,
|
||||
* we will be advancing an extra token but then * i > NCH(n)
|
||||
* and the enclosing while will finish correctly. */
|
||||
i += 2;
|
||||
break;
|
||||
case STAR:
|
||||
if (i+1 >= NCH(n) ||
|
||||
(i+2 == NCH(n) && (TYPE(CHILD(n, i+1)) == COMMA
|
||||
|
@ -1621,7 +1685,7 @@ ast_for_arguments(struct compiling *c, const node *n)
|
|||
return NULL;
|
||||
}
|
||||
}
|
||||
return arguments(posargs, vararg, kwonlyargs, kwdefaults, kwarg, posdefaults, c->c_arena);
|
||||
return arguments(posargs, posonlyargs, vararg, kwonlyargs, kwdefaults, kwarg, posdefaults, c->c_arena);
|
||||
}
|
||||
|
||||
static expr_ty
|
||||
|
@ -1909,7 +1973,7 @@ ast_for_lambdef(struct compiling *c, const node *n)
|
|||
expr_ty expression;
|
||||
|
||||
if (NCH(n) == 3) {
|
||||
args = arguments(NULL, NULL, NULL, NULL, NULL, NULL, c->c_arena);
|
||||
args = arguments(NULL, NULL, NULL, NULL, NULL, NULL, NULL, c->c_arena);
|
||||
if (!args)
|
||||
return NULL;
|
||||
expression = ast_for_expr(c, CHILD(n, 2));
|
||||
|
|
120
Python/ceval.c
120
Python/ceval.c
|
@ -3694,10 +3694,10 @@ missing_arguments(PyCodeObject *co, Py_ssize_t missing, Py_ssize_t defcount,
|
|||
return;
|
||||
if (positional) {
|
||||
start = 0;
|
||||
end = co->co_argcount - defcount;
|
||||
end = co->co_posonlyargcount + co->co_argcount - defcount;
|
||||
}
|
||||
else {
|
||||
start = co->co_argcount;
|
||||
start = co->co_posonlyargcount + co->co_argcount;
|
||||
end = start + co->co_kwonlyargcount;
|
||||
}
|
||||
for (i = start; i < end; i++) {
|
||||
|
@ -3724,23 +3724,25 @@ too_many_positional(PyCodeObject *co, Py_ssize_t given, Py_ssize_t defcount,
|
|||
Py_ssize_t kwonly_given = 0;
|
||||
Py_ssize_t i;
|
||||
PyObject *sig, *kwonly_sig;
|
||||
Py_ssize_t co_posonlyargcount = co->co_posonlyargcount;
|
||||
Py_ssize_t co_argcount = co->co_argcount;
|
||||
Py_ssize_t total_positional = co_argcount + co_posonlyargcount;
|
||||
|
||||
assert((co->co_flags & CO_VARARGS) == 0);
|
||||
/* Count missing keyword-only args. */
|
||||
for (i = co_argcount; i < co_argcount + co->co_kwonlyargcount; i++) {
|
||||
for (i = total_positional; i < total_positional + co->co_kwonlyargcount; i++) {
|
||||
if (GETLOCAL(i) != NULL) {
|
||||
kwonly_given++;
|
||||
}
|
||||
}
|
||||
if (defcount) {
|
||||
Py_ssize_t atleast = co_argcount - defcount;
|
||||
Py_ssize_t atleast = total_positional - defcount;
|
||||
plural = 1;
|
||||
sig = PyUnicode_FromFormat("from %zd to %zd", atleast, co_argcount);
|
||||
sig = PyUnicode_FromFormat("from %zd to %zd", atleast, total_positional);
|
||||
}
|
||||
else {
|
||||
plural = (co_argcount != 1);
|
||||
sig = PyUnicode_FromFormat("%zd", co_argcount);
|
||||
plural = (total_positional != 1);
|
||||
sig = PyUnicode_FromFormat("%zd", total_positional);
|
||||
}
|
||||
if (sig == NULL)
|
||||
return;
|
||||
|
@ -3772,6 +3774,67 @@ too_many_positional(PyCodeObject *co, Py_ssize_t given, Py_ssize_t defcount,
|
|||
Py_DECREF(kwonly_sig);
|
||||
}
|
||||
|
||||
static int
|
||||
positional_only_passed_as_keyword(PyCodeObject *co, Py_ssize_t kwcount,
|
||||
PyObject* const* kwnames)
|
||||
{
|
||||
int posonly_conflicts = 0;
|
||||
PyObject* posonly_names = PyList_New(0);
|
||||
|
||||
for(int k=0; k < co->co_posonlyargcount; k++){
|
||||
PyObject* posonly_name = PyTuple_GET_ITEM(co->co_varnames, k);
|
||||
|
||||
for (int k2=0; k2<kwcount; k2++){
|
||||
/* Compare the pointers first and fallback to PyObject_RichCompareBool*/
|
||||
PyObject* kwname = kwnames[k2];
|
||||
if (kwname == posonly_name){
|
||||
if(PyList_Append(posonly_names, kwname) != 0) {
|
||||
goto fail;
|
||||
}
|
||||
posonly_conflicts++;
|
||||
continue;
|
||||
}
|
||||
|
||||
int cmp = PyObject_RichCompareBool(posonly_name, kwname, Py_EQ);
|
||||
|
||||
if ( cmp > 0) {
|
||||
if(PyList_Append(posonly_names, kwname) != 0) {
|
||||
goto fail;
|
||||
}
|
||||
posonly_conflicts++;
|
||||
} else if (cmp < 0) {
|
||||
goto fail;
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
if (posonly_conflicts) {
|
||||
PyObject* comma = PyUnicode_FromString(", ");
|
||||
if (comma == NULL) {
|
||||
goto fail;
|
||||
}
|
||||
PyObject* error_names = PyUnicode_Join(comma, posonly_names);
|
||||
Py_DECREF(comma);
|
||||
if (error_names == NULL) {
|
||||
goto fail;
|
||||
}
|
||||
PyErr_Format(PyExc_TypeError,
|
||||
"%U() got some positional-only arguments passed"
|
||||
" as keyword arguments: '%U'",
|
||||
co->co_name, error_names);
|
||||
Py_DECREF(error_names);
|
||||
goto fail;
|
||||
}
|
||||
|
||||
Py_DECREF(posonly_names);
|
||||
return 0;
|
||||
|
||||
fail:
|
||||
Py_XDECREF(posonly_names);
|
||||
return 1;
|
||||
|
||||
}
|
||||
|
||||
/* This is gonna seem *real weird*, but if you put some other code between
|
||||
PyEval_EvalFrame() and _PyEval_EvalFrameDefault() you will need to adjust
|
||||
the test in the if statements in Misc/gdbinit (pystack and pystackv). */
|
||||
|
@ -3791,8 +3854,8 @@ _PyEval_EvalCodeWithName(PyObject *_co, PyObject *globals, PyObject *locals,
|
|||
PyObject **fastlocals, **freevars;
|
||||
PyThreadState *tstate;
|
||||
PyObject *x, *u;
|
||||
const Py_ssize_t total_args = co->co_argcount + co->co_kwonlyargcount;
|
||||
Py_ssize_t i, n;
|
||||
const Py_ssize_t total_args = co->co_argcount + co->co_kwonlyargcount + co->co_posonlyargcount;
|
||||
Py_ssize_t i, j, n;
|
||||
PyObject *kwdict;
|
||||
|
||||
if (globals == NULL) {
|
||||
|
@ -3826,14 +3889,28 @@ _PyEval_EvalCodeWithName(PyObject *_co, PyObject *globals, PyObject *locals,
|
|||
kwdict = NULL;
|
||||
}
|
||||
|
||||
/* Copy positional arguments into local variables */
|
||||
if (argcount > co->co_argcount) {
|
||||
n = co->co_argcount;
|
||||
/* Copy positional only arguments into local variables */
|
||||
if (argcount > co->co_argcount + co->co_posonlyargcount) {
|
||||
n = co->co_posonlyargcount;
|
||||
}
|
||||
else {
|
||||
n = argcount;
|
||||
}
|
||||
for (i = 0; i < n; i++) {
|
||||
for (j = 0; j < n; j++) {
|
||||
x = args[j];
|
||||
Py_INCREF(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);
|
||||
|
@ -3866,7 +3943,7 @@ _PyEval_EvalCodeWithName(PyObject *_co, PyObject *globals, PyObject *locals,
|
|||
/* Speed hack: do raw pointer compares. As names are
|
||||
normally interned this should almost always hit. */
|
||||
co_varnames = ((PyTupleObject *)(co->co_varnames))->ob_item;
|
||||
for (j = 0; j < total_args; j++) {
|
||||
for (j = co->co_posonlyargcount; j < total_args; j++) {
|
||||
PyObject *name = co_varnames[j];
|
||||
if (name == keyword) {
|
||||
goto kw_found;
|
||||
|
@ -3874,7 +3951,7 @@ _PyEval_EvalCodeWithName(PyObject *_co, PyObject *globals, PyObject *locals,
|
|||
}
|
||||
|
||||
/* Slow fallback, just in case */
|
||||
for (j = 0; j < total_args; j++) {
|
||||
for (j = co->co_posonlyargcount; j < total_args; j++) {
|
||||
PyObject *name = co_varnames[j];
|
||||
int cmp = PyObject_RichCompareBool( keyword, name, Py_EQ);
|
||||
if (cmp > 0) {
|
||||
|
@ -3887,6 +3964,11 @@ _PyEval_EvalCodeWithName(PyObject *_co, PyObject *globals, PyObject *locals,
|
|||
|
||||
assert(j >= total_args);
|
||||
if (kwdict == NULL) {
|
||||
|
||||
if (co->co_posonlyargcount && positional_only_passed_as_keyword(co, kwcount, kwnames)) {
|
||||
goto fail;
|
||||
}
|
||||
|
||||
PyErr_Format(PyExc_TypeError,
|
||||
"%U() got an unexpected keyword argument '%S'",
|
||||
co->co_name, keyword);
|
||||
|
@ -3910,14 +3992,14 @@ _PyEval_EvalCodeWithName(PyObject *_co, PyObject *globals, PyObject *locals,
|
|||
}
|
||||
|
||||
/* Check the number of positional arguments */
|
||||
if (argcount > co->co_argcount && !(co->co_flags & CO_VARARGS)) {
|
||||
if ((argcount > co->co_argcount + co->co_posonlyargcount) && !(co->co_flags & CO_VARARGS)) {
|
||||
too_many_positional(co, argcount, defcount, fastlocals);
|
||||
goto fail;
|
||||
}
|
||||
|
||||
/* Add missing positional arguments (copy default values from defs) */
|
||||
if (argcount < co->co_argcount) {
|
||||
Py_ssize_t m = co->co_argcount - defcount;
|
||||
if (argcount < co->co_posonlyargcount + co->co_argcount) {
|
||||
Py_ssize_t m = co->co_posonlyargcount + co->co_argcount - defcount;
|
||||
Py_ssize_t missing = 0;
|
||||
for (i = argcount; i < m; i++) {
|
||||
if (GETLOCAL(i) == NULL) {
|
||||
|
@ -3944,7 +4026,7 @@ _PyEval_EvalCodeWithName(PyObject *_co, PyObject *globals, PyObject *locals,
|
|||
/* Add missing keyword arguments (copy default values from kwdefs) */
|
||||
if (co->co_kwonlyargcount > 0) {
|
||||
Py_ssize_t missing = 0;
|
||||
for (i = co->co_argcount; i < total_args; i++) {
|
||||
for (i = co->co_posonlyargcount + co->co_argcount; i < total_args; i++) {
|
||||
PyObject *name;
|
||||
if (GETLOCAL(i) != NULL)
|
||||
continue;
|
||||
|
|
|
@ -122,6 +122,7 @@ struct compiler_unit {
|
|||
PyObject *u_private; /* for private name mangling */
|
||||
|
||||
Py_ssize_t u_argcount; /* number of arguments for block */
|
||||
Py_ssize_t u_posonlyargcount; /* number of positional only arguments for block */
|
||||
Py_ssize_t u_kwonlyargcount; /* number of keyword only arguments for block */
|
||||
/* Pointer to the most recently allocated block. By following b_list
|
||||
members, you can reach all early allocated blocks. */
|
||||
|
@ -552,6 +553,7 @@ compiler_enter_scope(struct compiler *c, identifier name,
|
|||
memset(u, 0, sizeof(struct compiler_unit));
|
||||
u->u_scope_type = scope_type;
|
||||
u->u_argcount = 0;
|
||||
u->u_posonlyargcount = 0;
|
||||
u->u_kwonlyargcount = 0;
|
||||
u->u_ste = PySymtable_Lookup(c->c_st, key);
|
||||
if (!u->u_ste) {
|
||||
|
@ -2127,6 +2129,7 @@ compiler_function(struct compiler *c, stmt_ty s, int is_async)
|
|||
}
|
||||
|
||||
c->u->u_argcount = asdl_seq_LEN(args->args);
|
||||
c->u->u_posonlyargcount = asdl_seq_LEN(args->posonlyargs);
|
||||
c->u->u_kwonlyargcount = asdl_seq_LEN(args->kwonlyargs);
|
||||
VISIT_SEQ_IN_SCOPE(c, stmt, body);
|
||||
co = assemble(c, 1);
|
||||
|
@ -2507,6 +2510,7 @@ compiler_lambda(struct compiler *c, expr_ty e)
|
|||
return 0;
|
||||
|
||||
c->u->u_argcount = asdl_seq_LEN(args->args);
|
||||
c->u->u_posonlyargcount = asdl_seq_LEN(args->posonlyargs);
|
||||
c->u->u_kwonlyargcount = asdl_seq_LEN(args->kwonlyargs);
|
||||
VISIT_IN_SCOPE(c, expr, e->v.Lambda.body);
|
||||
if (c->u->u_ste->ste_generator) {
|
||||
|
@ -5742,7 +5746,7 @@ makecode(struct compiler *c, struct assembler *a)
|
|||
Py_ssize_t nlocals;
|
||||
int nlocals_int;
|
||||
int flags;
|
||||
int argcount, kwonlyargcount, maxdepth;
|
||||
int argcount, posonlyargcount, kwonlyargcount, maxdepth;
|
||||
|
||||
consts = consts_dict_keys_inorder(c->u->u_consts);
|
||||
names = dict_keys_inorder(c->u->u_names, 0);
|
||||
|
@ -5787,12 +5791,13 @@ makecode(struct compiler *c, struct assembler *a)
|
|||
}
|
||||
|
||||
argcount = Py_SAFE_DOWNCAST(c->u->u_argcount, Py_ssize_t, int);
|
||||
posonlyargcount = Py_SAFE_DOWNCAST(c->u->u_posonlyargcount, Py_ssize_t, int);
|
||||
kwonlyargcount = Py_SAFE_DOWNCAST(c->u->u_kwonlyargcount, Py_ssize_t, int);
|
||||
maxdepth = stackdepth(c);
|
||||
if (maxdepth < 0) {
|
||||
goto error;
|
||||
}
|
||||
co = PyCode_New(argcount, kwonlyargcount,
|
||||
co = PyCode_New(argcount, posonlyargcount, kwonlyargcount,
|
||||
nlocals_int, maxdepth, flags,
|
||||
bytecode, consts, names, varnames,
|
||||
freevars, cellvars,
|
||||
|
|
|
@ -15,15 +15,15 @@
|
|||
the appropriate bytes from M___main__.c. */
|
||||
|
||||
static unsigned char M___hello__[] = {
|
||||
227,0,0,0,0,0,0,0,0,0,0,0,0,2,0,0,
|
||||
0,64,0,0,0,115,16,0,0,0,100,0,90,0,101,1,
|
||||
100,1,131,1,1,0,100,2,83,0,41,3,84,122,12,72,
|
||||
101,108,108,111,32,119,111,114,108,100,33,78,41,2,218,11,
|
||||
105,110,105,116,105,97,108,105,122,101,100,218,5,112,114,105,
|
||||
110,116,169,0,114,3,0,0,0,114,3,0,0,0,250,22,
|
||||
46,47,84,111,111,108,115,47,102,114,101,101,122,101,47,102,
|
||||
108,97,103,46,112,121,218,8,60,109,111,100,117,108,101,62,
|
||||
1,0,0,0,115,2,0,0,0,4,1,
|
||||
227,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
|
||||
0,2,0,0,0,64,0,0,0,115,16,0,0,0,100,0,
|
||||
90,0,101,1,100,1,131,1,1,0,100,2,83,0,41,3,
|
||||
84,122,12,72,101,108,108,111,32,119,111,114,108,100,33,78,
|
||||
41,2,218,11,105,110,105,116,105,97,108,105,122,101,100,218,
|
||||
5,112,114,105,110,116,169,0,114,3,0,0,0,114,3,0,
|
||||
0,0,250,20,84,111,111,108,115,47,102,114,101,101,122,101,
|
||||
47,102,108,97,103,46,112,121,218,8,60,109,111,100,117,108,
|
||||
101,62,1,0,0,0,115,2,0,0,0,4,1,
|
||||
};
|
||||
|
||||
#define SIZE (int)sizeof(M___hello__)
|
||||
|
|
File diff suppressed because it is too large
Load diff
2781
Python/importlib.h
generated
2781
Python/importlib.h
generated
File diff suppressed because it is too large
Load diff
4216
Python/importlib_external.h
generated
4216
Python/importlib_external.h
generated
File diff suppressed because it is too large
Load diff
File diff suppressed because it is too large
Load diff
|
@ -530,6 +530,7 @@ w_complex_object(PyObject *v, char flag, WFILE *p)
|
|||
PyCodeObject *co = (PyCodeObject *)v;
|
||||
W_TYPE(TYPE_CODE, p);
|
||||
w_long(co->co_argcount, p);
|
||||
w_long(co->co_posonlyargcount, p);
|
||||
w_long(co->co_kwonlyargcount, p);
|
||||
w_long(co->co_nlocals, p);
|
||||
w_long(co->co_stacksize, p);
|
||||
|
@ -1322,6 +1323,7 @@ r_object(RFILE *p)
|
|||
case TYPE_CODE:
|
||||
{
|
||||
int argcount;
|
||||
int posonlyargcount;
|
||||
int kwonlyargcount;
|
||||
int nlocals;
|
||||
int stacksize;
|
||||
|
@ -1347,6 +1349,10 @@ r_object(RFILE *p)
|
|||
argcount = (int)r_long(p);
|
||||
if (PyErr_Occurred())
|
||||
goto code_error;
|
||||
posonlyargcount = (int)r_long(p);
|
||||
if (PyErr_Occurred()) {
|
||||
goto code_error;
|
||||
}
|
||||
kwonlyargcount = (int)r_long(p);
|
||||
if (PyErr_Occurred())
|
||||
goto code_error;
|
||||
|
@ -1391,7 +1397,7 @@ r_object(RFILE *p)
|
|||
goto code_error;
|
||||
|
||||
v = (PyObject *) PyCode_New(
|
||||
argcount, kwonlyargcount,
|
||||
argcount, posonlyargcount, kwonlyargcount,
|
||||
nlocals, stacksize, flags,
|
||||
code, consts, names, varnames,
|
||||
freevars, cellvars, filename, name,
|
||||
|
|
|
@ -1653,6 +1653,8 @@ symtable_visit_arguments(struct symtable *st, arguments_ty a)
|
|||
/* skip default arguments inside function block
|
||||
XXX should ast be different?
|
||||
*/
|
||||
if (a->posonlyargs && !symtable_visit_params(st, a->posonlyargs))
|
||||
return 0;
|
||||
if (a->args && !symtable_visit_params(st, a->args))
|
||||
return 0;
|
||||
if (a->kwonlyargs && !symtable_visit_params(st, a->kwonlyargs))
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue