diff --git a/src/Base/Exception.cpp b/src/Base/Exception.cpp index 43622a1d57..cdf61d248f 100644 --- a/src/Base/Exception.cpp +++ b/src/Base/Exception.cpp @@ -29,6 +29,7 @@ #include "Exception.h" #include "Console.h" +#include using namespace Base; @@ -37,30 +38,34 @@ TYPESYSTEM_SOURCE(Base::Exception,Base::BaseClass); Exception::Exception(void) + : _line(0) { _sErrMsg = "FreeCAD Exception"; } Exception::Exception(const Exception &inst) -: BaseClass(),_sErrMsg(inst._sErrMsg), _file(inst._file), _line(inst._line), _function(inst._function) + : _sErrMsg(inst._sErrMsg), _file(inst._file), + _line(inst._line), _function(inst._function) { } - Exception::Exception(const char * sMessage) - : _sErrMsg(sMessage) + : _sErrMsg(sMessage), _line(0) { } Exception::Exception(const std::string& sMessage) - : _sErrMsg(sMessage) + : _sErrMsg(sMessage), _line(0) { } Exception &Exception::operator=(const Exception &inst) { - _sErrMsg = inst._sErrMsg; - return *this; + _sErrMsg = inst._sErrMsg; + _file = inst._file; + _line = inst._line; + _function = inst._function; + return *this; } const char* Exception::what(void) const throw() @@ -100,38 +105,31 @@ void Exception::ReportException (void) const PyObject * Exception::getPyObject(void) { - 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; + Py::Dict edict; + edict.setItem("sclassname", Py::String(typeid(*this).name())); + edict.setItem("sErrMsg", Py::String(this->getMessage())); + edict.setItem("sfile", Py::String(this->getFile())); + edict.setItem("iline", Py::Long(this->getLine())); + edict.setItem("sfunction", Py::String(this->getFunction())); + edict.setItem("swhat", Py::String(this->what())); + return Py::new_reference_to(edict); } void Exception::setPyObject( PyObject * pydict) { - if(pydict!=NULL) { - PyObject *pystring; + if (pydict!=NULL) { + Py::Dict edict(pydict); + if (edict.hasKey("sfile")) + _file = static_cast(Py::String(edict.getItem("sfile"))); - pystring = PyDict_GetItemString(pydict,"sfile"); - if(pystring!=NULL) - _file = std::string(PyString_AsString(pystring)); + if (edict.hasKey("sfunction")) + _function = static_cast(Py::String(edict.getItem("sfunction"))); - pystring = PyDict_GetItemString(pydict,"sfunction"); - if(pystring!=NULL) - _function = std::string(PyString_AsString(pystring)); + if (edict.hasKey("sErrMsg")) + _sErrMsg = static_cast(Py::String(edict.getItem("sErrMsg"))); - 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); + if (edict.hasKey("iline")) + _line = static_cast(Py::Long(edict.getItem("iline"))); } } @@ -244,6 +242,14 @@ std::string FileException::getFileName() const return file.fileName(); } +FileException & FileException::operator=(const FileException &inst) +{ + Exception::operator = (inst); + file = inst.file; + _sErrMsgAndFileName = inst._sErrMsgAndFileName; + return *this; +} + const char* FileException::what() const throw() { return _sErrMsgAndFileName.c_str(); @@ -281,20 +287,19 @@ void FileException::ReportException (void) const PyObject * FileException::getPyObject(void) { - PyObject *edict = Exception::getPyObject(); - PyDict_SetItemString(edict, "filename", PyString_FromString(this->file.fileName().c_str())); - - return edict; + Py::Dict edict(Exception::getPyObject(), true); + edict.setItem("filename", Py::String(this->file.fileName())); + return Py::new_reference_to(edict); } void FileException::setPyObject( PyObject * pydict) { - if(pydict!=NULL) { + if (pydict!=NULL) { Exception::setPyObject(pydict); - PyObject *pystring = PyDict_GetItemString(pydict,"filename"); - if(pystring!=NULL) - file = FileInfo(PyString_AsString(pystring)); + Py::Dict edict(pydict); + if (edict.hasKey("filename")) + file.setFile(static_cast(Py::String(edict.getItem("filename")))); } } diff --git a/src/Base/Exception.h b/src/Base/Exception.h index 87d2341e01..1d80ec38f3 100644 --- a/src/Base/Exception.h +++ b/src/Base/Exception.h @@ -186,6 +186,8 @@ public: FileException(const FileException &inst); /// Destruction virtual ~FileException() throw() {} + /// Assignment operator + FileException &operator=(const FileException &inst); /// Description of the exception virtual const char* what() const throw(); /// Report generation diff --git a/src/Base/ExceptionFactory.cpp b/src/Base/ExceptionFactory.cpp index d727b9e0c6..b5f67966e6 100644 --- a/src/Base/ExceptionFactory.cpp +++ b/src/Base/ExceptionFactory.cpp @@ -23,6 +23,7 @@ #include "PreCompiled.h" #include "ExceptionFactory.h" +#include using namespace Base; @@ -46,12 +47,9 @@ void ExceptionFactory::raiseException (PyObject * pydict) const { std::string classname; - PyObject *pystring; - - pystring = PyDict_GetItemString(pydict,"sclassname"); - - if(pystring!=NULL) { - classname = std::string(PyString_AsString(pystring)); + Py::Dict edict(pydict); + if (edict.hasKey("sclassname")) { + classname = static_cast(Py::String(edict.getItem("sclassname"))); std::map::const_iterator pProd; diff --git a/src/Base/Interpreter.cpp b/src/Base/Interpreter.cpp index a2a71dd4b0..b23cb715db 100644 --- a/src/Base/Interpreter.cpp +++ b/src/Base/Interpreter.cpp @@ -87,22 +87,21 @@ PyException::~PyException() throw() void PyException::ThrowException(void) { PyException myexcp = PyException(); - - if(PP_PyDict_Object!=NULL) { - PyObject *pystring; + PyGILStateLocker locker; + if (PP_PyDict_Object!=NULL) { + // delete the Python dict upon destruction of edict + Py::Dict edict(PP_PyDict_Object, true); + PP_PyDict_Object = 0; - pystring = PyDict_GetItemString(PP_PyDict_Object,"sclassname"); - - if(pystring==NULL) + if (!edict.hasKey("sclassname")) throw myexcp; - std::string exceptionname = std::string(PyString_AsString(pystring)); - - if(!Base::ExceptionFactory::Instance().CanProduce(exceptionname.c_str())) + std::string exceptionname = static_cast(Py::String(edict.getItem("sclassname"))); + if (!Base::ExceptionFactory::Instance().CanProduce(exceptionname.c_str())) throw myexcp; - Base::ExceptionFactory::Instance().raiseException(PP_PyDict_Object); + Base::ExceptionFactory::Instance().raiseException(edict.ptr()); } else throw myexcp; diff --git a/src/Base/PyTools.c b/src/Base/PyTools.c index 0b602682e7..3e77359a13 100644 --- a/src/Base/PyTools.c +++ b/src/Base/PyTools.c @@ -259,14 +259,17 @@ void PP_Fetch_Error_Text() if (errdata != NULL && (PyDict_Check(errdata)) ) /* str() increfs */ { - pystring = PyDict_GetItemString(errdata,"swhat"); + // PyDict_GetItemString returns a borrowed reference + // so we must make sure not to decrement the reference + PyObject* value = PyDict_GetItemString(errdata,"swhat"); - if(pystring!=NULL) { - strncpy(PP_last_error_info, PyString_AsString(pystring), MAX); + if (value!=NULL) { + strncpy(PP_last_error_info, PyString_AsString(value), MAX); PP_last_error_info[MAX-1] = '\0'; } pydict = errdata; + Py_INCREF(pydict); } else if (errdata != NULL && (pystring = PyObject_Str(errdata)) != NULL && /* str(): increfs */