Skip to content

Navigation Menu

Sign in
Appearance settings

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Appearance settings

Commit 8ac1b5b

Browse filesBrowse files
ericsnowcurrentlyhugovk
authored andcommitted
pythongh-76785: Move _Py_excinfo Functions Out of the Internal C-API (pythongh-111715)
I added _Py_excinfo to the internal API (and added its functions in Python/errors.c) in pythongh-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 pythongh-111572/pythongh-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 pythongh-111572, which I may, in turn, combine with pythongh-111573. We'll see.)
1 parent 7af88ed commit 8ac1b5b
Copy full SHA for 8ac1b5b

File tree

Expand file treeCollapse file tree

4 files changed

+134
-199
lines changed
Filter options
Expand file treeCollapse file tree

4 files changed

+134
-199
lines changed

‎Include/internal/pycore_crossinterp.h

Copy file name to clipboardExpand all lines: Include/internal/pycore_crossinterp.h
+11Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -164,6 +164,17 @@ 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+
167178
typedef enum error_code {
168179
_PyXI_ERR_NO_ERROR = 0,
169180
_PyXI_ERR_UNCAUGHT_EXCEPTION = -1,

‎Include/internal/pycore_pyerrors.h

Copy file name to clipboardExpand all lines: Include/internal/pycore_pyerrors.h
-24Lines changed: 0 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -68,30 +68,6 @@ 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-
9571
/* other API */
9672

9773
static inline PyObject* _PyErr_Occurred(PyThreadState *tstate)

‎Python/crossinterp.c

Copy file name to clipboardExpand all lines: Python/crossinterp.c
+123Lines changed: 123 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -800,6 +800,17 @@ _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+
803814
static const char *
804815
_copy_string_obj_raw(PyObject *strobj)
805816
{
@@ -835,6 +846,118 @@ _release_xid_data(_PyCrossInterpreterData *data, int rawfree)
835846
}
836847

837848

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+
838961
/***************************/
839962
/* short-term data sharing */
840963
/***************************/

‎Python/errors.c

Copy file name to clipboardExpand all lines: Python/errors.c
-175Lines changed: 0 additions & 175 deletions
Original file line numberDiff line numberDiff line change
@@ -1934,178 +1934,3 @@ 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 (0)
Morty Proxy This is a proxified and sanitized view of the page, visit original site.