diff --git a/include/cantera/cython/funcWrapper.h b/include/cantera/cython/funcWrapper.h index 4dd1695ca..7749ff515 100644 --- a/include/cantera/cython/funcWrapper.h +++ b/include/cantera/cython/funcWrapper.h @@ -20,13 +20,13 @@ class CallbackError : public Cantera::CanteraError { public: CallbackError(void* type, void* value) : + CanteraError("Python callback function"), m_type((PyObject*) type), m_value((PyObject*) value) { } - const char* what() const throw() { - formattedMessage_ = "\n" + std::string(71, '*') + "\n"; - formattedMessage_ += "Exception raised in Python callback function:\n"; + std::string getMessage() const { + std::string msg; PyObject* name = PyObject_GetAttrString(m_type, "__name__"); PyObject* value_str = PyObject_Str(m_value); @@ -40,26 +40,28 @@ public: #endif if (name_bytes) { - formattedMessage_ += PyBytes_AsString(name_bytes); + msg += PyBytes_AsString(name_bytes); Py_DECREF(name_bytes); } else { - formattedMessage_ += ""; + msg += ""; } - formattedMessage_ += ": "; + msg += ": "; if (value_bytes) { - formattedMessage_ += PyBytes_AsString(value_bytes); + msg += PyBytes_AsString(value_bytes); Py_DECREF(value_bytes); } else { - formattedMessage_ += ""; + msg += ""; } Py_XDECREF(name); Py_XDECREF(value_str); + return msg; + } - formattedMessage_ += "\n" + std::string(71, '*') + "\n"; - return formattedMessage_.c_str(); + virtual std::string getClass() const { + return "Exception"; } PyObject* m_type; diff --git a/interfaces/cython/cantera/test/test_reactor.py b/interfaces/cython/cantera/test/test_reactor.py index 209180559..e3681275a 100644 --- a/interfaces/cython/cantera/test/test_reactor.py +++ b/interfaces/cython/cantera/test/test_reactor.py @@ -364,6 +364,16 @@ class TestReactor(utilities.CanteraTest): self.assertNear(ma + 0.1, mb) self.assertArrayNear(ma * Ya + 0.1 * gas2.Y, mb * Yb) + def test_user_function_error(self): + # Make sure Python error message actually gets displayed + self.make_reactors(n_reactors=2) + mfc = ct.MassFlowController(self.r1, self.r2) + mfc.set_mass_flow_rate(lambda t: eggs) + + # TODO: replace with 'assertRasesRegex' after dropping Python 2.7 support + with self.assertRaisesRegexp(Exception, 'eggs'): + self.net.step() + def test_valve1(self): self.make_reactors(P1=10*ct.one_atm, X1='AR:1.0', X2='O2:1.0') self.net.rtol = 1e-12 diff --git a/src/numerics/FuncEval.cpp b/src/numerics/FuncEval.cpp index 86dbc46bc..6f696b73f 100644 --- a/src/numerics/FuncEval.cpp +++ b/src/numerics/FuncEval.cpp @@ -15,7 +15,7 @@ int FuncEval::eval_nothrow(double t, double* y, double* ydot) eval(t, y, ydot, m_sens_params.data()); } catch (CanteraError& err) { if (suppressErrors()) { - m_errors.push_back(err.getMessage()); + m_errors.push_back(err.what()); } else { writelog(err.what()); }