PYTHON-5032 - Use PyErr_GetRaisedException instead of deprecated PyEr… (#2795)
This commit is contained in:
parent
8dc7efade2
commit
b6bac45c7e
@ -109,6 +109,7 @@ struct module_state {
|
|||||||
#define DATETIME_CLAMP 2
|
#define DATETIME_CLAMP 2
|
||||||
#define DATETIME_MS 3
|
#define DATETIME_MS 3
|
||||||
#define DATETIME_AUTO 4
|
#define DATETIME_AUTO 4
|
||||||
|
#define PYTHON_3_12 0x030C0000
|
||||||
|
|
||||||
/* Converts integer to its string representation in decimal notation. */
|
/* Converts integer to its string representation in decimal notation. */
|
||||||
extern int cbson_long_long_to_str(long long num, char* str, size_t size) {
|
extern int cbson_long_long_to_str(long long num, char* str, size_t size) {
|
||||||
@ -249,6 +250,67 @@ static int _write_element_to_buffer(PyObject* self, buffer_t buffer,
|
|||||||
*/
|
*/
|
||||||
static int write_raw_doc(buffer_t buffer, PyObject* raw, PyObject* _raw);
|
static int write_raw_doc(buffer_t buffer, PyObject* raw, PyObject* _raw);
|
||||||
|
|
||||||
|
#if PY_VERSION_HEX >= PYTHON_3_12
|
||||||
|
/* Transfer traceback from old_exc to new_exc.
|
||||||
|
* Steals reference to old_exc. */
|
||||||
|
static PyObject* _transfer_traceback(PyObject *old_exc, PyObject *new_exc) {
|
||||||
|
PyObject *tb = PyException_GetTraceback(old_exc);
|
||||||
|
if (tb) {
|
||||||
|
PyException_SetTraceback(new_exc, tb);
|
||||||
|
Py_DECREF(tb);
|
||||||
|
}
|
||||||
|
Py_DECREF(old_exc);
|
||||||
|
return new_exc;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
/* Rewrap the current exception as InvalidBSON(str(e)) if it is not already an InvalidBSON error. */
|
||||||
|
static void _rewrap_as_invalid_bson(void) {
|
||||||
|
#if PY_VERSION_HEX >= PYTHON_3_12
|
||||||
|
PyObject *exc = PyErr_GetRaisedException();
|
||||||
|
if (exc && PyErr_GivenExceptionMatches(exc, PyExc_Exception)) {
|
||||||
|
PyObject *InvalidBSON = _error("InvalidBSON");
|
||||||
|
if (InvalidBSON) {
|
||||||
|
if (!PyErr_GivenExceptionMatches(exc, InvalidBSON)) {
|
||||||
|
PyObject *err_msg = PyObject_Str(exc);
|
||||||
|
if (err_msg) {
|
||||||
|
PyObject *new_exc = PyObject_CallOneArg(InvalidBSON, err_msg);
|
||||||
|
if (new_exc) {
|
||||||
|
exc = _transfer_traceback(exc, new_exc);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
Py_XDECREF(err_msg);
|
||||||
|
}
|
||||||
|
Py_DECREF(InvalidBSON);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
/* Steals reference to exc. */
|
||||||
|
PyErr_SetRaisedException(exc);
|
||||||
|
#else
|
||||||
|
PyObject *etype = NULL, *evalue = NULL, *etrace = NULL;
|
||||||
|
PyObject *InvalidBSON = NULL;
|
||||||
|
PyErr_Fetch(&etype, &evalue, &etrace);
|
||||||
|
if (PyErr_GivenExceptionMatches(etype, PyExc_Exception)) {
|
||||||
|
InvalidBSON = _error("InvalidBSON");
|
||||||
|
if (InvalidBSON) {
|
||||||
|
if (!PyErr_GivenExceptionMatches(etype, InvalidBSON)) {
|
||||||
|
Py_DECREF(etype);
|
||||||
|
etype = InvalidBSON;
|
||||||
|
if (evalue) {
|
||||||
|
PyObject *msg = PyObject_Str(evalue);
|
||||||
|
Py_DECREF(evalue);
|
||||||
|
evalue = msg;
|
||||||
|
}
|
||||||
|
PyErr_NormalizeException(&etype, &evalue, &etrace);
|
||||||
|
} else {
|
||||||
|
Py_DECREF(InvalidBSON);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
PyErr_Restore(etype, evalue, etrace);
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
/* Date stuff */
|
/* Date stuff */
|
||||||
static PyObject* datetime_from_millis(long long millis) {
|
static PyObject* datetime_from_millis(long long millis) {
|
||||||
/* To encode a datetime instance like datetime(9999, 12, 31, 23, 59, 59, 999999)
|
/* To encode a datetime instance like datetime(9999, 12, 31, 23, 59, 59, 999999)
|
||||||
@ -294,34 +356,57 @@ static PyObject* datetime_from_millis(long long millis) {
|
|||||||
timeinfo.tm_sec,
|
timeinfo.tm_sec,
|
||||||
microseconds);
|
microseconds);
|
||||||
if(!datetime) {
|
if(!datetime) {
|
||||||
PyObject *etype = NULL, *evalue = NULL, *etrace = NULL;
|
#if PY_VERSION_HEX >= PYTHON_3_12
|
||||||
|
PyObject *exc = PyErr_GetRaisedException();
|
||||||
|
|
||||||
/*
|
/* Only add additional error message on ValueError exceptions. */
|
||||||
* Calling _error clears the error state, so fetch it first.
|
if (exc && PyErr_GivenExceptionMatches(exc, PyExc_ValueError)) {
|
||||||
*/
|
PyObject* err_msg = PyObject_Str(exc);
|
||||||
PyErr_Fetch(&etype, &evalue, &etrace);
|
|
||||||
|
|
||||||
/* Only add addition error message on ValueError exceptions. */
|
|
||||||
if (PyErr_GivenExceptionMatches(etype, PyExc_ValueError)) {
|
|
||||||
if (evalue) {
|
|
||||||
PyObject* err_msg = PyObject_Str(evalue);
|
|
||||||
if (err_msg) {
|
if (err_msg) {
|
||||||
PyObject* appendage = PyUnicode_FromString(" (Consider Using CodecOptions(datetime_conversion=DATETIME_AUTO) or MongoClient(datetime_conversion='DATETIME_AUTO')). See: https://www.mongodb.com/docs/languages/python/pymongo-driver/current/data-formats/dates-and-times/#handling-out-of-range-datetimes");
|
PyObject* appendage = PyUnicode_FromString(" (Consider Using CodecOptions(datetime_conversion=DATETIME_AUTO) or MongoClient(datetime_conversion='DATETIME_AUTO')). See: https://www.mongodb.com/docs/languages/python/pymongo-driver/current/data-formats/dates-and-times/#handling-out-of-range-datetimes");
|
||||||
if (appendage) {
|
if (appendage) {
|
||||||
PyObject* msg = PyUnicode_Concat(err_msg, appendage);
|
PyObject* msg = PyUnicode_Concat(err_msg, appendage);
|
||||||
if (msg) {
|
if (msg) {
|
||||||
Py_DECREF(evalue);
|
PyObject* new_exc = PyObject_CallOneArg(PyExc_ValueError, msg);
|
||||||
evalue = msg;
|
if (new_exc) {
|
||||||
|
exc = _transfer_traceback(exc, new_exc);
|
||||||
|
}
|
||||||
|
Py_DECREF(msg);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
Py_XDECREF(appendage);
|
Py_XDECREF(appendage);
|
||||||
}
|
}
|
||||||
Py_XDECREF(err_msg);
|
Py_XDECREF(err_msg);
|
||||||
}
|
}
|
||||||
PyErr_NormalizeException(&etype, &evalue, &etrace);
|
/* Steals reference to exc. */
|
||||||
}
|
PyErr_SetRaisedException(exc);
|
||||||
/* Steals references to args. */
|
#else
|
||||||
PyErr_Restore(etype, evalue, etrace);
|
/* Calling _error clears the error state, so fetch it first.*/
|
||||||
|
PyObject *etype = NULL, *evalue = NULL, *etrace = NULL;
|
||||||
|
PyErr_Fetch(&etype, &evalue, &etrace);
|
||||||
|
|
||||||
|
/* Only add additional error message on ValueError exceptions. */
|
||||||
|
if (PyErr_GivenExceptionMatches(etype, PyExc_ValueError)) {
|
||||||
|
if (evalue) {
|
||||||
|
PyObject* err_msg = PyObject_Str(evalue);
|
||||||
|
if (err_msg) {
|
||||||
|
PyObject* appendage = PyUnicode_FromString(" (Consider Using CodecOptions(datetime_conversion=DATETIME_AUTO) or MongoClient(datetime_conversion='DATETIME_AUTO')). See: https://www.mongodb.com/docs/languages/python/pymongo-driver/current/data-formats/dates-and-times/#handling-out-of-range-datetimes");
|
||||||
|
if (appendage) {
|
||||||
|
PyObject* msg = PyUnicode_Concat(err_msg, appendage);
|
||||||
|
if (msg) {
|
||||||
|
Py_DECREF(evalue);
|
||||||
|
evalue = msg;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
Py_XDECREF(appendage);
|
||||||
|
}
|
||||||
|
Py_XDECREF(err_msg);
|
||||||
|
}
|
||||||
|
PyErr_NormalizeException(&etype, &evalue, &etrace);
|
||||||
|
}
|
||||||
|
/* Steals references to args. */
|
||||||
|
PyErr_Restore(etype, evalue, etrace);
|
||||||
|
#endif
|
||||||
}
|
}
|
||||||
return datetime;
|
return datetime;
|
||||||
}
|
}
|
||||||
@ -1681,6 +1766,46 @@ fail:
|
|||||||
/* Update Invalid Document error to include doc as a property.
|
/* Update Invalid Document error to include doc as a property.
|
||||||
*/
|
*/
|
||||||
void handle_invalid_doc_error(PyObject* dict) {
|
void handle_invalid_doc_error(PyObject* dict) {
|
||||||
|
#if PY_VERSION_HEX >= PYTHON_3_12
|
||||||
|
PyObject *exc = PyErr_GetRaisedException();
|
||||||
|
PyObject *msg = NULL, *new_msg = NULL;
|
||||||
|
PyObject *InvalidDocument = NULL;
|
||||||
|
|
||||||
|
if (exc == NULL) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
InvalidDocument = _error("InvalidDocument");
|
||||||
|
if (InvalidDocument == NULL) {
|
||||||
|
goto cleanup;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (PyErr_GivenExceptionMatches(exc, InvalidDocument)) {
|
||||||
|
msg = PyObject_Str(exc);
|
||||||
|
if (msg) {
|
||||||
|
const char *msg_utf8 = PyUnicode_AsUTF8(msg);
|
||||||
|
if (msg_utf8 == NULL) {
|
||||||
|
goto cleanup;
|
||||||
|
}
|
||||||
|
new_msg = PyUnicode_FromFormat("Invalid document: %s", msg_utf8);
|
||||||
|
if (new_msg == NULL) {
|
||||||
|
goto cleanup;
|
||||||
|
}
|
||||||
|
/* Add doc to the error instance as a property. */
|
||||||
|
PyObject* exc_args[2] = {new_msg, dict};
|
||||||
|
PyObject* new_exc = PyObject_Vectorcall(InvalidDocument, exc_args, 2, NULL);
|
||||||
|
if (new_exc) {
|
||||||
|
exc = _transfer_traceback(exc, new_exc);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
cleanup:
|
||||||
|
/* Steals reference to exc. */
|
||||||
|
PyErr_SetRaisedException(exc);
|
||||||
|
Py_XDECREF(msg);
|
||||||
|
Py_XDECREF(InvalidDocument);
|
||||||
|
Py_XDECREF(new_msg);
|
||||||
|
#else
|
||||||
PyObject *etype = NULL, *evalue = NULL, *etrace = NULL;
|
PyObject *etype = NULL, *evalue = NULL, *etrace = NULL;
|
||||||
PyObject *msg = NULL, *new_msg = NULL, *new_evalue = NULL;
|
PyObject *msg = NULL, *new_msg = NULL, *new_evalue = NULL;
|
||||||
PyErr_Fetch(&etype, &evalue, &etrace);
|
PyErr_Fetch(&etype, &evalue, &etrace);
|
||||||
@ -1723,6 +1848,7 @@ cleanup:
|
|||||||
Py_XDECREF(InvalidDocument);
|
Py_XDECREF(InvalidDocument);
|
||||||
Py_XDECREF(new_evalue);
|
Py_XDECREF(new_evalue);
|
||||||
Py_XDECREF(new_msg);
|
Py_XDECREF(new_msg);
|
||||||
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@ -2654,42 +2780,7 @@ static PyObject* get_value(PyObject* self, PyObject* name, const char* buffer,
|
|||||||
* Wrap any non-InvalidBSON errors in InvalidBSON.
|
* Wrap any non-InvalidBSON errors in InvalidBSON.
|
||||||
*/
|
*/
|
||||||
if (PyErr_Occurred()) {
|
if (PyErr_Occurred()) {
|
||||||
PyObject *etype = NULL, *evalue = NULL, *etrace = NULL;
|
_rewrap_as_invalid_bson();
|
||||||
PyObject *InvalidBSON = NULL;
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Calling _error clears the error state, so fetch it first.
|
|
||||||
*/
|
|
||||||
PyErr_Fetch(&etype, &evalue, &etrace);
|
|
||||||
|
|
||||||
/* Dont reraise anything but PyExc_Exceptions as InvalidBSON. */
|
|
||||||
if (PyErr_GivenExceptionMatches(etype, PyExc_Exception)) {
|
|
||||||
InvalidBSON = _error("InvalidBSON");
|
|
||||||
if (InvalidBSON) {
|
|
||||||
if (!PyErr_GivenExceptionMatches(etype, InvalidBSON)) {
|
|
||||||
/*
|
|
||||||
* Raise InvalidBSON(str(e)).
|
|
||||||
*/
|
|
||||||
Py_DECREF(etype);
|
|
||||||
etype = InvalidBSON;
|
|
||||||
|
|
||||||
if (evalue) {
|
|
||||||
PyObject *msg = PyObject_Str(evalue);
|
|
||||||
Py_DECREF(evalue);
|
|
||||||
evalue = msg;
|
|
||||||
}
|
|
||||||
PyErr_NormalizeException(&etype, &evalue, &etrace);
|
|
||||||
} else {
|
|
||||||
/*
|
|
||||||
* The current exception matches InvalidBSON, so we don't
|
|
||||||
* need this reference after all.
|
|
||||||
*/
|
|
||||||
Py_DECREF(InvalidBSON);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
/* Steals references to args. */
|
|
||||||
PyErr_Restore(etype, evalue, etrace);
|
|
||||||
} else {
|
} else {
|
||||||
PyObject *InvalidBSON = _error("InvalidBSON");
|
PyObject *InvalidBSON = _error("InvalidBSON");
|
||||||
if (InvalidBSON) {
|
if (InvalidBSON) {
|
||||||
@ -2727,25 +2818,7 @@ static int _element_to_dict(PyObject* self, const char* string,
|
|||||||
if (!*name) {
|
if (!*name) {
|
||||||
/* If NULL is returned then wrap the UnicodeDecodeError
|
/* If NULL is returned then wrap the UnicodeDecodeError
|
||||||
in an InvalidBSON error */
|
in an InvalidBSON error */
|
||||||
PyObject *etype = NULL, *evalue = NULL, *etrace = NULL;
|
_rewrap_as_invalid_bson();
|
||||||
PyObject *InvalidBSON = NULL;
|
|
||||||
|
|
||||||
PyErr_Fetch(&etype, &evalue, &etrace);
|
|
||||||
if (PyErr_GivenExceptionMatches(etype, PyExc_Exception)) {
|
|
||||||
InvalidBSON = _error("InvalidBSON");
|
|
||||||
if (InvalidBSON) {
|
|
||||||
Py_DECREF(etype);
|
|
||||||
etype = InvalidBSON;
|
|
||||||
|
|
||||||
if (evalue) {
|
|
||||||
PyObject *msg = PyObject_Str(evalue);
|
|
||||||
Py_DECREF(evalue);
|
|
||||||
evalue = msg;
|
|
||||||
}
|
|
||||||
PyErr_NormalizeException(&etype, &evalue, &etrace);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
PyErr_Restore(etype, evalue, etrace);
|
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
position += (unsigned)name_length + 1;
|
position += (unsigned)name_length + 1;
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user