@@ -346,6 +346,33 @@ class error_already_set : public std::runtime_error {
346
346
// / the given tuple.
347
347
bool matches (handle exc) const { return PyErr_GivenExceptionMatches (m_type.ptr (), exc.ptr ()); }
348
348
349
+ // / Replaces the currently held error with the chosen error, performing a 'raise from' to make
350
+ // / the new error caused by the original error
351
+ void caused (PyObject *type, const char *message) {
352
+ // from cpython/errors.c _PyErr_FormatVFromCause
353
+ PyObject *exc, *val, *val2, *tb;
354
+ exc = m_type.release ().ptr ();
355
+ val = m_value.release ().ptr ();
356
+ tb = m_trace.release ().ptr ();
357
+
358
+ PyErr_NormalizeException (&exc, &val, &tb);
359
+ if (tb != nullptr ) {
360
+ PyException_SetTraceback (val, tb);
361
+ Py_DECREF (tb);
362
+ }
363
+ Py_DECREF (exc);
364
+
365
+ PyErr_SetString (type, message);
366
+ PyErr_Fetch (&exc, &val2, &tb);
367
+ PyErr_NormalizeException (&exc, &val2, &tb);
368
+ Py_INCREF (val);
369
+ PyException_SetCause (val2, val);
370
+ PyException_SetContext (val2, val);
371
+ m_type = reinterpret_steal<object>(exc);
372
+ if (val2) { m_value = reinterpret_steal<object>(val2); }
373
+ if (tb) { m_trace = reinterpret_steal<object>(tb); }
374
+ }
375
+
349
376
const object& type () const { return m_type; }
350
377
const object& value () const { return m_value; }
351
378
const object& trace () const { return m_trace; }
0 commit comments