@@ -602,25 +602,79 @@ const char* pesapi_get_exception_as_string(pesapi_scope pscope, int with_stack)
602602 {
603603 return nullptr ;
604604 }
605- auto ex = scope->caught ->ex ;
606- auto globals = PyModule_GetDict (PyImport_AddModule (" __main__" ));
607- PyDict_SetItem (globals, PyUnicode_FromString (" __pesapi_last_exception" ), ex);
608- const char * ret;
605+
606+ const char * ret = nullptr ;
609607 if (with_stack)
610608 {
611- PyRun_SimpleString (
612- " import traceback\n "
613- " try:\n "
614- " raise __pesapi_last_exception\n "
615- " except Exception as e:\n "
616- " __pesapi_last_exception_str = ''.join(traceback.format_exception(type(e), e, e.__traceback__))\n " );
617- ret = PyUnicode_AsUTF8 (PyDict_GetItem (globals, PyUnicode_FromString (" __pesapi_last_exception_str" )));
609+ #if PY_MAJOR_VERSION == 3 && PY_MINOR_VERSION >= 12
610+ auto tracebackModule = PyImport_ImportModule (" traceback" );
611+ auto value = scope->caught ->value ;
612+ auto type = Py_TYPE (value);
613+ auto traceback = PyObject_GetAttrString (value, " __traceback__" );
614+ if (traceback && traceback != Py_None)
615+ {
616+ if (PyObject* formatExceptionFunc = PyObject_GetAttrString (tracebackModule, " format_exception" );
617+ formatExceptionFunc && PyCallable_Check (formatExceptionFunc))
618+ {
619+ PyObject* formattedList = PyObject_CallFunctionObjArgs (formatExceptionFunc, type, value, traceback, nullptr );
620+ auto formattedStr = PyUnicode_Join (PyUnicode_FromString (" " ), formattedList);
621+ ret = strdup (PyUnicode_AsUTF8 (formattedStr));
622+ Py_DECREF (formattedStr);
623+ Py_DECREF (formattedList);
624+ Py_DECREF (formatExceptionFunc);
625+ }
626+ }
627+ else
628+ {
629+ if (PyObject* formatExceptionOnlyFunc = PyObject_GetAttrString (tracebackModule, " format_exception_only" );
630+ formatExceptionOnlyFunc && PyCallable_Check (formatExceptionOnlyFunc))
631+ {
632+ PyObject* formattedList = PyObject_CallFunctionObjArgs (formatExceptionOnlyFunc, type, value, nullptr );
633+ auto formattedStr = PyUnicode_Join (PyUnicode_FromString (" " ), formattedList);
634+ ret = strdup (PyUnicode_AsUTF8 (formattedStr));
635+ Py_DECREF (formattedStr);
636+ Py_DECREF (formattedList);
637+ Py_DECREF (formatExceptionOnlyFunc);
638+ }
639+ }
640+ #else
641+ auto tracebackModule = PyImport_ImportModule (" traceback" );
642+ PyErr_NormalizeException (&scope->caught ->type , &scope->caught ->value , &scope->caught ->traceback );
643+ auto traceback = scope->caught ->traceback ;
644+ auto type = scope->caught ->type ;
645+ auto value = scope->caught ->value ;
646+ if (traceback)
647+ {
648+ if (PyObject* formatExceptionFunc = PyObject_GetAttrString (tracebackModule, " format_exception" );
649+ formatExceptionFunc && PyCallable_Check (formatExceptionFunc))
650+ {
651+ PyObject* formattedList = PyObject_CallFunctionObjArgs (formatExceptionFunc, type, value, traceback, nullptr );
652+ auto formattedStr = PyUnicode_Join (PyUnicode_FromString (" " ), formattedList);
653+ ret = strdup (PyUnicode_AsUTF8 (formattedStr));
654+ Py_DECREF (formattedStr);
655+ Py_DECREF (formattedList);
656+ Py_DECREF (formatExceptionFunc);
657+ }
658+ }
659+ else
660+ {
661+ if (PyObject* formatExceptionOnlyFunc = PyObject_GetAttrString (tracebackModule, " format_exception_only" );
662+ formatExceptionOnlyFunc && PyCallable_Check (formatExceptionOnlyFunc))
663+ {
664+ PyObject* formattedList = PyObject_CallFunctionObjArgs (formatExceptionOnlyFunc, type, value, nullptr );
665+ auto formattedStr = PyUnicode_Join (PyUnicode_FromString (" " ), formattedList);
666+ ret = strdup (PyUnicode_AsUTF8 (formattedStr));
667+ Py_DECREF (formattedStr);
668+ Py_DECREF (formattedList);
669+ Py_DECREF (formatExceptionOnlyFunc);
670+ }
671+ }
672+ #endif
618673 }
619674 else
620675 {
621- ret = PyUnicode_AsUTF8 (PyObject_Str (ex ));
676+ ret = PyUnicode_AsUTF8 (PyObject_Str (scope-> caught -> value ));
622677 }
623- PyDict_DelItemString (globals, " __pesapi_last_exception" );
624678 return ret;
625679}
626680
@@ -780,16 +834,13 @@ pesapi_value pesapi_call_function(
780834 else
781835 {
782836 auto scope = (pesapi_scope__*)mapper->getCurrentScope ();
783- #if PY_VERSION_HEX >= 0x030B0000
837+ #if PY_MAJOR_VERSION == 3 && PY_MINOR_VERSION >= 12
784838 scope->setCaughtException (PyErr_GetRaisedException ());
785839#else
786840 {
787- PyObject *type = nullptr , *value = nullptr , *tb = nullptr ;
788- PyErr_Fetch (&type, &value, &tb);
789- PyObject *exc = value ? value : type;
790- if (exc) Py_XINCREF (exc);
791- PyErr_Restore (type, value, tb);
792- scope->setCaughtException (exc);
841+ PyObject *type = nullptr , *value = nullptr , *traceback = nullptr ;
842+ PyErr_Fetch (&type, &value, &traceback);
843+ scope->setCaughtException (type, value, traceback);
793844 }
794845#endif
795846 return nullptr ;
@@ -816,16 +867,13 @@ pesapi_value pesapi_eval(pesapi_env env, const uint8_t* code, size_t code_size,
816867 }
817868 }
818869 auto scope = (pesapi_scope__*)mapper->getCurrentScope ();
819- #if PY_VERSION_HEX >= 0x030B0000
870+ #if PY_MAJOR_VERSION == 3 && PY_MINOR_VERSION >= 12
820871 scope->setCaughtException (PyErr_GetRaisedException ());
821872#else
822873 {
823- PyObject *type = nullptr , *value = nullptr , *tb = nullptr ;
824- PyErr_Fetch (&type, &value, &tb);
825- PyObject *exc = value ? value : type;
826- if (exc) Py_XINCREF (exc);
827- PyErr_Restore (type, value, tb);
828- scope->setCaughtException (exc);
874+ PyObject *type = nullptr , *value = nullptr , *traceback = nullptr ;
875+ PyErr_Fetch (&type, &value, &traceback);
876+ scope->setCaughtException (type, value, traceback);
829877 }
830878#endif
831879 return nullptr ;
0 commit comments