Skip to content

Commit 177e4b1

Browse files
Revert "pythongh-76785: Move _Py_excinfo Functions Out of the Internal C-API (pythongh-111715)"
This reverts commit d4426e8.
1 parent d4426e8 commit 177e4b1

4 files changed

Lines changed: 199 additions & 134 deletions

File tree

Include/internal/pycore_crossinterp.h

Lines changed: 0 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -164,17 +164,6 @@ extern void _PyXI_Fini(PyInterpreterState *interp);
164164
/* short-term data sharing */
165165
/***************************/
166166

167-
// Ultimately we'd like to preserve enough information about the
168-
// exception and traceback that we could re-constitute (or at least
169-
// simulate, a la traceback.TracebackException), and even chain, a copy
170-
// of the exception in the calling interpreter.
171-
172-
typedef struct _excinfo {
173-
const char *type;
174-
const char *msg;
175-
} _Py_excinfo;
176-
177-
178167
typedef enum error_code {
179168
_PyXI_ERR_NO_ERROR = 0,
180169
_PyXI_ERR_UNCAUGHT_EXCEPTION = -1,

Include/internal/pycore_pyerrors.h

Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -68,6 +68,30 @@ extern PyStatus _PyErr_InitTypes(PyInterpreterState *);
6868
extern void _PyErr_FiniTypes(PyInterpreterState *);
6969

7070

71+
/* exception snapshots */
72+
73+
// Ultimately we'd like to preserve enough information about the
74+
// exception and traceback that we could re-constitute (or at least
75+
// simulate, a la traceback.TracebackException), and even chain, a copy
76+
// of the exception in the calling interpreter.
77+
78+
typedef struct _excinfo {
79+
const char *type;
80+
const char *msg;
81+
} _Py_excinfo;
82+
83+
extern void _Py_excinfo_Clear(_Py_excinfo *info);
84+
extern int _Py_excinfo_Copy(_Py_excinfo *dest, _Py_excinfo *src);
85+
extern const char * _Py_excinfo_InitFromException(
86+
_Py_excinfo *info,
87+
PyObject *exc);
88+
extern void _Py_excinfo_Apply(_Py_excinfo *info, PyObject *exctype);
89+
extern const char * _Py_excinfo_AsUTF8(
90+
_Py_excinfo *info,
91+
char *buf,
92+
size_t bufsize);
93+
94+
7195
/* other API */
7296

7397
static inline PyObject* _PyErr_Occurred(PyThreadState *tstate)

Python/crossinterp.c

Lines changed: 0 additions & 123 deletions
Original file line numberDiff line numberDiff line change
@@ -800,17 +800,6 @@ _xidregistry_fini(struct _xidregistry *registry)
800800
/* convenience utilities */
801801
/*************************/
802802

803-
static const char *
804-
_copy_raw_string(const char *str)
805-
{
806-
char *copied = PyMem_RawMalloc(strlen(str)+1);
807-
if (copied == NULL) {
808-
return NULL;
809-
}
810-
strcpy(copied, str);
811-
return copied;
812-
}
813-
814803
static const char *
815804
_copy_string_obj_raw(PyObject *strobj)
816805
{
@@ -846,118 +835,6 @@ _release_xid_data(_PyCrossInterpreterData *data, int rawfree)
846835
}
847836

848837

849-
/* exception snapshots */
850-
851-
static int
852-
_exc_type_name_as_utf8(PyObject *exc, const char **p_typename)
853-
{
854-
// XXX Use PyObject_GetAttrString(Py_TYPE(exc), '__name__')?
855-
PyObject *nameobj = PyUnicode_FromString(Py_TYPE(exc)->tp_name);
856-
if (nameobj == NULL) {
857-
assert(PyErr_Occurred());
858-
*p_typename = "unable to format exception type name";
859-
return -1;
860-
}
861-
const char *name = PyUnicode_AsUTF8(nameobj);
862-
if (name == NULL) {
863-
assert(PyErr_Occurred());
864-
Py_DECREF(nameobj);
865-
*p_typename = "unable to encode exception type name";
866-
return -1;
867-
}
868-
name = _copy_raw_string(name);
869-
Py_DECREF(nameobj);
870-
if (name == NULL) {
871-
*p_typename = "out of memory copying exception type name";
872-
return -1;
873-
}
874-
*p_typename = name;
875-
return 0;
876-
}
877-
878-
static int
879-
_exc_msg_as_utf8(PyObject *exc, const char **p_msg)
880-
{
881-
PyObject *msgobj = PyObject_Str(exc);
882-
if (msgobj == NULL) {
883-
assert(PyErr_Occurred());
884-
*p_msg = "unable to format exception message";
885-
return -1;
886-
}
887-
const char *msg = PyUnicode_AsUTF8(msgobj);
888-
if (msg == NULL) {
889-
assert(PyErr_Occurred());
890-
Py_DECREF(msgobj);
891-
*p_msg = "unable to encode exception message";
892-
return -1;
893-
}
894-
msg = _copy_raw_string(msg);
895-
Py_DECREF(msgobj);
896-
if (msg == NULL) {
897-
assert(PyErr_ExceptionMatches(PyExc_MemoryError));
898-
*p_msg = "out of memory copying exception message";
899-
return -1;
900-
}
901-
*p_msg = msg;
902-
return 0;
903-
}
904-
905-
static void
906-
_Py_excinfo_Clear(_Py_excinfo *info)
907-
{
908-
if (info->type != NULL) {
909-
PyMem_RawFree((void *)info->type);
910-
}
911-
if (info->msg != NULL) {
912-
PyMem_RawFree((void *)info->msg);
913-
}
914-
*info = (_Py_excinfo){ NULL };
915-
}
916-
917-
static const char *
918-
_Py_excinfo_InitFromException(_Py_excinfo *info, PyObject *exc)
919-
{
920-
assert(exc != NULL);
921-
922-
// Extract the exception type name.
923-
const char *typename = NULL;
924-
if (_exc_type_name_as_utf8(exc, &typename) < 0) {
925-
assert(typename != NULL);
926-
return typename;
927-
}
928-
929-
// Extract the exception message.
930-
const char *msg = NULL;
931-
if (_exc_msg_as_utf8(exc, &msg) < 0) {
932-
assert(msg != NULL);
933-
return msg;
934-
}
935-
936-
info->type = typename;
937-
info->msg = msg;
938-
return NULL;
939-
}
940-
941-
static void
942-
_Py_excinfo_Apply(_Py_excinfo *info, PyObject *exctype)
943-
{
944-
if (info->type != NULL) {
945-
if (info->msg != NULL) {
946-
PyErr_Format(exctype, "%s: %s", info->type, info->msg);
947-
}
948-
else {
949-
PyErr_SetString(exctype, info->type);
950-
}
951-
}
952-
else if (info->msg != NULL) {
953-
PyErr_SetString(exctype, info->msg);
954-
}
955-
else {
956-
PyErr_SetNone(exctype);
957-
}
958-
}
959-
960-
961838
/***************************/
962839
/* short-term data sharing */
963840
/***************************/

Python/errors.c

Lines changed: 175 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1934,3 +1934,178 @@ PyErr_ProgramTextObject(PyObject *filename, int lineno)
19341934
{
19351935
return _PyErr_ProgramDecodedTextObject(filename, lineno, NULL);
19361936
}
1937+
1938+
1939+
/***********************/
1940+
/* exception snapshots */
1941+
/***********************/
1942+
1943+
static const char *
1944+
_copy_raw_string(const char *str)
1945+
{
1946+
char *copied = PyMem_RawMalloc(strlen(str)+1);
1947+
if (copied == NULL) {
1948+
return NULL;
1949+
}
1950+
strcpy(copied, str);
1951+
return copied;
1952+
}
1953+
1954+
static int
1955+
_exc_type_name_as_utf8(PyObject *exc, const char **p_typename)
1956+
{
1957+
// XXX Use PyObject_GetAttrString(Py_TYPE(exc), '__name__')?
1958+
PyObject *nameobj = PyUnicode_FromString(Py_TYPE(exc)->tp_name);
1959+
if (nameobj == NULL) {
1960+
assert(PyErr_Occurred());
1961+
*p_typename = "unable to format exception type name";
1962+
return -1;
1963+
}
1964+
const char *name = PyUnicode_AsUTF8(nameobj);
1965+
if (name == NULL) {
1966+
assert(PyErr_Occurred());
1967+
Py_DECREF(nameobj);
1968+
*p_typename = "unable to encode exception type name";
1969+
return -1;
1970+
}
1971+
name = _copy_raw_string(name);
1972+
Py_DECREF(nameobj);
1973+
if (name == NULL) {
1974+
*p_typename = "out of memory copying exception type name";
1975+
return -1;
1976+
}
1977+
*p_typename = name;
1978+
return 0;
1979+
}
1980+
1981+
static int
1982+
_exc_msg_as_utf8(PyObject *exc, const char **p_msg)
1983+
{
1984+
PyObject *msgobj = PyObject_Str(exc);
1985+
if (msgobj == NULL) {
1986+
assert(PyErr_Occurred());
1987+
*p_msg = "unable to format exception message";
1988+
return -1;
1989+
}
1990+
const char *msg = PyUnicode_AsUTF8(msgobj);
1991+
if (msg == NULL) {
1992+
assert(PyErr_Occurred());
1993+
Py_DECREF(msgobj);
1994+
*p_msg = "unable to encode exception message";
1995+
return -1;
1996+
}
1997+
msg = _copy_raw_string(msg);
1998+
Py_DECREF(msgobj);
1999+
if (msg == NULL) {
2000+
assert(PyErr_ExceptionMatches(PyExc_MemoryError));
2001+
*p_msg = "out of memory copying exception message";
2002+
return -1;
2003+
}
2004+
*p_msg = msg;
2005+
return 0;
2006+
}
2007+
2008+
void
2009+
_Py_excinfo_Clear(_Py_excinfo *info)
2010+
{
2011+
if (info->type != NULL) {
2012+
PyMem_RawFree((void *)info->type);
2013+
}
2014+
if (info->msg != NULL) {
2015+
PyMem_RawFree((void *)info->msg);
2016+
}
2017+
*info = (_Py_excinfo){ NULL };
2018+
}
2019+
2020+
int
2021+
_Py_excinfo_Copy(_Py_excinfo *dest, _Py_excinfo *src)
2022+
{
2023+
// XXX Clear dest first?
2024+
2025+
if (src->type == NULL) {
2026+
dest->type = NULL;
2027+
}
2028+
else {
2029+
dest->type = _copy_raw_string(src->type);
2030+
if (dest->type == NULL) {
2031+
return -1;
2032+
}
2033+
}
2034+
2035+
if (src->msg == NULL) {
2036+
dest->msg = NULL;
2037+
}
2038+
else {
2039+
dest->msg = _copy_raw_string(src->msg);
2040+
if (dest->msg == NULL) {
2041+
return -1;
2042+
}
2043+
}
2044+
2045+
return 0;
2046+
}
2047+
2048+
const char *
2049+
_Py_excinfo_InitFromException(_Py_excinfo *info, PyObject *exc)
2050+
{
2051+
assert(exc != NULL);
2052+
2053+
// Extract the exception type name.
2054+
const char *typename = NULL;
2055+
if (_exc_type_name_as_utf8(exc, &typename) < 0) {
2056+
assert(typename != NULL);
2057+
return typename;
2058+
}
2059+
2060+
// Extract the exception message.
2061+
const char *msg = NULL;
2062+
if (_exc_msg_as_utf8(exc, &msg) < 0) {
2063+
assert(msg != NULL);
2064+
return msg;
2065+
}
2066+
2067+
info->type = typename;
2068+
info->msg = msg;
2069+
return NULL;
2070+
}
2071+
2072+
void
2073+
_Py_excinfo_Apply(_Py_excinfo *info, PyObject *exctype)
2074+
{
2075+
if (info->type != NULL) {
2076+
if (info->msg != NULL) {
2077+
PyErr_Format(exctype, "%s: %s", info->type, info->msg);
2078+
}
2079+
else {
2080+
PyErr_SetString(exctype, info->type);
2081+
}
2082+
}
2083+
else if (info->msg != NULL) {
2084+
PyErr_SetString(exctype, info->msg);
2085+
}
2086+
else {
2087+
PyErr_SetNone(exctype);
2088+
}
2089+
}
2090+
2091+
const char *
2092+
_Py_excinfo_AsUTF8(_Py_excinfo *info, char *buf, size_t bufsize)
2093+
{
2094+
// XXX Dynamically allocate if no buf provided?
2095+
assert(buf != NULL);
2096+
if (info->type != NULL) {
2097+
if (info->msg != NULL) {
2098+
snprintf(buf, bufsize, "%s: %s", info->type, info->msg);
2099+
return buf;
2100+
}
2101+
else {
2102+
return info->type;
2103+
}
2104+
}
2105+
else if (info->msg != NULL) {
2106+
return info->msg;
2107+
}
2108+
else {
2109+
return NULL;
2110+
}
2111+
}

0 commit comments

Comments
 (0)