Skip to content

Commit 6c7249f

Browse files
gh-92154: Expose PyCode_GetCode in the C API (GH-92168)
1 parent 1d4a9a4 commit 6c7249f

File tree

6 files changed

+53
-0
lines changed

6 files changed

+53
-0
lines changed

Doc/c-api/code.rst

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -76,3 +76,17 @@ bound into a function.
7676
information is not available for any particular element.
7777
7878
Returns ``1`` if the function succeeds and 0 otherwise.
79+
80+
.. c:function:: PyObject* PyCode_GetCode(PyCodeObject *co)
81+
82+
Equivalent to the Python code ``getattr(co, 'co_code')``.
83+
Returns a strong reference to a :c:type:`PyBytesObject` representing the
84+
bytecode in a code object. On error, ``NULL`` is returned and an exception
85+
is raised.
86+
87+
This ``PyBytesObject`` may be created on-demand by the interpreter and does
88+
not necessarily represent the bytecode actually executed by CPython. The
89+
primary use case for this function is debuggers and profilers.
90+
91+
.. versionadded:: 3.11
92+

Doc/whatsnew/3.11.rst

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1412,6 +1412,11 @@ C API Changes
14121412
To get a custom code object: create a code object using the compiler,
14131413
then get a modified version with the ``replace`` method.
14141414

1415+
* :c:type:`PyCodeObject` no longer has a ``co_code`` field. Instead,
1416+
use ``PyObject_GetAttrString(code_object, "co_code")`` or
1417+
:c:func:`PyCode_GetCode` to get the underlying bytes object.
1418+
(Contributed by Brandt Bucher in :issue:`46841` and Ken Jin in :gh:`92154`.)
1419+
14151420
New Features
14161421
------------
14171422

Include/cpython/code.h

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -202,6 +202,9 @@ PyAPI_FUNC(int) _PyCode_GetExtra(PyObject *code, Py_ssize_t index,
202202
PyAPI_FUNC(int) _PyCode_SetExtra(PyObject *code, Py_ssize_t index,
203203
void *extra);
204204

205+
/* Equivalent to getattr(code, 'co_code') in Python.
206+
Returns a strong reference to a bytes object. */
207+
PyAPI_FUNC(PyObject *) PyCode_GetCode(PyCodeObject *code);
205208

206209
typedef enum _PyCodeLocationInfoKind {
207210
/* short forms are 0 to 9 */
Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,2 @@
1+
Added the :c:func:`PyCode_GetCode` function. This function does the
2+
equivalent of the Python code ``getattr(code_object, 'co_code')``.

Modules/_testcapimodule.c

Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5931,6 +5931,29 @@ get_feature_macros(PyObject *self, PyObject *Py_UNUSED(args))
59315931
return result;
59325932
}
59335933

5934+
static PyObject *
5935+
test_code_api(PyObject *self, PyObject *Py_UNUSED(args))
5936+
{
5937+
PyCodeObject *co = PyCode_NewEmpty("_testcapi", "dummy", 1);
5938+
if (co == NULL) {
5939+
return NULL;
5940+
}
5941+
PyObject *co_code = PyCode_GetCode(co);
5942+
if (co_code == NULL) {
5943+
Py_DECREF(co);
5944+
return NULL;
5945+
}
5946+
assert(PyBytes_CheckExact(co_code));
5947+
if (PyObject_Length(co_code) == 0) {
5948+
PyErr_SetString(PyExc_ValueError, "empty co_code");
5949+
Py_DECREF(co);
5950+
Py_DECREF(co_code);
5951+
return NULL;
5952+
}
5953+
Py_DECREF(co);
5954+
Py_DECREF(co_code);
5955+
Py_RETURN_NONE;
5956+
}
59345957

59355958
static PyObject *negative_dictoffset(PyObject *, PyObject *);
59365959
static PyObject *test_buildvalue_issue38913(PyObject *, PyObject *);
@@ -6227,6 +6250,7 @@ static PyMethodDef TestMethods[] = {
62276250
{"frame_getbuiltins", frame_getbuiltins, METH_O, NULL},
62286251
{"frame_getlasti", frame_getlasti, METH_O, NULL},
62296252
{"get_feature_macros", get_feature_macros, METH_NOARGS, NULL},
6253+
{"test_code_api", test_code_api, METH_NOARGS, NULL},
62306254
{NULL, NULL} /* sentinel */
62316255
};
62326256

Objects/codeobject.c

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1370,6 +1370,11 @@ _PyCode_GetCode(PyCodeObject *co)
13701370
return code;
13711371
}
13721372

1373+
PyObject *
1374+
PyCode_GetCode(PyCodeObject *co)
1375+
{
1376+
return _PyCode_GetCode(co);
1377+
}
13731378

13741379
/******************
13751380
* PyCode_Type

0 commit comments

Comments
 (0)