From cf33af72173a6dcc6c947afa387e3819a2ff270c Mon Sep 17 00:00:00 2001 From: Bogdan Romanyuk Date: Wed, 21 Feb 2024 23:27:25 +0300 Subject: [PATCH 1/6] make PyCode_GetFirstFree an unstable API --- Include/cpython/code.h | 2 +- Objects/frameobject.c | 2 +- Objects/typeobject.c | 2 +- Python/ceval.c | 2 +- Python/compile.c | 2 +- 5 files changed, 5 insertions(+), 5 deletions(-) diff --git a/Include/cpython/code.h b/Include/cpython/code.h index 1f47d99fb60443..5af2b02ff369ce 100644 --- a/Include/cpython/code.h +++ b/Include/cpython/code.h @@ -226,7 +226,7 @@ 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; } diff --git a/Objects/frameobject.c b/Objects/frameobject.c index a914c61aac2fd5..d55c246d80dd6a 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 fe3b7b87c8b4b6..7516f2cb616f53 100644 --- a/Objects/typeobject.c +++ b/Objects/typeobject.c @@ -10814,7 +10814,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 06c136aeb252c9..125c7440ab3826 100644 --- a/Python/ceval.c +++ b/Python/ceval.c @@ -2892,7 +2892,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 d857239690e7b5..d1cbad3baf5fdf 100644 --- a/Python/compile.c +++ b/Python/compile.c @@ -1831,7 +1831,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. From 356db2f2a37fe781ba3319d0cb88abc49d3d4977 Mon Sep 17 00:00:00 2001 From: Bogdan Romanyuk Date: Fri, 23 Feb 2024 00:55:00 +0300 Subject: [PATCH 2/6] Preserve deprecated API function --- Include/cpython/code.h | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/Include/cpython/code.h b/Include/cpython/code.h index 5af2b02ff369ce..bc90b9d008a83d 100644 --- a/Include/cpython/code.h +++ b/Include/cpython/code.h @@ -231,6 +231,10 @@ static inline int PyUnstable_Code_GetFirstFree(PyCodeObject *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)) From 001fe51234cf6d8662f1c92c11479a7540ccc6c4 Mon Sep 17 00:00:00 2001 From: Bogdan Romanyuk Date: Fri, 23 Feb 2024 01:01:47 +0300 Subject: [PATCH 3/6] Make necessary changes in a documentation --- Doc/c-api/code.rst | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/Doc/c-api/code.rst b/Doc/c-api/code.rst index f6fdd7574323c7..968c472219c643 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, From 012f351456dc5d4a2c8776fe36a4810c8b14642b Mon Sep 17 00:00:00 2001 From: Bogdan Romanyuk Date: Thu, 29 Feb 2024 11:18:31 +0300 Subject: [PATCH 4/6] add news entry --- Doc/whatsnew/3.13.rst | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/Doc/whatsnew/3.13.rst b/Doc/whatsnew/3.13.rst index 3a277d7ce1585f..8c462c224a8af3 100644 --- a/Doc/whatsnew/3.13.rst +++ b/Doc/whatsnew/3.13.rst @@ -1394,6 +1394,10 @@ Changes in the Python API than directories only. Users may add a trailing slash to match only directories. +* The :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 ============= From 1a45b38e2269ea58ce602a2fc43c5e3da3bf2bda Mon Sep 17 00:00:00 2001 From: Petr Viktorin Date: Tue, 19 Mar 2024 09:30:46 +0100 Subject: [PATCH 5/6] Avoid undefined reference --- Doc/whatsnew/3.13.rst | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Doc/whatsnew/3.13.rst b/Doc/whatsnew/3.13.rst index 8c462c224a8af3..2ab4856f5bdb51 100644 --- a/Doc/whatsnew/3.13.rst +++ b/Doc/whatsnew/3.13.rst @@ -1394,7 +1394,7 @@ Changes in the Python API than directories only. Users may add a trailing slash to match only directories. -* The :c:func:`PyCode_GetFirstFree` is an ustable API now and has been renamed +* :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`) From 04c101d73e2c1859ed5673752cf623a18c8b0b15 Mon Sep 17 00:00:00 2001 From: Petr Viktorin Date: Tue, 19 Mar 2024 09:49:12 +0100 Subject: [PATCH 6/6] Add a blurb --- .../next/C API/2024-03-19-09-49-04.gh-issue-115756.4Ls_Tl.rst | 3 +++ 1 file changed, 3 insertions(+) create mode 100644 Misc/NEWS.d/next/C API/2024-03-19-09-49-04.gh-issue-115756.4Ls_Tl.rst 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 00000000000000..6960395fe229a3 --- /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`)