Skip to content

bpo-37221: Add PyCode_NewWithPosOnlyArgs to be used internally and set PyCode_New as a compatibility wrapper #13959

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 6 commits into from
Jul 1, 2019
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
21 changes: 11 additions & 10 deletions Doc/c-api/code.rst
Original file line number Diff line number Diff line change
Expand Up @@ -33,20 +33,21 @@ bound into a function.

Return the number of free variables in *co*.

.. c:function:: PyCodeObject* PyCode_New(int argcount, int posonlyargcount, int kwonlyargcount, int nlocals, int stacksize, int flags, PyObject *code, PyObject *consts, PyObject *names, PyObject *varnames, PyObject *freevars, PyObject *cellvars, PyObject *filename, PyObject *name, int firstlineno, PyObject *lnotab)
.. c:function:: PyCodeObject* PyCode_New(int argcount, int kwonlyargcount, int nlocals, int stacksize, int flags, PyObject *code, PyObject *consts, PyObject *names, PyObject *varnames, PyObject *freevars, PyObject *cellvars, PyObject *filename, PyObject *name, int firstlineno, PyObject *lnotab)

Return a new code object. If you need a dummy code object to
create a frame, use :c:func:`PyCode_NewEmpty` instead. Calling
:c:func:`PyCode_New` directly can bind you to a precise Python
version since the definition of the bytecode changes often.

.. versionchanged:: 3.8
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.
Return a new code object. If you need a dummy code object to create a frame,
use :c:func:`PyCode_NewEmpty` instead. Calling :c:func:`PyCode_New` directly
can bind you to a precise Python version since the definition of the bytecode
changes often.

.. audit-event:: code.__new__ "code filename name argcount posonlyargcount kwonlyargcount nlocals stacksize flags"

.. c:function:: PyCodeObject* PyCode_NewWithPosOnlyArgs(int argcount, int posonlyargcount, int kwonlyargcount, int nlocals, int stacksize, int flags, PyObject *code, PyObject *consts, PyObject *names, PyObject *varnames, PyObject *freevars, PyObject *cellvars, PyObject *filename, PyObject *name, int firstlineno, PyObject *lnotab)

Similar to :c:func:`PyCode_New`, but with an extra "posonlyargcount" for positonal-only arguments.

.. versionadded:: 3.8

.. c:function:: PyCodeObject* PyCode_NewEmpty(const char *filename, const char *funcname, int firstlineno)

Return a new empty code object with the specified filename,
Expand Down
19 changes: 18 additions & 1 deletion Doc/data/refcounts.dat
Original file line number Diff line number Diff line change
Expand Up @@ -234,9 +234,26 @@ PyCode_Check:PyObject*:co:0:
PyCode_GetNumFree:int:::
PyCode_GetNumFree:PyCodeObject*:co:0:

PyCode_NewWithPosOnlyArgs:PyCodeObject*::+1:
PyCode_NewWithPosOnlyArgs:int:argcount::
PyCode_NewWithPosOnlyArgs:int:posonlyargcount::
PyCode_NewWithPosOnlyArgs:int:kwonlyargcount::
PyCode_NewWithPosOnlyArgs:int:nlocals::
PyCode_NewWithPosOnlyArgs:int:stacksize::
PyCode_NewWithPosOnlyArgs:int:flags::
PyCode_NewWithPosOnlyArgs:PyObject*:code:0:
PyCode_NewWithPosOnlyArgs:PyObject*:consts:0:
PyCode_NewWithPosOnlyArgs:PyObject*:names:0:
PyCode_NewWithPosOnlyArgs:PyObject*:varnames:0:
PyCode_NewWithPosOnlyArgs:PyObject*:freevars:0:
PyCode_NewWithPosOnlyArgs:PyObject*:cellvars:0:
PyCode_NewWithPosOnlyArgs:PyObject*:filename:0:
PyCode_NewWithPosOnlyArgs:PyObject*:name:0:
PyCode_NewWithPosOnlyArgs:int:firstlineno::
PyCode_NewWithPosOnlyArgs:PyObject*:lnotab:0:

PyCode_New:PyCodeObject*::+1:
PyCode_New:int:argcount::
PyCode_New:int:posonlyargcount::
PyCode_New:int:kwonlyargcount::
PyCode_New:int:nlocals::
PyCode_New:int:stacksize::
Expand Down
5 changes: 5 additions & 0 deletions Doc/whatsnew/3.8.rst
Original file line number Diff line number Diff line change
Expand Up @@ -1042,6 +1042,11 @@ Build and C API Changes
allocation or deallocation may need to be adjusted.
(Contributed by Eddie Elizondo in :issue:`35810`.)

* The new function :c:func:`PyCode_NewWithPosOnlyArgs` allows to create
code objects like :c:func:`PyCode_New`, but with an extra *posonlyargcount*
parameter for indicating the number of positional-only arguments.
(Contributed by Pablo Galindo in :issue:`37221`.)


Deprecated
==========
Expand Down
5 changes: 5 additions & 0 deletions Include/code.h
Original file line number Diff line number Diff line change
Expand Up @@ -120,6 +120,11 @@ PyAPI_DATA(PyTypeObject) PyCode_Type;

/* Public interface */
PyAPI_FUNC(PyCodeObject *) PyCode_New(
int, int, int, int, int, PyObject *, PyObject *,
PyObject *, PyObject *, PyObject *, PyObject *,
PyObject *, PyObject *, int, PyObject *);

