From b410f8857c9b4c79ceaacf0cc50faee68c623a1b Mon Sep 17 00:00:00 2001 From: Abdullah Tahiri Date: Fri, 12 May 2017 22:40:05 +0200 Subject: [PATCH] Enable exceptions to save/restore information in a python dictionary and enable throwing exception from dictionary information --- src/Base/Exception.cpp | 88 +++++++++++++++++++ src/Base/Exception.h | 9 ++ src/Base/ExceptionFactory.cpp | 19 ++-- src/Base/ExceptionFactory.h | 19 ++-- src/Base/Interpreter.cpp | 36 ++------ .../templateClassPyExport.py | 45 ++-------- 6 files changed, 127 insertions(+), 89 deletions(-) diff --git a/src/Base/Exception.cpp b/src/Base/Exception.cpp index 32979349d7..f48a799d0e 100644 --- a/src/Base/Exception.cpp +++ b/src/Base/Exception.cpp @@ -25,6 +25,7 @@ #include "PreCompiled.h" +#include #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)); + } +} // --------------------------------------------------------- diff --git a/src/Base/Exception.h b/src/Base/Exception.h index 148a0e02f9..b8cc3d98b8 100644 --- a/src/Base/Exception.h +++ b/src/Base/Exception.h @@ -30,6 +30,7 @@ #include #include #include +#include #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() diff --git a/src/Base/ExceptionFactory.cpp b/src/Base/ExceptionFactory.cpp index 7042a6a0de..d727b9e0c6 100644 --- a/src/Base/ExceptionFactory.cpp +++ b/src/Base/ExceptionFactory.cpp @@ -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_iterator pProd; + pystring = PyDict_GetItemString(pydict,"sclassname"); - pProd = _mpcProducers.find(info.exceptionname.c_str()); - if (pProd != _mpcProducers.end()) - static_cast(pProd->second)->raiseException(info); + if(pystring!=NULL) { + classname = std::string(PyString_AsString(pystring)); + + std::map::const_iterator pProd; + + pProd = _mpcProducers.find(classname.c_str()); + if (pProd != _mpcProducers.end()) + static_cast(pProd->second)->raiseException(pydict); } } diff --git a/src/Base/ExceptionFactory.h b/src/Base/ExceptionFactory.h index b0e77b244b..1787839203 100644 --- a/src/Base/ExceptionFactory.h +++ b/src/Base/ExceptionFactory.h @@ -25,20 +25,13 @@ #define BASE_EXCEPTIONFACTORY_H +#include #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; } diff --git a/src/Base/Interpreter.cpp b/src/Base/Interpreter.cpp index 775685912e..a2a71dd4b0 100644 --- a/src/Base/Interpreter.cpp +++ b/src/Base/Interpreter.cpp @@ -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; diff --git a/src/Tools/generateTemplates/templateClassPyExport.py b/src/Tools/generateTemplates/templateClassPyExport.py index b08a0d23ba..dac3bb98c2 100644 --- a/src/Tools/generateTemplates/templateClassPyExport.py +++ b/src/Tools/generateTemplates/templateClassPyExport.py @@ -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);