changeset 423:6b9de18b4bdd

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.
author Mike Miller <mtmiller@octave.org>
date Thu, 04 May 2017 21:15:07 -0700
parents 8247f298fd16
children 9b34c17cb0fb
files Makefile.am exceptions.cc exceptions.h oct-py-error.cc oct-py-error.h oct-py-eval.cc oct-py-types.cc oct-py-util.cc pycall.cc pyeval.cc pyexec.cc
diffstat 11 files changed, 70 insertions(+), 161 deletions(-) [+]
line wrap: on
line diff
--- 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 \
--- 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
-<http://www.gnu.org/licenses/>.
-
-*/
-
-#if defined (HAVE_CONFIG_H)
-#  include <config.h>
-#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;
-  }
-}
--- 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
-<http://www.gnu.org/licenses/>.
-
-*/
-
-#if ! defined (pytave_exceptions_h)
-#define pytave_exceptions_h
-
-#include <Python.h>
-#include <string>
-
-namespace pytave
-{
-  class error_already_set
-  {
-  };
-
-  std::string fetch_exception_message (void);
-}
-
-#endif
--- 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 <config.h>
 #endif
 
+#include <Python.h>
 #include <octave/error.h>
 
 #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);
+      }
+  }
+
 }
--- 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
--- 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 <octave/ov.h>
 #include <octave/ovl.h>
 
-#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 ();
   }
--- 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 <octave/quit.h>
 #include <octave/ov-null-mat.h>
 
-#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;
--- 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 <octave/oct.h>
 #include <octave/parse.h>
 
-#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;
       }
--- 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 <Python.h>
 #include <octave/oct.h>
 
-#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;
 }
--- 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 <Python.h>
 #include <octave/oct.h>
 
-#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;
 }
--- 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 <Python.h>
 #include <octave/oct.h>
 
-#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;
 }