Enable exceptions to save/restore information in a python dictionary and enable throwing exception from dictionary information

This commit is contained in:
Abdullah Tahiri
2017-05-12 22:40:05 +02:00
committed by wmayer
parent 085acfac5e
commit 3a27e2d8ff
6 changed files with 127 additions and 89 deletions

View File

@@ -25,6 +25,7 @@
#include "PreCompiled.h"
#include <typeinfo>
#include "Exception.h"
#include "Console.h"
@@ -97,6 +98,47 @@ void Exception::ReportException (void) const
Console().Error("Exception (%s): %s \n",Console().Time(),str.c_str());
}
PyObject * Exception::getPyDict() const
{
PyObject *edict = PyDict_New();
PyDict_SetItemString(edict, "sclassname", PyString_FromString(typeid(*this).name()));
PyDict_SetItemString(edict, "sErrMsg", PyString_FromString(this->getMessage().c_str()));
PyDict_SetItemString(edict, "sfile", PyString_FromString(this->getFile().c_str()));
PyDict_SetItemString(edict, "iline", PyInt_FromLong(this->getLine()));
PyDict_SetItemString(edict, "sfunction", PyString_FromString(this->getFunction().c_str()));
PyDict_SetItemString(edict, "swhat", PyString_FromString(this->what()));
return edict;
}
void Exception::setPyDict( PyObject * pydict)
{
if(pydict!=NULL) {
PyObject *pystring;
pystring = PyDict_GetItemString(pydict,"sfile");
if(pystring!=NULL)
_file = std::string(PyString_AsString(pystring));
pystring = PyDict_GetItemString(pydict,"sfunction");
if(pystring!=NULL)
_function = std::string(PyString_AsString(pystring));
pystring = PyDict_GetItemString(pydict,"sErrMsg");
if(pystring!=NULL)
_sErrMsg = std::string(PyString_AsString(pystring));
pystring = PyDict_GetItemString(pydict,"iline");
if(pystring!=NULL)
_line = PyInt_AsLong(pystring);
}
}
// ---------------------------------------------------------
@@ -241,6 +283,52 @@ void FileException::ReportException (void) const
Console().Error("Exception (%s): %s \n",Console().Time(),str.c_str());
}
PyObject * FileException::getPyDict() const
{
PyObject *edict = PyDict_New();
PyDict_SetItemString(edict, "sclassname", PyString_FromString(typeid(*this).name()));
PyDict_SetItemString(edict, "sErrMsg", PyString_FromString(this->getMessage().c_str()));
PyDict_SetItemString(edict, "sfile", PyString_FromString(this->getFile().c_str()));
PyDict_SetItemString(edict, "iline", PyInt_FromLong(this->getLine()));
PyDict_SetItemString(edict, "sfunction", PyString_FromString(this->getFunction().c_str()));
PyDict_SetItemString(edict, "swhat", PyString_FromString(this->what()));
PyDict_SetItemString(edict, "filename", PyString_FromString(this->file.fileName().c_str()));
return edict;
}
void FileException::setPyDict( PyObject * pydict)
{
if(pydict!=NULL) {
PyObject *pystring;
pystring = PyDict_GetItemString(pydict,"sfile");
if(pystring!=NULL)
_file = std::string(PyString_AsString(pystring));
pystring = PyDict_GetItemString(pydict,"sfunction");
if(pystring!=NULL)
_function = std::string(PyString_AsString(pystring));
pystring = PyDict_GetItemString(pydict,"sErrMsg");
if(pystring!=NULL)
_sErrMsg = std::string(PyString_AsString(pystring));
pystring = PyDict_GetItemString(pydict,"iline");
if(pystring!=NULL)
_line = PyInt_AsLong(pystring);
pystring = PyDict_GetItemString(pydict,"filename");
if(pystring!=NULL)
file = FileInfo(PyString_AsString(pystring));
}
}
// ---------------------------------------------------------

View File

@@ -30,6 +30,7 @@
#include <stdexcept>
#include <string>
#include <signal.h>
#include <Python.h>
#include "FileInfo.h"
#include "BaseClass.h"
@@ -83,6 +84,10 @@ public:
/// setter methods for including debug information
/// intended to use via macro for autofilling of debugging information
inline void setDebugInformation(const std::string & file, const int line, const std::string & function);
/// returns a Python dictionary containing the exception data
virtual PyObject * getPyDict() const;
/// returns sets the exception data from a Python dictionary
virtual void setPyDict( PyObject * pydict);
protected:
public: // FIXME: Remove the public keyword
@@ -187,6 +192,10 @@ public:
virtual void ReportException (void) const;
/// Get file name for use with tranlatable message
std::string getFileName() const;
/// returns a Python dictionary containing the exception data
virtual PyObject * getPyDict() const;
/// returns sets the exception data from a Python dictionary
virtual void setPyDict( PyObject * pydict);
protected:
FileInfo file;
// necesary for what() legacy behaviour as it returns a buffer that can not be of a temporary object to be destroyed at end of what()