PyAPI_FUNC(PyCodeObject *) PyCode_NewWithPosOnlyArgs(
int, int, int, int, int, int, PyObject *, PyObject *,
PyObject *, PyObject *, PyObject *, PyObject *,
PyObject *, PyObject *, int, PyObject *);
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
The new function :c:func:`PyCode_NewWithPosOnlyArgs` allows to create
code objects like :c:func:`PyCode_New`, but with an extra *posonlyargcount*
parameter for indicating the number of positonal-only arguments.
46 changes: 31 additions & 15 deletions Objects/codeobject.c
Original file line number Diff line number Diff line change
Expand Up @@ -102,14 +102,13 @@ intern_string_constants(PyObject *tuple)
return modified;
}


PyCodeObject *
PyCode_New(int argcount, int posonlyargcount, int kwonlyargcount,
int nlocals, int stacksize, int flags,
PyObject *code, PyObject *consts, PyObject *names,
PyObject *varnames, PyObject *freevars, PyObject *cellvars,
PyObject *filename, PyObject *name, int firstlineno,
PyObject *lnotab)
PyCode_NewWithPosOnlyArgs(int argcount, int posonlyargcount, int kwonlyargcount,
int nlocals, int stacksize, int flags,
PyObject *code, PyObject *consts, PyObject *names,
PyObject *varnames, PyObject *freevars, PyObject *cellvars,
PyObject *filename, PyObject *name, int firstlineno,
PyObject *lnotab)
{
PyCodeObject *co;
Py_ssize_t *cell2arg = NULL;
Expand Down Expand Up @@ -243,6 +242,20 @@ PyCode_New(int argcount, int posonlyargcount, int kwonlyargcount,
return co;
}

PyCodeObject *
PyCode_New(int argcount, int kwonlyargcount,
int nlocals, int stacksize, int flags,
PyObject *code, PyObject *consts, PyObject *names,
PyObject *varnames, PyObject *freevars, PyObject *cellvars,
PyObject *filename, PyObject *name, int firstlineno,
PyObject *lnotab)
{
return PyCode_NewWithPosOnlyArgs(argcount, 0, kwonlyargcount, nlocals,
stacksize, flags, code, consts, names,
varnames, freevars, cellvars, filename,
name, firstlineno, lnotab);
}

int
_PyCode_InitOpcache(PyCodeObject *co)
{
Expand Down Expand Up @@ -311,7 +324,8 @@ PyCode_NewEmpty(const char *filename, const char *funcname, int firstlineno)
if (filename_ob == NULL)
goto failed;

result = PyCode_New(0, /* argcount */
result = PyCode_NewWithPosOnlyArgs(
0, /* argcount */
0, /* posonlyargcount */
0, /* kwonlyargcount */
0, /* nlocals */
Expand Down Expand Up @@ -492,12 +506,14 @@ code_new(PyTypeObject *type, PyObject *args, PyObject *kw)
if (ourcellvars == NULL)
goto cleanup;

co = (PyObject *)PyCode_New(argcount, posonlyargcount, kwonlyargcount,
nlocals, stacksize, flags,
code, consts, ournames, ourvarnames,
ourfreevars, ourcellvars, filename,
name, firstlineno, lnotab);
cleanup:
co = (PyObject *)PyCode_NewWithPosOnlyArgs(argcount, posonlyargcount,
kwonlyargcount,
nlocals, stacksize, flags,
code, consts, ournames,
ourvarnames, ourfreevars,
ourcellvars, filename,
name, firstlineno, lnotab);
cleanup:
Py_XDECREF(ournames);
Py_XDECREF(ourvarnames);
Py_XDECREF(ourfreevars);
Expand Down Expand Up @@ -625,7 +641,7 @@ code_replace_impl(PyCodeObject *self, int co_argcount,

#undef CHECK_INT_ARG

return (PyObject *)PyCode_New(
return (PyObject *)PyCode_NewWithPosOnlyArgs(
co_argcount, co_posonlyargcount, co_kwonlyargcount, co_nlocals,
co_stacksize, co_flags, (PyObject*)co_code, co_consts, co_names,
co_varnames, co_freevars, co_cellvars, co_filename, co_name,
Expand Down
12 changes: 5 additions & 7 deletions Python/compile.c
Original file line number Diff line number Diff line change
Expand Up @@ -5813,13 +5813,11 @@ makecode(struct compiler *c, struct assembler *a)
if (maxdepth < 0) {
goto error;
}
co = PyCode_New(posonlyargcount+posorkeywordargcount, posonlyargcount,
kwonlyargcount, nlocals_int, maxdepth, flags,
bytecode, consts, names, varnames,
freevars, cellvars,
c->c_filename, c->u->u_name,
c->u->u_firstlineno,
a->a_lnotab);
co = PyCode_NewWithPosOnlyArgs(posonlyargcount+posorkeywordargcount,
posonlyargcount, kwonlyargcount, nlocals_int,
maxdepth, flags, bytecode, consts, names,
varnames, freevars, cellvars, c->c_filename,
c->u->u_name, c->u->u_firstlineno, a->a_lnotab);
error:
Py_XDECREF(consts);
Py_XDECREF(names);
Expand Down
2 changes: 1 addition & 1 deletion Python/marshal.c
Original file line number Diff line number Diff line change
Expand Up @@ -1396,7 +1396,7 @@ r_object(RFILE *p)
if (lnotab == NULL)
goto code_error;

v = (PyObject *) PyCode_New(
v = (PyObject *) PyCode_NewWithPosOnlyArgs(
argcount, posonlyargcount, kwonlyargcount,
nlocals, stacksize, flags,
code, consts, names, varnames,
Expand Down