From a8e93d3dca086896e668b88b6c5450eaf644c0e7 Mon Sep 17 00:00:00 2001 From: Bogdan Romanyuk <65823030+wrongnull@users.noreply.github.com> Date: Tue, 19 Mar 2024 12:20:38 +0300 Subject: gh-115756: make PyCode_GetFirstFree an unstable API (GH-115781) --- Doc/c-api/code.rst | 8 +++++++- Doc/whatsnew/3.13.rst | 4 ++++ Include/cpython/code.h | 6 +++++- .../next/C API/2024-03-19-09-49-04.gh-issue-115756.4Ls_Tl.rst | 3 +++ Objects/frameobject.c | 2 +- Objects/typeobject.c | 2 +- Python/ceval.c | 2 +- Python/compile.c | 2 +- 8 files changed, 23 insertions(+), 6 deletions(-) create mode 100644 Misc/NEWS.d/next/C API/2024-03-19-09-49-04.gh-issue-115756.4Ls_Tl.rst diff --git a/Doc/c-api/code.rst b/Doc/c-api/code.rst index f6fdd75..968c472 100644 --- a/Doc/c-api/code.rst +++ b/Doc/c-api/code.rst @@ -34,10 +34,16 @@ bound into a function. Return the number of free variables in a code object. -.. c:function:: int PyCode_GetFirstFree(PyCodeObject *co) +.. c:function:: int PyUnstable_Code_GetFirstFree(PyCodeObject *co) Return the position of the first free variable in a code object. + .. versionchanged:: 3.13 + + Renamed from ``PyCode_GetFirstFree`` as part of :ref:`unstable-c-api`. + The old name is deprecated, but will remain available until the + signature changes again. + .. c:function:: PyCodeObject* PyUnstable_Code_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, PyObject *qualname, int firstlineno, PyObject *linetable, PyObject *exceptiontable) Return a new code object. If you need a dummy code object to create a frame, diff --git a/Doc/whatsnew/3.13.rst b/Doc/whatsnew/3.13.rst index 0553cc9..0e04dcd 100644 --- a/Doc/whatsnew/3.13.rst +++ b/Doc/whatsnew/3.13.rst @@ -1471,6 +1471,10 @@ Changes in the Python API than directories only. Users may add a trailing slash to match only directories. +* :c:func:`!PyCode_GetFirstFree` is an ustable API now and has been renamed + to :c:func:`PyUnstable_Code_GetFirstFree`. + (Contributed by Bogdan Romanyuk in :gh:`115781`) + Build Changes ============= diff --git a/Include/cpython/code.h b/Include/cpython/code.h index 4e7e212..d5dac17 100644 --- a/Include/cpython/code.h +++ b/Include/cpython/code.h @@ -226,11 +226,15 @@ static inline Py_ssize_t PyCode_GetNumFree(PyCodeObject *op) { return op->co_nfreevars; } -static inline int PyCode_GetFirstFree(PyCodeObject *op) { +static inline int PyUnstable_Code_GetFirstFree(PyCodeObject *op) { assert(PyCode_Check(op)); return op->co_nlocalsplus - op->co_nfreevars; } +Py_DEPRECATED(3.13) static inline int PyCode_GetFirstFree(PyCodeObject *op) { + return PyUnstable_Code_GetFirstFree(op); +} + #define _PyCode_CODE(CO) _Py_RVALUE((_Py_CODEUNIT *)(CO)->co_code_adaptive) #define _PyCode_NBYTES(CO) (Py_SIZE(CO) * (Py_ssize_t)sizeof(_Py_CODEUNIT)) diff --git a/Misc/NEWS.d/next/C API/2024-03-19-09-49-04.gh-issue-115756.4Ls_Tl.rst b/Misc/NEWS.d/next/C API/2024-03-19-09-49-04.gh-issue-115756.4Ls_Tl.rst new file mode 100644 index 0000000..6960395 --- /dev/null +++ b/Misc/NEWS.d/next/C API/2024-03-19-09-49-04.gh-issue-115756.4Ls_Tl.rst @@ -0,0 +1,3 @@ +:c:func:`!PyCode_GetFirstFree` is an ustable API now and has been renamed to +:c:func:`PyUnstable_Code_GetFirstFree`. (Contributed by Bogdan Romanyuk in +:gh:`115781`) diff --git a/Objects/frameobject.c b/Objects/frameobject.c index a914c61..d55c246 100644 --- a/Objects/frameobject.c +++ b/Objects/frameobject.c @@ -1140,7 +1140,7 @@ frame_init_get_vars(_PyInterpreterFrame *frame) /* Free vars have not been initialized -- Do that */ PyObject *closure = ((PyFunctionObject *)frame->f_funcobj)->func_closure; - int offset = PyCode_GetFirstFree(co); + int offset = PyUnstable_Code_GetFirstFree(co); for (int i = 0; i < co->co_nfreevars; ++i) { PyObject *o = PyTuple_GET_ITEM(closure, i); frame->localsplus[offset + i] = Py_NewRef(o); diff --git a/Objects/typeobject.c b/Objects/typeobject.c index 24f3149..06c2fc8 100644 --- a/Objects/typeobject.c +++ b/Objects/typeobject.c @@ -10884,7 +10884,7 @@ super_init_without_args(_PyInterpreterFrame *cframe, PyCodeObject *co, // Look for __class__ in the free vars. PyTypeObject *type = NULL; - int i = PyCode_GetFirstFree(co); + int i = PyUnstable_Code_GetFirstFree(co); for (; i < co->co_nlocalsplus; i++) { assert((_PyLocals_GetKind(co->co_localspluskinds, i) & CO_FAST_FREE) != 0); PyObject *name = PyTuple_GET_ITEM(co->co_localsplusnames, i); diff --git a/Python/ceval.c b/Python/ceval.c index 9dbcd3d..b35a321 100644 --- a/Python/ceval.c +++ b/Python/ceval.c @@ -2903,7 +2903,7 @@ _PyEval_FormatExcUnbound(PyThreadState *tstate, PyCodeObject *co, int oparg) if (_PyErr_Occurred(tstate)) return; name = PyTuple_GET_ITEM(co->co_localsplusnames, oparg); - if (oparg < PyCode_GetFirstFree(co)) { + if (oparg < PyUnstable_Code_GetFirstFree(co)) { _PyEval_FormatExcCheckArg(tstate, PyExc_UnboundLocalError, UNBOUNDLOCAL_ERROR_MSG, name); } else { diff --git a/Python/compile.c b/Python/compile.c index 6b17f3b..3291d31 100644 --- a/Python/compile.c +++ b/Python/compile.c @@ -1830,7 +1830,7 @@ compiler_make_closure(struct compiler *c, location loc, PyCodeObject *co, Py_ssize_t flags) { if (co->co_nfreevars) { - int i = PyCode_GetFirstFree(co); + int i = PyUnstable_Code_GetFirstFree(co); for (; i < co->co_nlocalsplus; ++i) { /* Bypass com_addop_varname because it will generate LOAD_DEREF but LOAD_CLOSURE is needed. -- cgit v0.12