Skip to content

Commit

Permalink
Re #8686. Added real filename and line number when emitting errors.
Browse files Browse the repository at this point in the history
Required a small refactor of the code. Hopefully the additional
comments help out.
  • Loading branch information
peterfpeterson committed Jan 8, 2014
1 parent 8687e97 commit 681a995
Show file tree
Hide file tree
Showing 2 changed files with 39 additions and 21 deletions.
55 changes: 36 additions & 19 deletions Code/Mantid/MantidPlot/src/PythonScript.cpp
Expand Up @@ -223,27 +223,43 @@ void PythonScript::generateAutoCompleteList()
}

/**
* Convert a python error state into a human-readable string
*
* @return A string containing the error message
* This emits the error signal and resets the error state
* of the python interpreter.
*/
QString PythonScript::constructErrorMsg()
void PythonScript::emit_error()
{
// gil is necessary so other things don't continue
GlobalInterpreterLock gil;
QString message;
if (!PyErr_Occurred())
{
return message;
}

// return early if nothing happened
if (!PyErr_Occurred())
return;

// get the error information out
PyObject *exception(NULL), *value(NULL), *traceback(NULL);
PyErr_Fetch(&exception, &value, &traceback);

// prework on the exception handling
PyErr_NormalizeException(&exception, &value, &traceback);
PyErr_Clear();

// convert the traceback into something useful
int lineNumber = 0;
QString filename;
if (traceback)
{
PyTracebackObject* tb = (PyTracebackObject*)traceback;
lineNumber = tb->tb_lineno;
filename = PyString_AsString(tb->tb_frame->f_code->co_filename);
}

// the error message is the full (formated) traceback
PyObject *str_repr = PyObject_Str(value);
QString message;
QTextStream msgStream(&message);
if( value && str_repr )
{
if(exception == PyExc_SyntaxError)
if(exception == PyExc_SyntaxError)
{
msgStream << constructSyntaxErrorStr(value);
}
Expand All @@ -253,7 +269,7 @@ QString PythonScript::constructErrorMsg()
excTypeName = excTypeName.section(".", -1);
msgStream << excTypeName << ": " << PyString_AsString(str_repr);
}

}
else
{
Expand All @@ -265,7 +281,8 @@ QString PythonScript::constructErrorMsg()
Py_XDECREF(traceback);
Py_XDECREF(exception);
Py_XDECREF(value);
return msgStream.readAll();

emit error(msgStream.readAll(), filename, lineNumber);
}

/**
Expand Down Expand Up @@ -468,7 +485,7 @@ QVariant PythonScript::evaluateImpl()
}
else
{
emit error(constructErrorMsg(), "", 0);
emit_error();
return QVariant();
}
}
Expand Down Expand Up @@ -538,7 +555,7 @@ QVariant PythonScript::evaluateImpl()
}
else
{
emit error(constructErrorMsg(), "", 0);
emit_error();
}
return QVariant();
}
Expand Down Expand Up @@ -567,13 +584,14 @@ bool PythonScript::executeString()
// If an error has occurred we need to construct the error message
// before any other python code is run
QString msg;
if(!result)
if(!result)
{
msg = constructErrorMsg(); // Also clears error indicator
emit_error();
}
else
{
msg = "Script execution finished.";
QString msg = "Script execution finished.";
emit finished(msg);
success = true;
}
if(isInteractive())
Expand All @@ -583,8 +601,7 @@ bool PythonScript::executeString()

Py_XDECREF(compiledCode);
Py_XDECREF(result);
if(success) emit finished(msg);
else emit error(msg, "", 0);

return success;
}

Expand Down
5 changes: 3 additions & 2 deletions Code/Mantid/MantidPlot/src/PythonScript.h
Expand Up @@ -79,8 +79,6 @@ class PythonScript : public Script, MantidQt::API::WorkspaceObserver
/// Create a list of keywords for the code completion API
void generateAutoCompleteList();

/// Construct the error message from the stack trace (if one exists)
QString constructErrorMsg();
/// Special handle for syntax errors as they have no traceback
QString constructSyntaxErrorStr(PyObject *syntaxError);
/// Convert a traceback to a string
Expand Down Expand Up @@ -185,6 +183,9 @@ class PythonScript : public Script, MantidQt::API::WorkspaceObserver
/// Delete a Python reference to the given workspace name
void deletePythonReference(const std::string& wsName);

/// Send out an error and clear it from python.
void emit_error();

PythonScripting * m_pythonEnv;
PyObject *localDict, *stdoutSave, *stderrSave;
PyObject *m_CodeFileObject;
Expand Down

0 comments on commit 681a995

Please sign in to comment.