bpo-45711: Change exc_info related APIs to derive type and traceback … · python/cpython@8a45ca5

@@ -470,25 +470,43 @@ PyErr_Clear(void)

470470

_PyErr_Clear(tstate);

471471

}

472472473+

static PyObject*

474+

get_exc_type(PyObject *exc_value) /* returns a borrowed ref */

475+

{

476+

if (exc_value == NULL || exc_value == Py_None) {

477+

return Py_None;

478+

}

479+

else {

480+

assert(PyExceptionInstance_Check(exc_value));

481+

PyObject *type = PyExceptionInstance_Class(exc_value);

482+

assert(type != NULL);

483+

return type;

484+

}

485+

}

486+487+

static PyObject*

488+

get_exc_traceback(PyObject *exc_value) /* returns a borrowed ref */

489+

{

490+

if (exc_value == NULL || exc_value == Py_None) {

491+

return Py_None;

492+

}

493+

else {

494+

assert(PyExceptionInstance_Check(exc_value));

495+

PyObject *tb = PyException_GetTraceback(exc_value);

496+

Py_XDECREF(tb);

497+

return tb ? tb : Py_None;

498+

}

499+

}

473500474501

void

475502

_PyErr_GetExcInfo(PyThreadState *tstate,

476503

PyObject **p_type, PyObject **p_value, PyObject **p_traceback)

477504

{

478505

_PyErr_StackItem *exc_info = _PyErr_GetTopmostException(tstate);

479506507+

*p_type = get_exc_type(exc_info->exc_value);

480508

*p_value = exc_info->exc_value;

481-

*p_traceback = exc_info->exc_traceback;

482-483-

if (*p_value == NULL || *p_value == Py_None) {

484-

assert(exc_info->exc_type == NULL || exc_info->exc_type == Py_None);

485-

*p_type = Py_None;

486-

}

487-

else {

488-

assert(PyExceptionInstance_Check(*p_value));

489-

assert(exc_info->exc_type == PyExceptionInstance_Class(*p_value));

490-

*p_type = PyExceptionInstance_Class(*p_value);

491-

}

509+

*p_traceback = get_exc_traceback(exc_info->exc_value);

492510493511

Py_XINCREF(*p_type);

494512

Py_XINCREF(*p_value);

@@ -504,7 +522,7 @@ PyErr_GetExcInfo(PyObject **p_type, PyObject **p_value, PyObject **p_traceback)

504522

}

505523506524

void

507-

PyErr_SetExcInfo(PyObject *p_type, PyObject *p_value, PyObject *p_traceback)

525+

PyErr_SetExcInfo(PyObject *type, PyObject *value, PyObject *traceback)

508526

{

509527

PyObject *oldtype, *oldvalue, *oldtraceback;

510528

PyThreadState *tstate = _PyThreadState_GET();

@@ -513,9 +531,16 @@ PyErr_SetExcInfo(PyObject *p_type, PyObject *p_value, PyObject *p_traceback)

513531

oldvalue = tstate->exc_info->exc_value;

514532

oldtraceback = tstate->exc_info->exc_traceback;

515533516-

tstate->exc_info->exc_type = p_type;

517-

tstate->exc_info->exc_value = p_value;

518-

tstate->exc_info->exc_traceback = p_traceback;

534+535+

tstate->exc_info->exc_type = get_exc_type(value);

536+

Py_XINCREF(tstate->exc_info->exc_type);

537+

tstate->exc_info->exc_value = value;

538+

tstate->exc_info->exc_traceback = get_exc_traceback(value);

539+

Py_XINCREF(tstate->exc_info->exc_traceback);

540+541+

/* These args are no longer used, but we still need to steal a ref */

542+

Py_XDECREF(type);

543+

Py_XDECREF(traceback);

519544520545

Py_XDECREF(oldtype);

521546

Py_XDECREF(oldvalue);

@@ -527,22 +552,19 @@ PyObject*

527552

_PyErr_StackItemToExcInfoTuple(_PyErr_StackItem *err_info)

528553

{

529554

PyObject *exc_value = err_info->exc_value;

530-

if (exc_value == NULL) {

531-

exc_value = Py_None;

532-

}

533555534-

assert(exc_value == Py_None || PyExceptionInstance_Check(exc_value));

556+

assert(exc_value == NULL ||

557+

exc_value == Py_None ||

558+

PyExceptionInstance_Check(exc_value));

535559536-

PyObject *exc_type = PyExceptionInstance_Check(exc_value) ?

537-

PyExceptionInstance_Class(exc_value) :

538-

Py_None;

560+

PyObject *exc_type = get_exc_type(exc_value);

561+

PyObject *exc_traceback = get_exc_traceback(exc_value);

539562540563

return Py_BuildValue(

541564

"(OOO)",

542-

exc_type,

543-

exc_value,

544-

err_info->exc_traceback != NULL ?

545-

err_info->exc_traceback : Py_None);

565+

exc_type ? exc_type : Py_None,

566+

exc_value ? exc_value : Py_None,

567+

exc_traceback ? exc_traceback : Py_None);

546568

}

547569548570