]> git.ipfire.org Git - thirdparty/Python/cpython.git/commitdiff
gh-92154: Expose PyCode_GetCode in the C API (GH-92168)
authorKen Jin <kenjin4096@gmail.com>
Tue, 3 May 2022 13:13:13 +0000 (20:13 +0700)
committerGitHub <noreply@github.com>
Tue, 3 May 2022 13:13:13 +0000 (21:13 +0800)
Doc/c-api/code.rst
Doc/whatsnew/3.11.rst
Include/cpython/code.h
Misc/NEWS.d/next/C API/2022-05-03-20-08-35.gh-issue-92154.IqMcAJ.rst [new file with mode: 0644]
Modules/_testcapimodule.c
Objects/codeobject.c

index 407d8b481be4aeef65a0cc07683909881d7a2f01..7915b81b463773c2191436a24d970b99ce680d9e 100644 (file)
@@ -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
+
index 607f2e749bb5a48d522580509e50a2f1fd266fd8..c19f158f57a31a3064ce7bc98f1bfba9a0702370 100644 (file)
@@ -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
 ------------
 
index be3b10bba724b8e6f9a42bddfa8a71369ffc4ed8..ba7324b48d8675eeb51e3a8783236f695c5d12db 100644 (file)
@@ -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 (file)
index 0000000..7713954
--- /dev/null
@@ -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')``.
index 9073f33e226bd3c14ced2c1cde61295ed6d6ece5..26d8d38f2f79543ddbf4a359d2da3b7c7f62cab8 100644 (file)
@@ -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 */
 };
 
index e3e4ca159a632952b44d08b38d84591d80faf90d..9f922dabeac63ee511cfbe43066baa1c344c1fd3 100644 (file)
@@ -1370,6 +1370,11 @@ _PyCode_GetCode(PyCodeObject *co)
     return code;
 }
 
+PyObject *
+PyCode_GetCode(PyCodeObject *co)
+{
+    return _PyCode_GetCode(co);
+}
 
 /******************
  * PyCode_Type