[Python] Fix display of information from errors in callback functions

This commit is contained in:
Ray Speth 2018-08-14 23:08:11 -04:00
parent 820b9de4b0
commit d3f49e74cb
3 changed files with 23 additions and 11 deletions

View file

@ -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_ += "<error determining exception type>";
msg += "<error determining exception type>";
}
formattedMessage_ += ": ";
msg += ": ";
if (value_bytes) {
formattedMessage_ += PyBytes_AsString(value_bytes);
msg += PyBytes_AsString(value_bytes);
Py_DECREF(value_bytes);
} else {
formattedMessage_ += "<error determining exception message>";
msg += "<error determining exception message>";
}
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;

View file

@ -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

View file

@ -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());
}