Salome HOME
updated copyright message
[tools/py2cpp.git] / src / Errors.cxx
1 // Copyright (C) 2019-2023 EDF
2 //
3 // This library is free software; you can redistribute it and/or
4 // modify it under the terms of the GNU Lesser General Public
5 // License as published by the Free Software Foundation; either
6 // version 2.1 of the License, or (at your option) any later version.
7 //
8 // This library is distributed in the hope that it will be useful,
9 // but WITHOUT ANY WARRANTY; without even the implied warranty of
10 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
11 // Lesser General Public License for more details.
12 //
13 // You should have received a copy of the GNU Lesser General Public
14 // License along with this library; if not, write to the Free Software
15 // Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307 USA
16 //
17 // See http://www.salome-platform.org/ or email : webmaster.salome@opencascade.com
18 //
19 #include "Errors.hxx"
20 #include <Python.h>
21
22 namespace py2cpp
23 {
24 std::string getLastPyError()
25 {
26   std::string result="";
27   if (PyErr_Occurred())
28   {
29     PyObject *ptype, *pvalue, *ptraceback;
30     PyObject *pystr, *module_name, *pyth_module, *pyth_func;
31     PyErr_Fetch(&ptype, &pvalue, &ptraceback);
32     PyErr_NormalizeException(&ptype, &pvalue, &ptraceback);
33     pystr = PyObject_Str(pvalue);
34     const char* charstr = PyUnicode_AsUTF8(pystr);
35     if(charstr != nullptr)
36       result = std::string(charstr);
37     result += "\n";
38     Py_DECREF(pystr);
39     
40     /* See if we can get a full traceback */
41     if(ptraceback)
42     {
43       module_name = PyUnicode_FromString("traceback");
44       pyth_module = PyImport_Import(module_name);
45       Py_DECREF(module_name);
46       if (pyth_module)
47       {
48         pyth_func = PyObject_GetAttrString(pyth_module, "format_exception");
49         if (pyth_func && PyCallable_Check(pyth_func))
50         {
51           PyObject *pyList;
52           pyList = PyObject_CallFunctionObjArgs(pyth_func, ptype, pvalue, ptraceback, NULL);
53           if(pyList)
54           {
55             int n = PyList_Size(pyList);
56             for(int i=0; i<n; i++)
57             {
58               pystr = PyList_GetItem(pyList,i);
59               const char* charstr = PyUnicode_AsUTF8(pystr);
60               if(charstr != nullptr)
61                 result += charstr;
62             }
63             Py_DECREF(pyList);
64           }
65         }
66         Py_XDECREF(pyth_func);
67         Py_DECREF(pyth_module);
68       }
69     }
70     Py_XDECREF(ptype);
71     Py_XDECREF(pvalue);
72     Py_XDECREF(ptraceback);
73   }
74   return result;
75 }
76
77 ConversionCheck::ConversionCheck()
78 : _message()
79 {
80 }
81
82 ConversionCheck::ConversionCheck(const std::string& error)
83 : _message(error)
84 {
85 }
86
87 ConversionCheck::~ConversionCheck()
88 {
89 }
90
91 ConversionCheck::operator bool()const
92 {
93   return _message.size() == 0;
94 }
95
96 const std::string& ConversionCheck::getMessage()const
97 {
98   return _message;
99 }
100
101 void ConversionCheck::addError(const std::string& expectedType, PyObject * obj)
102 {
103   std::string newMessage;
104   if(obj)
105   {
106     std::string pyRepr;
107     PyObject* pyResult = PyObject_Repr(obj);
108     if(pyResult && PyUnicode_Check(pyResult))
109     {
110       const char* charstr = PyUnicode_AsUTF8(pyResult);
111       if(charstr != nullptr)
112         pyRepr = charstr;
113     }
114     else
115       pyRepr = "unknown representation";
116     Py_XDECREF(pyResult);
117     if(pyRepr.size() > 80)
118     {
119       pyRepr = pyRepr.substr(0, 76);
120       pyRepr += "...";
121     }
122     const std::string beginMessage = "Cannot convert the python object ";
123     const std::string midMessage = " to c++ type ";
124     int messageSize = pyRepr.size() + beginMessage.size() + midMessage.size();
125     newMessage = beginMessage;
126     if(messageSize >= 80)
127       newMessage += "\n";
128     newMessage += "<";
129     newMessage += pyRepr;
130     newMessage += ">";
131     if(messageSize > 80)
132       newMessage += "\n";
133     newMessage += " to c++ type ";
134     newMessage += expectedType;
135     newMessage += ".\n";
136   }
137   else
138   {
139     newMessage = "Cannont convert a NULL python object to c++ type ";
140     newMessage += expectedType;
141     newMessage += ".\n";
142   }
143   addErrorMessage(newMessage);
144 }
145
146 void ConversionCheck::addError(const ConversionCheck& err)
147 {
148   _message += err.getMessage();
149 }
150
151 void ConversionCheck::addErrorMessage(const std::string& message)
152 {
153   _message += message;
154 }
155
156 void ConversionCheck::reset()
157 {
158   _message = "";
159 }
160
161 Exception::Exception(const std::string& message)
162 : std::exception()
163 , _message(message)
164 {
165 }
166
167 const char* Exception::what() const noexcept
168 {
169   return _message.c_str();
170 }
171
172 ConversionException::ConversionException(const std::string& message)
173 : Exception(message)
174 {
175 }
176
177 ExecutionException::ExecutionException(const std::string& message)
178 : Exception(message)
179 {
180 }
181
182 AttributeException::AttributeException(const std::string& message)
183 : Exception(message)
184 {
185 }
186
187 }