Skip to content

Commit

Permalink
Enable exceptions to save/restore information in a python dictionary …
Browse files Browse the repository at this point in the history
…and enable throwing exception from dictionary information
  • Loading branch information
abdullahtahiriyo authored and wwmayer committed May 13, 2017
1 parent 9c698f1 commit b410f88
Show file tree
Hide file tree
Showing 6 changed files with 127 additions and 89 deletions.
88 changes: 88 additions & 0 deletions src/Base/Exception.cpp
Expand Up @@ -25,6 +25,7 @@

#include "PreCompiled.h"

#include <typeinfo>

#include "Exception.h"
#include "Console.h"
Expand Down Expand Up @@ -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);
}
}

// ---------------------------------------------------------


Expand Down Expand Up @@ -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));
}
}

// ---------------------------------------------------------

Expand Down
9 changes: 9 additions & 0 deletions src/Base/Exception.h
Expand Up @@ -30,6 +30,7 @@
#include <stdexcept>
#include <string>
#include <signal.h>
#include <Python.h>
#include "FileInfo.h"
#include "BaseClass.h"

Expand Down Expand Up @@ -83,6 +84,10 @@ class BaseExport Exception : public BaseClass
/// 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
Expand Down Expand Up @@ -187,6 +192,10 @@ class BaseExport FileException : public Exception
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()
Expand Down
19 changes: 13 additions & 6 deletions src/Base/ExceptionFactory.cpp
Expand Up @@ -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);
}
}

Expand Down
19 changes: 5 additions & 14 deletions src/Base/ExceptionFactory.h
Expand Up @@ -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
{
Expand All @@ -49,7 +42,7 @@ class BaseExport AbstractExceptionProducer : public AbstractProducer
void* Produce () const {
return nullptr;
}
virtual void raiseException(const ExceptionInfo& info) const = 0;
virtual void raiseException(PyObject * pydict) const = 0;
};

// --------------------------------------------------------------------
Expand All @@ -61,7 +54,7 @@ class BaseExport ExceptionFactory : public Factory
static ExceptionFactory& Instance(void);
static void Destruct (void);

void raiseException(const ExceptionInfo& info) const;
void raiseException(PyObject * pydict) const;

private:
static ExceptionFactory* _pcSingleton;
Expand All @@ -83,13 +76,11 @@ class BaseExport ExceptionProducer : public AbstractExceptionProducer

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;
}
Expand Down
36 changes: 7 additions & 29 deletions src/Base/Interpreter.cpp
Expand Up @@ -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;
Expand Down
45 changes: 5 additions & 40 deletions src/Tools/generateTemplates/templateClassPyExport.py
Expand Up @@ -494,14 +494,7 @@ class @self.export.Namespace@Export @self.export.Name@ : public @self.export.Fat
}
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);
Expand Down Expand Up @@ -691,14 +684,7 @@ class @self.export.Namespace@Export @self.export.Name@ : public @self.export.Fat
#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);
Expand Down Expand Up @@ -728,14 +714,7 @@ class @self.export.Namespace@Export @self.export.Name@ : public @self.export.Fat
#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);
Expand Down Expand Up @@ -778,14 +757,7 @@ class @self.export.Namespace@Export @self.export.Name@ : public @self.export.Fat
#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);
Expand Down Expand Up @@ -816,14 +788,7 @@ class @self.export.Namespace@Export @self.export.Name@ : public @self.export.Fat
#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);
Expand Down

0 comments on commit b410f88

Please sign in to comment.