mirror of
https://github.com/python/cpython.git
synced 2025-08-24 10:45:53 +00:00
gh-94936: C getters: co_varnames, co_cellvars, co_freevars (#95008)
This commit is contained in:
parent
0342c93a6b
commit
42b102bbf9
6 changed files with 128 additions and 15 deletions
|
@ -90,3 +90,28 @@ bound into a function.
|
||||||
|
|
||||||
.. versionadded:: 3.11
|
.. versionadded:: 3.11
|
||||||
|
|
||||||
|
.. c:function:: PyObject* PyCode_GetVarnames(PyCodeObject *co)
|
||||||
|
|
||||||
|
Equivalent to the Python code ``getattr(co, 'co_varnames')``.
|
||||||
|
Returns a new reference to a :c:type:`PyTupleObject` containing the names of
|
||||||
|
the local variables. On error, ``NULL`` is returned and an exception
|
||||||
|
is raised.
|
||||||
|
|
||||||
|
.. versionadded:: 3.11
|
||||||
|
|
||||||
|
.. c:function:: PyObject* PyCode_GetCellvars(PyCodeObject *co)
|
||||||
|
|
||||||
|
Equivalent to the Python code ``getattr(co, 'co_cellvars')``.
|
||||||
|
Returns a new reference to a :c:type:`PyTupleObject` containing the names of
|
||||||
|
the local variables that are referenced by nested functions. On error, ``NULL``
|
||||||
|
is returned and an exception is raised.
|
||||||
|
|
||||||
|
.. versionadded:: 3.11
|
||||||
|
|
||||||
|
.. c:function:: PyObject* PyCode_GetFreevars(PyCodeObject *co)
|
||||||
|
|
||||||
|
Equivalent to the Python code ``getattr(co, 'co_freevars')``.
|
||||||
|
Returns a new reference to a :c:type:`PyTupleObject` containing the names of
|
||||||
|
the free variables. On error, ``NULL`` is returned and an exception is raised.
|
||||||
|
|
||||||
|
.. versionadded:: 3.11
|
||||||
|
|
|
@ -1719,10 +1719,13 @@ Porting to Python 3.11
|
||||||
To get a custom code object: create a code object using the compiler,
|
To get a custom code object: create a code object using the compiler,
|
||||||
then get a modified version with the ``replace`` method.
|
then get a modified version with the ``replace`` method.
|
||||||
|
|
||||||
* :c:type:`PyCodeObject` no longer has a ``co_code`` field. Instead,
|
* :c:type:`PyCodeObject` no longer has the ``co_code``, ``co_varnames``,
|
||||||
use ``PyObject_GetAttrString(code_object, "co_code")`` or
|
``co_cellvars`` and ``co_freevars`` fields. Instead, use
|
||||||
:c:func:`PyCode_GetCode` to get the underlying bytes object.
|
:c:func:`PyCode_GetCode`, :c:func:`PyCode_GetVarnames`,
|
||||||
(Contributed by Brandt Bucher in :issue:`46841` and Ken Jin in :gh:`92154`.)
|
:c:func:`PyCode_GetCellvars` and :c:func:`PyCode_GetFreevars` respectively
|
||||||
|
to access them via the C API.
|
||||||
|
(Contributed by Brandt Bucher in :issue:`46841` and Ken Jin in :gh:`92154`
|
||||||
|
and :gh:`94936`.)
|
||||||
|
|
||||||
* The old trashcan macros (``Py_TRASHCAN_SAFE_BEGIN``/``Py_TRASHCAN_SAFE_END``)
|
* The old trashcan macros (``Py_TRASHCAN_SAFE_BEGIN``/``Py_TRASHCAN_SAFE_END``)
|
||||||
are now deprecated. They should be replaced by the new macros
|
are now deprecated. They should be replaced by the new macros
|
||||||
|
|
|
@ -210,6 +210,12 @@ PyAPI_FUNC(int) _PyCode_SetExtra(PyObject *code, Py_ssize_t index,
|
||||||
/* Equivalent to getattr(code, 'co_code') in Python.
|
/* Equivalent to getattr(code, 'co_code') in Python.
|
||||||
Returns a strong reference to a bytes object. */
|
Returns a strong reference to a bytes object. */
|
||||||
PyAPI_FUNC(PyObject *) PyCode_GetCode(PyCodeObject *code);
|
PyAPI_FUNC(PyObject *) PyCode_GetCode(PyCodeObject *code);
|
||||||
|
/* Equivalent to getattr(code, 'co_varnames') in Python. */
|
||||||
|
PyAPI_FUNC(PyObject *) PyCode_GetVarnames(PyCodeObject *code);
|
||||||
|
/* Equivalent to getattr(code, 'co_cellvars') in Python. */
|
||||||
|
PyAPI_FUNC(PyObject *) PyCode_GetCellvars(PyCodeObject *code);
|
||||||
|
/* Equivalent to getattr(code, 'co_freevars') in Python. */
|
||||||
|
PyAPI_FUNC(PyObject *) PyCode_GetFreevars(PyCodeObject *code);
|
||||||
|
|
||||||
typedef enum _PyCodeLocationInfoKind {
|
typedef enum _PyCodeLocationInfoKind {
|
||||||
/* short forms are 0 to 9 */
|
/* short forms are 0 to 9 */
|
||||||
|
|
|
@ -0,0 +1,3 @@
|
||||||
|
Added :c:func:`PyCode_GetVarnames`, :c:func:`PyCode_GetCellvars` and
|
||||||
|
:c:func:`PyCode_GetFreevars` for accessing ``co_varnames``, ``co_cellvars``
|
||||||
|
and ``co_freevars`` respectively via the C API.
|
|
@ -5600,21 +5600,79 @@ test_code_api(PyObject *self, PyObject *Py_UNUSED(args))
|
||||||
if (co == NULL) {
|
if (co == NULL) {
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
PyObject *co_code = PyCode_GetCode(co);
|
/* co_code */
|
||||||
if (co_code == NULL) {
|
{
|
||||||
Py_DECREF(co);
|
PyObject *co_code = PyCode_GetCode(co);
|
||||||
return NULL;
|
if (co_code == NULL) {
|
||||||
}
|
goto fail;
|
||||||
assert(PyBytes_CheckExact(co_code));
|
}
|
||||||
if (PyObject_Length(co_code) == 0) {
|
assert(PyBytes_CheckExact(co_code));
|
||||||
PyErr_SetString(PyExc_ValueError, "empty co_code");
|
if (PyObject_Length(co_code) == 0) {
|
||||||
Py_DECREF(co);
|
PyErr_SetString(PyExc_ValueError, "empty co_code");
|
||||||
|
Py_DECREF(co_code);
|
||||||
|
goto fail;
|
||||||
|
}
|
||||||
Py_DECREF(co_code);
|
Py_DECREF(co_code);
|
||||||
return NULL;
|
}
|
||||||
|
/* co_varnames */
|
||||||
|
{
|
||||||
|
PyObject *co_varnames = PyCode_GetVarnames(co);
|
||||||
|
if (co_varnames == NULL) {
|
||||||
|
goto fail;
|
||||||
|
}
|
||||||
|
if (!PyTuple_CheckExact(co_varnames)) {
|
||||||
|
PyErr_SetString(PyExc_TypeError, "co_varnames not tuple");
|
||||||
|
Py_DECREF(co_varnames);
|
||||||
|
goto fail;
|
||||||
|
}
|
||||||
|
if (PyTuple_GET_SIZE(co_varnames) != 0) {
|
||||||
|
PyErr_SetString(PyExc_ValueError, "non-empty co_varnames");
|
||||||
|
Py_DECREF(co_varnames);
|
||||||
|
goto fail;
|
||||||
|
}
|
||||||
|
Py_DECREF(co_varnames);
|
||||||
|
}
|
||||||
|
/* co_cellvars */
|
||||||
|
{
|
||||||
|
PyObject *co_cellvars = PyCode_GetCellvars(co);
|
||||||
|
if (co_cellvars == NULL) {
|
||||||
|
goto fail;
|
||||||
|
}
|
||||||
|
if (!PyTuple_CheckExact(co_cellvars)) {
|
||||||
|
PyErr_SetString(PyExc_TypeError, "co_cellvars not tuple");
|
||||||
|
Py_DECREF(co_cellvars);
|
||||||
|
goto fail;
|
||||||
|
}
|
||||||
|
if (PyTuple_GET_SIZE(co_cellvars) != 0) {
|
||||||
|
PyErr_SetString(PyExc_ValueError, "non-empty co_cellvars");
|
||||||
|
Py_DECREF(co_cellvars);
|
||||||
|
goto fail;
|
||||||
|
}
|
||||||
|
Py_DECREF(co_cellvars);
|
||||||
|
}
|
||||||
|
/* co_freevars */
|
||||||
|
{
|
||||||
|
PyObject *co_freevars = PyCode_GetFreevars(co);
|
||||||
|
if (co_freevars == NULL) {
|
||||||
|
goto fail;
|
||||||
|
}
|
||||||
|
if (!PyTuple_CheckExact(co_freevars)) {
|
||||||
|
PyErr_SetString(PyExc_TypeError, "co_freevars not tuple");
|
||||||
|
Py_DECREF(co_freevars);
|
||||||
|
goto fail;
|
||||||
|
}
|
||||||
|
if (PyTuple_GET_SIZE(co_freevars) != 0) {
|
||||||
|
PyErr_SetString(PyExc_ValueError, "non-empty co_freevars");
|
||||||
|
Py_DECREF(co_freevars);
|
||||||
|
goto fail;
|
||||||
|
}
|
||||||
|
Py_DECREF(co_freevars);
|
||||||
}
|
}
|
||||||
Py_DECREF(co);
|
Py_DECREF(co);
|
||||||
Py_DECREF(co_code);
|
|
||||||
Py_RETURN_NONE;
|
Py_RETURN_NONE;
|
||||||
|
fail:
|
||||||
|
Py_DECREF(co);
|
||||||
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
static int
|
static int
|
||||||
|
|
|
@ -1401,18 +1401,36 @@ _PyCode_GetVarnames(PyCodeObject *co)
|
||||||
return get_localsplus_names(co, CO_FAST_LOCAL, co->co_nlocals);
|
return get_localsplus_names(co, CO_FAST_LOCAL, co->co_nlocals);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
PyObject *
|
||||||
|
PyCode_GetVarnames(PyCodeObject *code)
|
||||||
|
{
|
||||||
|
return _PyCode_GetVarnames(code);
|
||||||
|
}
|
||||||
|
|
||||||
PyObject *
|
PyObject *
|
||||||
_PyCode_GetCellvars(PyCodeObject *co)
|
_PyCode_GetCellvars(PyCodeObject *co)
|
||||||
{
|
{
|
||||||
return get_localsplus_names(co, CO_FAST_CELL, co->co_ncellvars);
|
return get_localsplus_names(co, CO_FAST_CELL, co->co_ncellvars);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
PyObject *
|
||||||
|
PyCode_GetCellvars(PyCodeObject *code)
|
||||||
|
{
|
||||||
|
return _PyCode_GetCellvars(code);
|
||||||
|
}
|
||||||
|
|
||||||
PyObject *
|
PyObject *
|
||||||
_PyCode_GetFreevars(PyCodeObject *co)
|
_PyCode_GetFreevars(PyCodeObject *co)
|
||||||
{
|
{
|
||||||
return get_localsplus_names(co, CO_FAST_FREE, co->co_nfreevars);
|
return get_localsplus_names(co, CO_FAST_FREE, co->co_nfreevars);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
PyObject *
|
||||||
|
PyCode_GetFreevars(PyCodeObject *code)
|
||||||
|
{
|
||||||
|
return _PyCode_GetFreevars(code);
|
||||||
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
deopt_code(_Py_CODEUNIT *instructions, Py_ssize_t len)
|
deopt_code(_Py_CODEUNIT *instructions, Py_ssize_t len)
|
||||||
{
|
{
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue