]> git.ipfire.org Git - thirdparty/Python/cpython.git/commitdiff
gh-76785: Move _Py_excinfo Functions Out of the Internal C-API (gh-111715)
authorEric Snow <ericsnowcurrently@gmail.com>
Mon, 6 Nov 2023 18:09:22 +0000 (11:09 -0700)
committerGitHub <noreply@github.com>
Mon, 6 Nov 2023 18:09:22 +0000 (11:09 -0700)
I added _Py_excinfo to the internal API (and added its functions in Python/errors.c) in gh-111530 (9322ce9).  Since then I've had a nagging sense that I should have added the type and functions in its own PR.  While I do plan on using _Py_excinfo outside crossinterp.c very soon (see gh-111572/gh-111573), I'd still feel more comfortable if the _Py_excinfo stuff went in as its own PR.  Hence, here we are.

(FWIW, I may combine that with gh-111572, which I may, in turn, combine with gh-111573.  We'll see.)

Include/internal/pycore_crossinterp.h
Include/internal/pycore_pyerrors.h
Python/crossinterp.c
Python/errors.c

index 9600dfb9600e602919be3e883f9783c4d0c25137..ee9ff0090c2484e32ff588047ca4baca09dd07cd 100644 (file)
@@ -164,6 +164,17 @@ extern void _PyXI_Fini(PyInterpreterState *interp);
 /* short-term data sharing */
 /***************************/
 
+// Ultimately we'd like to preserve enough information about the
+// exception and traceback that we could re-constitute (or at least
+// simulate, a la traceback.TracebackException), and even chain, a copy
+// of the exception in the calling interpreter.
+
+typedef struct _excinfo {
+    const char *type;
+    const char *msg;
+} _Py_excinfo;
+
+
 typedef enum error_code {
     _PyXI_ERR_NO_ERROR = 0,
     _PyXI_ERR_UNCAUGHT_EXCEPTION = -1,
index a953d2bb18d4ad6625f4a0107094969d9e08058b..0f16fb894d17e12791c08bb897157ff75835206b 100644 (file)
@@ -68,30 +68,6 @@ extern PyStatus _PyErr_InitTypes(PyInterpreterState *);
 extern void _PyErr_FiniTypes(PyInterpreterState *);
 
 
-/* exception snapshots */
-
-// Ultimately we'd like to preserve enough information about the
-// exception and traceback that we could re-constitute (or at least
-// simulate, a la traceback.TracebackException), and even chain, a copy
-// of the exception in the calling interpreter.
-
-typedef struct _excinfo {
-    const char *type;
-    const char *msg;
-} _Py_excinfo;
-
-extern void _Py_excinfo_Clear(_Py_excinfo *info);
-extern int _Py_excinfo_Copy(_Py_excinfo *dest, _Py_excinfo *src);
-extern const char * _Py_excinfo_InitFromException(
-    _Py_excinfo *info,
-    PyObject *exc);
-extern void _Py_excinfo_Apply(_Py_excinfo *info, PyObject *exctype);
-extern const char * _Py_excinfo_AsUTF8(
-    _Py_excinfo *info,
-    char *buf,
-    size_t bufsize);
-
-
 /* other API */
 
 static inline PyObject* _PyErr_Occurred(PyThreadState *tstate)
index a65355a49c5252baa1005ed971bbc67e58794158..de28cb7071740ab00f434ddd7934ff1987895cfa 100644 (file)
@@ -800,6 +800,17 @@ _xidregistry_fini(struct _xidregistry *registry)
 /* convenience utilities */
 /*************************/
 
+static const char *
+_copy_raw_string(const char *str)
+{
+    char *copied = PyMem_RawMalloc(strlen(str)+1);
+    if (copied == NULL) {
+        return NULL;
+    }
+    strcpy(copied, str);
+    return copied;
+}
+
 static const char *
 _copy_string_obj_raw(PyObject *strobj)
 {
@@ -835,6 +846,118 @@ _release_xid_data(_PyCrossInterpreterData *data, int rawfree)
 }
 
 
+/* exception snapshots */
+
+static int
+_exc_type_name_as_utf8(PyObject *exc, const char **p_typename)
+{
+    // XXX Use PyObject_GetAttrString(Py_TYPE(exc), '__name__')?
+    PyObject *nameobj = PyUnicode_FromString(Py_TYPE(exc)->tp_name);
+    if (nameobj == NULL) {
+        assert(PyErr_Occurred());
+        *p_typename = "unable to format exception type name";
+        return -1;
+    }
+    const char *name = PyUnicode_AsUTF8(nameobj);
+    if (name == NULL) {
+        assert(PyErr_Occurred());
+        Py_DECREF(nameobj);
+        *p_typename = "unable to encode exception type name";
+        return -1;
+    }
+    name = _copy_raw_string(name);
+    Py_DECREF(nameobj);
+    if (name == NULL) {
+        *p_typename = "out of memory copying exception type name";
+        return -1;
+    }
+    *p_typename = name;
+    return 0;
+}
+
+static int
+_exc_msg_as_utf8(PyObject *exc, const char **p_msg)
+{
+    PyObject *msgobj = PyObject_Str(exc);
+    if (msgobj == NULL) {
+        assert(PyErr_Occurred());
+        *p_msg = "unable to format exception message";
+        return -1;
+    }
+    const char *msg = PyUnicode_AsUTF8(msgobj);
+    if (msg == NULL) {
+        assert(PyErr_Occurred());
+        Py_DECREF(msgobj);
+        *p_msg = "unable to encode exception message";
+        return -1;
+    }
+    msg = _copy_raw_string(msg);
+    Py_DECREF(msgobj);
+    if (msg == NULL) {
+        assert(PyErr_ExceptionMatches(PyExc_MemoryError));
+        *p_msg = "out of memory copying exception message";
+        return -1;
+    }
+    *p_msg = msg;
+    return 0;
+}
+
+static void
+_Py_excinfo_Clear(_Py_excinfo *info)
+{
+    if (info->type != NULL) {
+        PyMem_RawFree((void *)info->type);
+    }
+    if (info->msg != NULL) {
+        PyMem_RawFree((void *)info->msg);
+    }
+    *info = (_Py_excinfo){ NULL };
+}
+
+static const char *
+_Py_excinfo_InitFromException(_Py_excinfo *info, PyObject *exc)
+{
+    assert(exc != NULL);
+
+    // Extract the exception type name.
+    const char *typename = NULL;
+    if (_exc_type_name_as_utf8(exc, &typename) < 0) {
+        assert(typename != NULL);
+        return typename;
+    }
+
+    // Extract the exception message.
+    const char *msg = NULL;
+    if (_exc_msg_as_utf8(exc, &msg) < 0) {
+        assert(msg != NULL);
+        return msg;
+    }
+
+    info->type = typename;
+    info->msg = msg;
+    return NULL;
+}
+
+static void
+_Py_excinfo_Apply(_Py_excinfo *info, PyObject *exctype)
+{
+    if (info->type != NULL) {
+        if (info->msg != NULL) {
+            PyErr_Format(exctype, "%s: %s",  info->type, info->msg);
+        }
+        else {
+            PyErr_SetString(exctype, info->type);
+        }
+    }
+    else if (info->msg != NULL) {
+        PyErr_SetString(exctype, info->msg);
+    }
+    else {
+        PyErr_SetNone(exctype);
+    }
+}
+
+
 /***************************/
 /* short-term data sharing */
 /***************************/
index c55ebfdb502d61ce67158ccd6429c5592b8fa6b8..ed5eec5c261970e005012748e0d0c3da40730df9 100644 (file)
@@ -1934,178 +1934,3 @@ PyErr_ProgramTextObject(PyObject *filename, int lineno)
 {
     return _PyErr_ProgramDecodedTextObject(filename, lineno, NULL);
 }
-
-
-/***********************/
-/* exception snapshots */
-/***********************/
-
-static const char *
-_copy_raw_string(const char *str)
-{
-    char *copied = PyMem_RawMalloc(strlen(str)+1);
-    if (copied == NULL) {
-        return NULL;
-    }
-    strcpy(copied, str);
-    return copied;
-}
-
-static int
-_exc_type_name_as_utf8(PyObject *exc, const char **p_typename)
-{
-    // XXX Use PyObject_GetAttrString(Py_TYPE(exc), '__name__')?
-    PyObject *nameobj = PyUnicode_FromString(Py_TYPE(exc)->tp_name);
-    if (nameobj == NULL) {
-        assert(PyErr_Occurred());
-        *p_typename = "unable to format exception type name";
-        return -1;
-    }
-    const char *name = PyUnicode_AsUTF8(nameobj);
-    if (name == NULL) {
-        assert(PyErr_Occurred());
-        Py_DECREF(nameobj);
-        *p_typename = "unable to encode exception type name";
-        return -1;
-    }
-    name = _copy_raw_string(name);
-    Py_DECREF(nameobj);
-    if (name == NULL) {
-        *p_typename = "out of memory copying exception type name";
-        return -1;
-    }
-    *p_typename = name;
-    return 0;
-}
-
-static int
-_exc_msg_as_utf8(PyObject *exc, const char **p_msg)
-{
-    PyObject *msgobj = PyObject_Str(exc);
-    if (msgobj == NULL) {
-        assert(PyErr_Occurred());
-        *p_msg = "unable to format exception message";
-        return -1;
-    }
-    const char *msg = PyUnicode_AsUTF8(msgobj);
-    if (msg == NULL) {
-        assert(PyErr_Occurred());
-        Py_DECREF(msgobj);
-        *p_msg = "unable to encode exception message";
-        return -1;
-    }
-    msg = _copy_raw_string(msg);
-    Py_DECREF(msgobj);
-    if (msg == NULL) {
-        assert(PyErr_ExceptionMatches(PyExc_MemoryError));
-        *p_msg = "out of memory copying exception message";
-        return -1;
-    }
-    *p_msg = msg;
-    return 0;
-}
-
-void
-_Py_excinfo_Clear(_Py_excinfo *info)
-{
-    if (info->type != NULL) {
-        PyMem_RawFree((void *)info->type);
-    }
-    if (info->msg != NULL) {
-        PyMem_RawFree((void *)info->msg);
-    }
-    *info = (_Py_excinfo){ NULL };
-}
-
-int
-_Py_excinfo_Copy(_Py_excinfo *dest, _Py_excinfo *src)
-{
-    // XXX Clear dest first?
-
-    if (src->type == NULL) {
-        dest->type = NULL;
-    }
-    else {
-        dest->type = _copy_raw_string(src->type);
-        if (dest->type == NULL) {
-            return -1;
-        }
-    }
-
-    if (src->msg == NULL) {
-        dest->msg = NULL;
-    }
-    else {
-        dest->msg = _copy_raw_string(src->msg);
-        if (dest->msg == NULL) {
-            return -1;
-        }
-    }
-
-    return 0;
-}
-
-const char *
-_Py_excinfo_InitFromException(_Py_excinfo *info, PyObject *exc)
-{
-    assert(exc != NULL);
-
-    // Extract the exception type name.
-    const char *typename = NULL;
-    if (_exc_type_name_as_utf8(exc, &typename) < 0) {
-        assert(typename != NULL);
-        return typename;
-    }
-
-    // Extract the exception message.
-    const char *msg = NULL;
-    if (_exc_msg_as_utf8(exc, &msg) < 0) {
-        assert(msg != NULL);
-        return msg;
-    }
-
-    info->type = typename;
-    info->msg = msg;
-    return NULL;
-}
-
-void
-_Py_excinfo_Apply(_Py_excinfo *info, PyObject *exctype)
-{
-    if (info->type != NULL) {
-        if (info->msg != NULL) {
-            PyErr_Format(exctype, "%s: %s",  info->type, info->msg);
-        }
-        else {
-            PyErr_SetString(exctype, info->type);
-        }
-    }
-    else if (info->msg != NULL) {
-        PyErr_SetString(exctype, info->msg);
-    }
-    else {
-        PyErr_SetNone(exctype);
-    }
-}
-
-const char *
-_Py_excinfo_AsUTF8(_Py_excinfo *info, char *buf, size_t bufsize)
-{
-    // XXX Dynamically allocate if no buf provided?
-    assert(buf != NULL);
-    if (info->type != NULL) {
-        if (info->msg != NULL) {
-            snprintf(buf, bufsize, "%s: %s",  info->type, info->msg);
-            return buf;
-        }
-        else {
-            return info->type;
-        }
-    }
-    else if (info->msg != NULL) {
-        return info->msg;
-    }
-    else {
-        return NULL;
-    }
-}