# HG changeset patch # User Mike Miller # Date 1493957707 25200 # Node ID 6b9de18b4bdda98ffba7e913e43001a8c65e7f70 # Parent 8247f298fd16fa0ab5589fa2185802427a4d1a7a Eliminate remaining custom exception handling in favor of Octave errors * oct-py-error.cc, oct-py-error.h (pytave::error_python_exception): New function to generate an Octave error from an active Python error condition, based on pytave::fetch_exception_message. * oct-py-eval.cc (pytave::py_call_function, pytave::py_run_string_safe): Use it. * oct-py-types.cc (pytave::make_py_dict): Likewise. * oct-py-util.cc (pytave::py_objstore): Likewise. * pycall.cc (Fpycall): Remove exception handling logic. * pyeval.cc (Fpyeval): Likewise. * pyexec.cc (Fpyexec): Likewise. * exceptions.cc, exceptions.h: Delete. * Makefile.am (COMMON_SOURCE_FILES, PYTAVE_HEADER_FILES): Remove them. diff -r 8247f298fd16 -r 6b9de18b4bdd Makefile.am --- a/Makefile.am Thu May 04 17:13:38 2017 -0700 +++ b/Makefile.am Thu May 04 21:15:07 2017 -0700 @@ -29,7 +29,6 @@ export INCFLAGS COMMON_SOURCE_FILES = \ - exceptions.cc \ oct-py-error.cc \ oct-py-eval.cc \ oct-py-init.cc \ @@ -66,7 +65,6 @@ PYTAVE_HEADER_FILES = \ config.h \ - exceptions.h \ oct-py-error.h \ oct-py-eval.h \ oct-py-init.h \ diff -r 8247f298fd16 -r 6b9de18b4bdd exceptions.cc --- a/exceptions.cc Thu May 04 17:13:38 2017 -0700 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,63 +0,0 @@ -/* - -Copyright (C) 2015-2016 Mike Miller -Copyright (C) 2008 David Grundberg, Håkan Fors Nilsson - -This file is part of Pytave. - -Pytave is free software: you can redistribute it and/or modify it -under the terms of the GNU General Public License as published by the -Free Software Foundation, either version 3 of the License, or (at your -option) any later version. - -Pytave is distributed in the hope that it will be useful, but WITHOUT -ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or -FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License -for more details. - -You should have received a copy of the GNU General Public License -along with Pytave; see the file COPYING. If not, see -. - -*/ - -#if defined (HAVE_CONFIG_H) -# include -#endif - -#include "exceptions.h" -#include "oct-py-eval.h" -#include "oct-py-object.h" -#include "oct-py-types.h" - -namespace pytave -{ - std::string fetch_exception_message (void) - { - PyObject *ptype, *pvalue, *ptraceback; - PyErr_Fetch (&ptype, &pvalue, &ptraceback); - PyErr_NormalizeException (&ptype, &pvalue, &ptraceback); - - python_object args = PyTuple_Pack (2, ptype, pvalue); - python_object formatted_list = py_call_function - ("traceback.format_exception_only", args); - - std::string message; - - if (formatted_list && PyList_Check (formatted_list)) - { - int len = PyList_Size (formatted_list); - - for (int i = 0; i < len; i++) - message.append (extract_py_str (PyList_GetItem (formatted_list, i))); - } - else - { - PyErr_Restore (ptype, pvalue, ptraceback); - PyErr_Print (); - message = "exceptions.cc (pytave::fetch_exception_message): cannot call 'format_exceptions_only' for the traceback"; - } - - return message; - } -} diff -r 8247f298fd16 -r 6b9de18b4bdd exceptions.h --- a/exceptions.h Thu May 04 17:13:38 2017 -0700 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,39 +0,0 @@ -/* - -Copyright (C) 2015-2016 Mike Miller -Copyright (C) 2008 David Grundberg, Håkan Fors Nilsson - -This file is part of Pytave. - -Pytave is free software: you can redistribute it and/or modify it -under the terms of the GNU General Public License as published by the -Free Software Foundation, either version 3 of the License, or (at your -option) any later version. - -Pytave is distributed in the hope that it will be useful, but WITHOUT -ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or -FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License -for more details. - -You should have received a copy of the GNU General Public License -along with Pytave; see the file COPYING. If not, see -. - -*/ - -#if ! defined (pytave_exceptions_h) -#define pytave_exceptions_h - -#include -#include - -namespace pytave -{ - class error_already_set - { - }; - - std::string fetch_exception_message (void); -} - -#endif diff -r 8247f298fd16 -r 6b9de18b4bdd oct-py-error.cc --- a/oct-py-error.cc Thu May 04 17:13:38 2017 -0700 +++ b/oct-py-error.cc Thu May 04 21:15:07 2017 -0700 @@ -24,9 +24,13 @@ # include #endif +#include #include #include "oct-py-error.h" +#include "oct-py-eval.h" +#include "oct-py-object.h" +#include "oct-py-types.h" namespace pytave { @@ -45,4 +49,36 @@ must.c_str ()); } + void + error_python_exception () + { + const char *format_exception_only = "traceback.format_exception_only"; + + PyObject *ptype, *pvalue, *ptraceback; + PyErr_Fetch (&ptype, &pvalue, &ptraceback); + PyErr_NormalizeException (&ptype, &pvalue, &ptraceback); + + python_object args = PyTuple_Pack (2, ptype, pvalue); + python_object lines = py_call_function (format_exception_only, args); + + if (lines && PySequence_Check (lines)) + { + Py_ssize_t len = PySequence_Size (lines); + python_object last_line = PySequence_GetItem (lines, len - 1); + + std::string msg = extract_py_str (last_line); + if (msg.back () == '\n') + msg.resize (msg.size () - 1); + + error ("%s", msg.c_str ()); + } + else + { + PyErr_Restore (ptype, pvalue, ptraceback); + PyErr_Print (); + error ("runtime failed to get exception information from %s", + format_exception_only); + } + } + } diff -r 8247f298fd16 -r 6b9de18b4bdd oct-py-error.h --- a/oct-py-error.h Thu May 04 17:13:38 2017 -0700 +++ b/oct-py-error.h Thu May 04 21:15:07 2017 -0700 @@ -43,6 +43,10 @@ const std::string& must) PYTAVE_ATTR_NORETURN; + void + error_python_exception () + PYTAVE_ATTR_NORETURN; + } #undef PYTAVE_ATTR_NORETURN diff -r 8247f298fd16 -r 6b9de18b4bdd oct-py-eval.cc --- a/oct-py-eval.cc Thu May 04 17:13:38 2017 -0700 +++ b/oct-py-eval.cc Thu May 04 21:15:07 2017 -0700 @@ -29,7 +29,7 @@ #include #include -#include "exceptions.h" +#include "oct-py-error.h" #include "oct-py-eval.h" #include "oct-py-object.h" #include "oct-py-util.h" @@ -84,7 +84,7 @@ { python_object retval = PyEval_CallObjectWithKeywords (callable, args, kwargs); if (! retval) - throw pytave::error_already_set (); + error_python_exception (); return retval.release (); } @@ -119,7 +119,7 @@ Py_DECREF (globals); if (! retval) - throw pytave::error_already_set (); + error_python_exception (); return retval.release (); } diff -r 8247f298fd16 -r 6b9de18b4bdd oct-py-types.cc --- a/oct-py-types.cc Thu May 04 17:13:38 2017 -0700 +++ b/oct-py-types.cc Thu May 04 21:15:07 2017 -0700 @@ -31,7 +31,6 @@ #include #include -#include "exceptions.h" #include "oct-py-error.h" #include "oct-py-eval.h" #include "oct-py-object.h" @@ -361,7 +360,7 @@ PyObject *item = py_implicitly_convert_argument (map.contents (p)); if (PyDict_SetItem (dict, key, item) < 0) - throw pytave::error_already_set (); + error_python_exception (); } return dict; diff -r 8247f298fd16 -r 6b9de18b4bdd oct-py-util.cc --- a/oct-py-util.cc Thu May 04 17:13:38 2017 -0700 +++ b/oct-py-util.cc Thu May 04 21:15:07 2017 -0700 @@ -28,7 +28,7 @@ #include #include -#include "exceptions.h" +#include "oct-py-error.h" #include "oct-py-object.h" #include "oct-py-types.h" #include "oct-py-util.h" @@ -172,7 +172,7 @@ } if (! dict) - throw pytave::error_already_set (); + error_python_exception (); objstore = dict; } diff -r 8247f298fd16 -r 6b9de18b4bdd pycall.cc --- a/pycall.cc Thu May 04 17:13:38 2017 -0700 +++ b/pycall.cc Thu May 04 21:15:07 2017 -0700 @@ -27,7 +27,6 @@ #include #include -#include "exceptions.h" #include "oct-py-eval.h" #include "oct-py-init.h" #include "oct-py-object.h" @@ -89,35 +88,27 @@ pytave::py_init (); - try + pytave::python_object callable; + if (args(0).is_string ()) + { + callable = pytave::py_find_function (args(0).string_value ()); + if (! callable) + error ("pycall: no such Python function or callable: %s", + args(0).string_value ().c_str ()); + } + else { - pytave::python_object callable; - if (args(0).is_string ()) - { - callable = pytave::py_find_function (args(0).string_value ()); - if (! callable) - error ("pycall: no such Python function or callable: %s", - args(0).string_value ().c_str ()); - } - else - { - callable = pytave::pyobject_unwrap_object (args(0)); - if (! callable) - error("pycall: FUNC must be a valid Python reference"); - } + callable = pytave::pyobject_unwrap_object (args(0)); + if (! callable) + error("pycall: FUNC must be a valid Python reference"); + } - octave_value_list arglist = args.slice (1, nargin - 1); - pytave::python_object res = pytave::py_call_function (callable, arglist); + octave_value_list arglist = args.slice (1, nargin - 1); + pytave::python_object res = pytave::py_call_function (callable, arglist); - // Ensure reasonable "ans" behaviour, consistent with Python's "_". - if (nargout > 0 || ! res.is_none ()) - retval(0) = pytave::py_implicitly_convert_return_value (res); - } - catch (pytave::error_already_set const &) - { - std::string message = pytave::fetch_exception_message (); - error ("pycall: %s", message.c_str ()); - } + // Ensure reasonable "ans" behaviour, consistent with Python's "_". + if (nargout > 0 || ! res.is_none ()) + retval(0) = pytave::py_implicitly_convert_return_value (res); return retval; } diff -r 8247f298fd16 -r 6b9de18b4bdd pyeval.cc --- a/pyeval.cc Thu May 04 17:13:38 2017 -0700 +++ b/pyeval.cc Thu May 04 21:15:07 2017 -0700 @@ -27,7 +27,6 @@ #include #include -#include "exceptions.h" #include "oct-py-eval.h" #include "oct-py-init.h" #include "oct-py-object.h" @@ -81,18 +80,10 @@ error ("pyeval: NAMESPACE must be a valid Python reference"); } - try - { - pytave::python_object res = pytave::py_eval_string (code, 0, local_namespace); + pytave::python_object res = pytave::py_eval_string (code, 0, local_namespace); - if (nargout > 0 || ! res.is_none ()) - retval(0) = pytave::py_implicitly_convert_return_value (res); - } - catch (pytave::error_already_set const &) - { - std::string message = pytave::fetch_exception_message (); - error ("pyeval: %s", message.c_str ()); - } + if (nargout > 0 || ! res.is_none ()) + retval(0) = pytave::py_implicitly_convert_return_value (res); return retval; } diff -r 8247f298fd16 -r 6b9de18b4bdd pyexec.cc --- a/pyexec.cc Thu May 04 17:13:38 2017 -0700 +++ b/pyexec.cc Thu May 04 21:15:07 2017 -0700 @@ -27,7 +27,6 @@ #include #include -#include "exceptions.h" #include "oct-py-eval.h" #include "oct-py-init.h" #include "oct-py-util.h" @@ -74,16 +73,9 @@ error ("pyexec: NAMESPACE must be a valid Python reference"); } - try - { - // FIXME: figure out exec return code: - pytave::py_exec_string (code, 0, local_namespace); - } - catch (pytave::error_already_set const &) - { - std::string message = pytave::fetch_exception_message (); - error ("pyexec: %s", message.c_str ()); - } + // FIXME: figure out exec return code: + pytave::py_exec_string (code, 0, local_namespace); + return retval; }