Mercurial > pytave
changeset 144:ad964e46cd48
Handle errors properly with latest Octave interpreter changes
* pytave.cc (pytave::make_error_message): Get last error information directly
from the interpreter. (pytave::func_eval, pytave::str_eval): Catch interpreter
exceptions and propagate error properly.
author | Mike Miller <mtmiller@octave.org> |
---|---|
date | Tue, 05 Apr 2016 00:12:23 -0700 |
parents | fe783134c61c |
children | a5ec9bbd94cc |
files | pytave.cc |
diffstat | 1 files changed, 22 insertions(+), 32 deletions(-) [+] |
line wrap: on
line diff
--- a/pytave.cc Mon Apr 04 22:51:54 2016 -0700 +++ b/pytave.cc Tue Apr 05 00:12:23 2016 -0700 @@ -131,19 +131,18 @@ variable_name_exception::excclass))); } - std::string make_error_message (const octave_map& map) { + std::string make_error_message () { std::ostringstream exceptionmsg; - std::string message = map(0).getfield("message").string_value(); - std::string identifier = map(0).getfield("identifier").string_value(); - Cell stackCell = map.contents("stack"); + + std::string message = last_error_message (); + std::string identifier = last_error_id (); // Trim trailing new lines message = message.substr(0, message.find_last_not_of("\r\n") + 1); - if (!stackCell.is_empty() && stackCell(0).is_map()) { - // The struct element is called "stack" but only contain - // info about the top frame. - octave_map stack = stackCell(0).map_value(); + octave_map stack = last_error_stack (); + + if (! stack.is_empty ()) { std::string file = stack(0).getfield("file").string_value(); std::string name = stack(0).getfield("name").string_value(); int line = stack(0).getfield("line").int_value(); @@ -182,11 +181,15 @@ #endif bool bad_alloc_state = false; + bool octave_error = false; + Py_BEGIN_ALLOW_THREADS try { retval = feval(funcname, octave_args, (nargout >= 0) ? nargout : 0); } catch (std::bad_alloc) { bad_alloc_state = true; + } catch (const octave_execution_exception&) { + octave_error = true; } Py_END_ALLOW_THREADS @@ -198,19 +201,11 @@ if (bad_alloc_state) throw std::bad_alloc (); // Translated to MemoryError by boost::python - else if (error_state != 0) { -// error_state values: -// -2 error without traceback -// -1 traceback -// 1 general error - int parse_status = 0; - reset_error_handler(); - octave_value_list lasterror = eval_string("lasterror", - true, parse_status, 1); - if (!lasterror.empty() && lasterror(0).is_map()) { - std::string exceptionmsg = make_error_message(lasterror(0).map_value ()); + if (octave_error) { + std::string exceptionmsg = make_error_message (); + if (! exceptionmsg.empty ()) throw octave_error_exception(exceptionmsg); - } else + else throw octave_error_exception("No Octave error available"); } @@ -243,12 +238,16 @@ #endif bool bad_alloc_state = false; + bool octave_error = false; + Py_BEGIN_ALLOW_THREADS try { retval = eval_string(code, silent, parse_status, (nargout >= 0) ? nargout : 0); } catch (std::bad_alloc) { bad_alloc_state = true; + } catch (const octave_execution_exception&) { + octave_error = true; } Py_END_ALLOW_THREADS @@ -260,18 +259,9 @@ if (bad_alloc_state) throw std::bad_alloc (); // Translated to MemoryError by boost::python - if (parse_status != 0 || error_state != 0) { -// error_state values: -// -2 error without traceback -// -1 traceback -// 1 general error - int parse_status1 = 0; - reset_error_handler(); - octave_value_list lasterror = eval_string("lasterror", - true, parse_status1, 1); - if (!lasterror.empty() && lasterror(0).is_map()) { - std::string exceptionmsg = make_error_message (lasterror(0).map_value ()); - + if (octave_error || parse_status) { + std::string exceptionmsg = make_error_message (); + if (! exceptionmsg.empty ()) { if (parse_status != 0) throw octave_parse_exception(exceptionmsg); else