View File

@@ -42,15 +42,22 @@ void ExceptionFactory::Destruct (void)
_pcSingleton = 0;
}
void ExceptionFactory::raiseException (const ExceptionInfo& info) const
void ExceptionFactory::raiseException (PyObject * pydict) const
{
if(this->CanProduce(info.exceptionname.c_str())) {
std::string classname;
PyObject *pystring;
std::map<const std::string, AbstractProducer*>::const_iterator pProd;
pystring = PyDict_GetItemString(pydict,"sclassname");
pProd = _mpcProducers.find(info.exceptionname.c_str());
if (pProd != _mpcProducers.end())
static_cast<AbstractExceptionProducer *>(pProd->second)->raiseException(info);
if(pystring!=NULL) {
classname = std::string(PyString_AsString(pystring));
std::map<const std::string, AbstractProducer*>::const_iterator pProd;
pProd = _mpcProducers.find(classname.c_str());
if (pProd != _mpcProducers.end())
static_cast<AbstractExceptionProducer *>(pProd->second)->raiseException(pydict);
}
}

View File

@@ -25,20 +25,13 @@
#define BASE_EXCEPTIONFACTORY_H
#include <Python.h>
#include "Factory.h"
namespace Base
{
struct ExceptionInfo {
std::string exceptionname;
std::string function;
std::string message;
std::string file;
unsigned int line;
};
/// Abstract base class of all exception producers
class BaseExport AbstractExceptionProducer : public AbstractProducer
{
@@ -49,7 +42,7 @@ public:
void* Produce () const {
return nullptr;
}
virtual void raiseException(const ExceptionInfo& info) const = 0;
virtual void raiseException(PyObject * pydict) const = 0;
};
// --------------------------------------------------------------------
@@ -61,7 +54,7 @@ public:
static ExceptionFactory& Instance(void);
static void Destruct (void);
void raiseException(const ExceptionInfo& info) const;
void raiseException(PyObject * pydict) const;
private:
static ExceptionFactory* _pcSingleton;
@@ -83,13 +76,11 @@ public:
virtual ~ExceptionProducer (){}
void raiseException(const ExceptionInfo& info) const
void raiseException(PyObject * pydict) const
{
CLASS c;
c.setMessage(info.message);
c.setDebugInformation(info.file, info.line, info.function);
c.setPyDict(pydict);
throw c;
}

View File

@@ -90,41 +90,19 @@ void PyException::ThrowException(void)
if(PP_PyDict_Object!=NULL) {
Base::ExceptionInfo info;
PyObject *pystring;
pystring = PyDict_GetItemString(PP_PyDict_Object,"sclassname");
if(pystring==NULL)
throw myexcp;
info.exceptionname = std::string(PyString_AsString(pystring));
if(!Base::ExceptionFactory::Instance().CanProduce(info.exceptionname.c_str()))
std::string exceptionname = std::string(PyString_AsString(pystring));
if(!Base::ExceptionFactory::Instance().CanProduce(exceptionname.c_str()))
throw myexcp;
pystring = PyDict_GetItemString(PP_PyDict_Object,"sfile");
if(pystring!=NULL)
info.file = std::string(PyString_AsString(pystring));
pystring = PyDict_GetItemString(PP_PyDict_Object,"sfunction");
if(pystring!=NULL)
info.function = std::string(PyString_AsString(pystring));
pystring = PyDict_GetItemString(PP_PyDict_Object,"sErrMsg");
if(pystring!=NULL)
info.message = std::string(PyString_AsString(pystring));
pystring = PyDict_GetItemString(PP_PyDict_Object,"iline");
if(pystring!=NULL)
info.line = PyInt_AsLong(pystring);
Base::ExceptionFactory::Instance().raiseException(info);
Base::ExceptionFactory::Instance().raiseException(PP_PyDict_Object);
}
else
throw myexcp;

View File

@@ -494,14 +494,7 @@ PyObject * @self.export.Name@::staticCallback_@i.Name@ (PyObject *self, PyObject
}
catch(const Base::Exception& e) // catch the FreeCAD exceptions
{
PyObject *edict = PyDict_New();
PyDict_SetItemString(edict, "sclassname", PyString_FromString(typeid(e).name()));
PyDict_SetItemString(edict, "sErrMsg", PyString_FromString(e.getMessage().c_str()));
PyDict_SetItemString(edict, "sfile", PyString_FromString(e.getFile().c_str()));
PyDict_SetItemString(edict, "iline", PyInt_FromLong(e.getLine()));
PyDict_SetItemString(edict, "sfunction", PyString_FromString(e.getFunction().c_str()));
PyDict_SetItemString(edict, "swhat", PyString_FromString(e.what()));
PyObject *edict = e.getPyDict();
e.ReportException();
PyErr_SetObject(Base::BaseExceptionFreeCADError, edict);
@@ -691,14 +684,7 @@ PyObject *@self.export.Name@::_getattr(char *attr) // __getattr__ function: n
#ifndef DONT_CATCH_CXX_EXCEPTIONS
catch(const Base::Exception& e) // catch the FreeCAD exceptions
{
PyObject *edict = PyDict_New();
PyDict_SetItemString(edict, "sclassname", PyString_FromString(typeid(e).name()));
PyDict_SetItemString(edict, "sErrMsg", PyString_FromString(e.getMessage().c_str()));
PyDict_SetItemString(edict, "sfile", PyString_FromString(e.getFile().c_str()));
PyDict_SetItemString(edict, "iline", PyInt_FromLong(e.getLine()));
PyDict_SetItemString(edict, "sfunction", PyString_FromString(e.getFunction().c_str()));
PyDict_SetItemString(edict, "swhat", PyString_FromString(e.what()));
PyObject *edict = e.getPyDict();
e.ReportException();
PyErr_SetObject(Base::BaseExceptionFreeCADError, edict);
@@ -728,14 +714,7 @@ PyObject *@self.export.Name@::_getattr(char *attr) // __getattr__ function: n
#else // DONT_CATCH_CXX_EXCEPTIONS
catch(const Base::Exception& e) // catch the FreeCAD exceptions
{
PyObject *edict = PyDict_New();
PyDict_SetItemString(edict, "sclassname", PyString_FromString(typeid(e).name()));
PyDict_SetItemString(edict, "sErrMsg", PyString_FromString(e.getMessage().c_str()));
PyDict_SetItemString(edict, "sfile", PyString_FromString(e.getFile().c_str()));
PyDict_SetItemString(edict, "iline", PyInt_FromLong(e.getLine()));
PyDict_SetItemString(edict, "sfunction", PyString_FromString(e.getFunction().c_str()));
PyDict_SetItemString(edict, "swhat", PyString_FromString(e.what()));
PyObject *edict = e.getPyDict();
e.ReportException();
PyErr_SetObject(Base::BaseExceptionFreeCADError, edict);
@@ -778,14 +757,7 @@ int @self.export.Name@::_setattr(char *attr, PyObject *value) // __setattr__ fun
#ifndef DONT_CATCH_CXX_EXCEPTIONS
catch(const Base::Exception& e) // catch the FreeCAD exceptions
{
PyObject *edict = PyDict_New();
PyDict_SetItemString(edict, "sclassname", PyString_FromString(typeid(e).name()));
PyDict_SetItemString(edict, "sErrMsg", PyString_FromString(e.getMessage().c_str()));
PyDict_SetItemString(edict, "sfile", PyString_FromString(e.getFile().c_str()));
PyDict_SetItemString(edict, "iline", PyInt_FromLong(e.getLine()));
PyDict_SetItemString(edict, "sfunction", PyString_FromString(e.getFunction().c_str()));
PyDict_SetItemString(edict, "swhat", PyString_FromString(e.what()));
PyObject *edict = e.getPyDict();
e.ReportException();
PyErr_SetObject(Base::BaseExceptionFreeCADError, edict);
@@ -816,14 +788,7 @@ int @self.export.Name@::_setattr(char *attr, PyObject *value) // __setattr__ fun
#else // DONT_CATCH_CXX_EXCEPTIONS
catch(const Base::Exception& e) // catch the FreeCAD exceptions
{
PyObject *edict = PyDict_New();
PyDict_SetItemString(edict, "sclassname", PyString_FromString(typeid(e).name()));
PyDict_SetItemString(edict, "sErrMsg", PyString_FromString(e.getMessage().c_str()));
PyDict_SetItemString(edict, "sfile", PyString_FromString(e.getFile().c_str()));
PyDict_SetItemString(edict, "iline", PyInt_FromLong(e.getLine()));
PyDict_SetItemString(edict, "sfunction", PyString_FromString(e.getFunction().c_str()));
PyDict_SetItemString(edict, "swhat", PyString_FromString(e.what()));
PyObject *edict = e.getPyDict();
e.ReportException();
PyErr_SetObject(Base::BaseExceptionFreeCADError, edict);