Mercurial > pytave
changeset 231:6fffa6219b2c
Properly extract exception text from Python (fixes issue #24)
* exceptions.{h, cc}: Add a new method to properly extract string for a python
exception. Also add a new error message if we can't extract the error string.
* pycall.cc, pyeval.cc, pyexec.cc: Use the new method to extract string when an
exception occurs.
author | Abhinav Tripathi <genuinelucifer@gmail.com> |
---|---|
date | Sat, 16 Jul 2016 05:50:36 -0700 |
parents | 377f2dc057ea |
children | c02f0a4c92e7 |
files | exceptions.cc exceptions.h pycall.cc pyeval.cc pyexec.cc |
diffstat | 5 files changed, 50 insertions(+), 39 deletions(-) [+] |
line wrap: on
line diff
--- a/exceptions.cc Fri Jul 15 00:51:23 2016 -0700 +++ b/exceptions.cc Sat Jul 16 05:50:36 2016 -0700 @@ -45,4 +45,30 @@ && octave_parse_exception::init () && variable_name_exception::init ()); } + + std::string fetch_exception_message (void) + { + using namespace boost::python; + PyObject *ptype, *pvalue, *ptraceback; + PyErr_Fetch (&ptype, &pvalue, &ptraceback); + std::string message; + + try + { + object formatted_list, formatted; + handle<> htype (ptype), hval (allow_null (pvalue)); + object traceback (import ("traceback")); + object format_exception_only (traceback.attr ("format_exception_only")); + formatted_list = format_exception_only (htype, hval); + formatted = str ("\n").join (formatted_list); + message = extract<std::string> (formatted); + } + catch (error_already_set const &) + { + PyErr_Restore (ptype, pvalue, ptraceback); + PyErr_Print (); + message = std::string ("Something weird happened. See traceback above ^"); + } + return message; + } }
--- a/exceptions.h Fri Jul 15 00:51:23 2016 -0700 +++ b/exceptions.h Sat Jul 16 05:50:36 2016 -0700 @@ -159,6 +159,7 @@ }; bool init_exceptions (void); + std::string fetch_exception_message (void); } #endif
--- a/pycall.cc Fri Jul 15 00:51:23 2016 -0700 +++ b/pycall.cc Sat Jul 16 05:50:36 2016 -0700 @@ -182,19 +182,8 @@ } catch (error_already_set const &) { - PyObject *ptype, *pvalue, *ptraceback; - PyErr_Fetch (&ptype, &pvalue, &ptraceback); - - try - { - std::string message = extract<std::string> (pvalue); - error ("pycall: %s", message.c_str ()); - } - catch (error_already_set const &) - { - PyErr_Restore (ptype, pvalue, ptraceback); - PyErr_Print (); - } + std::string message = pytave::fetch_exception_message (); + error ("pycall: %s", message.c_str ()); } return retval; @@ -247,4 +236,8 @@ %! assert (pycall ("pyfunc", true), 30) %! assert (pycall ("pyfunc", false), 20) %! assert (pycall ("pyfunc", 10), 10) + +%!error <NameError> +%! pyexec ("def raiseException ():\n raise NameError ('oops')") +%! pycall ("raiseException") */
--- a/pyeval.cc Fri Jul 15 00:51:23 2016 -0700 +++ b/pyeval.cc Sat Jul 16 05:50:36 2016 -0700 @@ -86,19 +86,8 @@ } catch (error_already_set const &) { - PyObject *ptype, *pvalue, *ptraceback; - PyErr_Fetch (&ptype, &pvalue, &ptraceback); - - try - { - std::string message = extract<std::string> (pvalue); - error ("pyeval: %s", message.c_str ()); - } - catch (error_already_set const &) - { - PyErr_Restore (ptype, pvalue, ptraceback); - PyErr_Print (); - } + std::string message = pytave::fetch_exception_message (); + error ("pyeval: %s", message.c_str ()); } return retval; @@ -139,4 +128,8 @@ %! assert (z{2}{2}, 22) %! assert (z{4}{2}{1}, 421) %! assert (z{4}{2}{2}, 422) + +%!error <NameError> +%! pyexec ("def raiseException ():\n raise NameError ('oops')") +%! pyeval ("raiseException ()") */
--- a/pyexec.cc Fri Jul 15 00:51:23 2016 -0700 +++ b/pyexec.cc Sat Jul 16 05:50:36 2016 -0700 @@ -81,19 +81,17 @@ } catch (error_already_set const &) { - PyObject *ptype, *pvalue, *ptraceback; - PyErr_Fetch (&ptype, &pvalue, &ptraceback); - - try - { - std::string message = extract<std::string> (pvalue); - error ("pyexec: %s", message.c_str ()); - } - catch (error_already_set const &) - { - PyErr_Restore (ptype, pvalue, ptraceback); - PyErr_Print (); - } + std::string message = pytave::fetch_exception_message (); + error ("pyexec: %s", message.c_str ()); } return retval; } + +/* +%!error <NameError> +%! pyexec ("raise NameError ('oops')") + +%!error <AttributeError> +%! pyexec ("import sys") +%! pyexec ("sys.no_such_thing") +*/