summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorKen Jin <kenjin4096@gmail.com>2022-05-03 13:13:13 (GMT)
committerGitHub <noreply@github.com>2022-05-03 13:13:13 (GMT)
commit6c7249f2655749a06b4674a17537f844bd54d217 (patch)
tree15c7131fdf51411d2e8e566347f75e9f0809f508
parent1d4a9a45b7ac8c1c5fecc363c988be59500f1ed7 (diff)
downloadcpython-6c7249f2655749a06b4674a17537f844bd54d217.zip
cpython-6c7249f2655749a06b4674a17537f844bd54d217.tar.gz
cpython-6c7249f2655749a06b4674a17537f844bd54d217.tar.bz2
gh-92154: Expose PyCode_GetCode in the C API (GH-92168)
-rw-r--r--Doc/c-api/code.rst14
-rw-r--r--Doc/whatsnew/3.11.rst5
-rw-r--r--Include/cpython/code.h3
-rw-r--r--Misc/NEWS.d/next/C API/2022-05-03-20-08-35.gh-issue-92154.IqMcAJ.rst2
-rw-r--r--Modules/_testcapimodule.c24
-rw-r--r--Objects/codeobject.c5
6 files changed, 53 insertions, 0 deletions
diff --git a/Doc/c-api/code.rst b/Doc/c-api/code.rst
index 407d8b4..7915b81 100644
--- a/Doc/c-api/code.rst
+++ b/Doc/c-api/code.rst
@@ -76,3 +76,17 @@ bound into a function.
information is not available for any particular element.
Returns ``1`` if the function succeeds and 0 otherwise.
+
+.. c:function:: PyObject* PyCode_GetCode(PyCodeObject *co)
+
+ Equivalent to the Python code ``getattr(co, 'co_code')``.
+ Returns a strong reference to a :c:type:`PyBytesObject` representing the
+ bytecode in a code object. On error, ``NULL`` is returned and an exception
+ is raised.
+
+ This ``PyBytesObject`` may be created on-demand by the interpreter and does
+ not necessarily represent the bytecode actually executed by CPython. The
+ primary use case for this function is debuggers and profilers.
+
+ .. versionadded:: 3.11
+
diff --git a/Doc/whatsnew/3.11.rst b/Doc/whatsnew/3.11.rst
index 607f2e7..c19f158 100644
--- a/Doc/whatsnew/3.11.rst
+++ b/Doc/whatsnew/3.11.rst
@@ -1412,6 +1412,11 @@ C API Changes
To get a custom code object: create a code object using the compiler,
then get a modified version with the ``replace`` method.
+* :c:type:`PyCodeObject` no longer has a ``co_code`` field. Instead,
+ use ``PyObject_GetAttrString(code_object, "co_code")`` or
+ :c:func:`PyCode_GetCode` to get the underlying bytes object.
+ (Contributed by Brandt Bucher in :issue:`46841` and Ken Jin in :gh:`92154`.)
+
New Features
------------
diff --git a/Include/cpython/code.h b/Include/cpython/code.h
index be3b10b..ba7324b 100644
--- a/Include/cpython/code.h
+++ b/Include/cpython/code.h
@@ -202,6 +202,9 @@ PyAPI_FUNC(int) _PyCode_GetExtra(PyObject *code, Py_ssize_t index,
PyAPI_FUNC(int) _PyCode_SetExtra(PyObject *code, Py_ssize_t index,
void *extra);
+/* Equivalent to getattr(code, 'co_code') in Python.
+ Returns a strong reference to a bytes object. */
+PyAPI_FUNC(PyObject *) PyCode_GetCode(PyCodeObject *code);
typedef enum _PyCodeLocationInfoKind {
/* short forms are 0 to 9 */
diff --git a/Misc/NEWS.d/next/C API/2022-05-03-20-08-35.gh-issue-92154.IqMcAJ.rst b/Misc/NEWS.d/next/C API/2022-05-03-20-08-35.gh-issue-92154.IqMcAJ.rst
new file mode 100644
index 0000000..7713954
--- /dev/null
+++ b/Misc/NEWS.d/next/C API/2022-05-03-20-08-35.gh-issue-92154.IqMcAJ.rst
@@ -0,0 +1,2 @@
+Added the :c:func:`PyCode_GetCode` function. This function does the
+equivalent of the Python code ``getattr(code_object, 'co_code')``.
diff --git a/Modules/_testcapimodule.c b/Modules/_testcapimodule.c
index 9073f33..26d8d38 100644
--- a/Modules/_testcapimodule.c
+++ b/Modules/_testcapimodule.c
@@ -5931,6 +5931,29 @@ get_feature_macros(PyObject *self, PyObject *Py_UNUSED(args))
return result;
}
+static PyObject *
+test_code_api(PyObject *self, PyObject *Py_UNUSED(args))
+{
+ PyCodeObject *co = PyCode_NewEmpty("_testcapi", "dummy", 1);
+ if (co == NULL) {
+ return NULL;
+ }
+ PyObject *co_code = PyCode_GetCode(co);
+ if (co_code == NULL) {
+ Py_DECREF(co);
+ return NULL;
+ }
+ assert(PyBytes_CheckExact(co_code));
+ if (PyObject_Length(co_code) == 0) {
+ PyErr_SetString(PyExc_ValueError, "empty co_code");
+ Py_DECREF(co);
+ Py_DECREF(co_code);
+ return NULL;
+ }
+ Py_DECREF(co);
+ Py_DECREF(co_code);
+ Py_RETURN_NONE;
+}
static PyObject *negative_dictoffset(PyObject *, PyObject *);
static PyObject *test_buildvalue_issue38913(PyObject *, PyObject *);
@@ -6227,6 +6250,7 @@ static PyMethodDef TestMethods[] = {
{"frame_getbuiltins", frame_getbuiltins, METH_O, NULL},
{"frame_getlasti", frame_getlasti, METH_O, NULL},
{"get_feature_macros", get_feature_macros, METH_NOARGS, NULL},
+ {"test_code_api", test_code_api, METH_NOARGS, NULL},
{NULL, NULL} /* sentinel */
};
diff --git a/Objects/codeobject.c b/Objects/codeobject.c
index e3e4ca1..9f922da 100644
--- a/Objects/codeobject.c
+++ b/Objects/codeobject.c
@@ -1370,6 +1370,11 @@ _PyCode_GetCode(PyCodeObject *co)
return code;
}
+PyObject *
+PyCode_GetCode(PyCodeObject *co)
+{
+ return _PyCode_GetCode(co);
+}
/******************
* PyCode_Type