MCPcopy Create free account
hub / github.com/NatLabRockies/EnergyPlus / reportPythonError

Function reportPythonError

src/EnergyPlus/PythonEngine.cc:114–184  ·  view source on GitHub ↗

Source from the content-addressed store, hash-verified

112#if LINK_WITH_PYTHON
113
114 void reportPythonError([[maybe_unused]] EnergyPlusData &state)
115 {
116 PyObject *exc_type = nullptr;
117 PyObject *exc_value = nullptr;
118 PyObject *exc_tb = nullptr;
119 PyErr_Fetch(&exc_type, &exc_value, &exc_tb);
120 // Normalizing the exception is needed. Without it, our custom EnergyPlusException go through just fine
121 // but any ctypes built-in exception for eg will have wrong types
122 PyErr_NormalizeException(&exc_type, &exc_value, &exc_tb);
123 PyObject *str_exc_value = PyObject_Repr(exc_value); // Now a unicode object
124 PyObject *pyStr2 = PyUnicode_AsEncodedString(str_exc_value, "utf-8", "Error ~");
125 Py_DECREF(str_exc_value);
126 char *strExcValue = PyBytes_AsString(pyStr2); // NOLINT(hicpp-signed-bitwise)
127 Py_DECREF(pyStr2);
128 EnergyPlus::ShowContinueError(state, "Python error description follows: ");
129 EnergyPlus::ShowContinueError(state, strExcValue);
130
131 // See if we can get a full traceback.
132 // Calls into python, and does the same as capturing the exception in `e`
133 // then `print(traceback.format_exception(e.type, e.value, e.tb))`
134 PyObject *pModuleName = PyUnicode_DecodeFSDefault("traceback");
135 PyObject *pyth_module = PyImport_Import(pModuleName);
136 Py_DECREF(pModuleName);
137
138 if (pyth_module == nullptr) {
139 EnergyPlus::ShowContinueError(state, "Cannot find 'traceback' module in reportPythonError(), this is weird");
140 return;
141 }
142
143 PyObject *pyth_func = PyObject_GetAttrString(pyth_module, "format_exception");
144 Py_DECREF(pyth_module); // PyImport_Import returns a new reference, decrement it
145
146 if ((pyth_func != nullptr) || (PyCallable_Check(pyth_func) != 0)) {
147
148 PyObject *pyth_val = PyObject_CallFunction(pyth_func, "OOO", exc_type, exc_value, exc_tb);
149
150 // traceback.format_exception returns a list, so iterate on that
151 if ((pyth_val == nullptr) || !PyList_Check(pyth_val)) { // NOLINT(hicpp-signed-bitwise)
152 EnergyPlus::ShowContinueError(state, "In reportPythonError(), traceback.format_exception did not return a list.");
153 return;
154 }
155
156 Py_ssize_t numVals = PyList_Size(pyth_val);
157 if (numVals == 0) {
158 EnergyPlus::ShowContinueError(state, "No traceback available");
159 return;
160 }
161
162 EnergyPlus::ShowContinueError(state, "Python traceback follows: ");
163
164 EnergyPlus::ShowContinueError(state, "```");
165
166 for (Py_ssize_t itemNum = 0; itemNum < numVals; itemNum++) {
167 PyObject *item = PyList_GetItem(pyth_val, itemNum);
168 if (PyUnicode_Check(item)) { // NOLINT(hicpp-signed-bitwise) -- something inside Python code causes warning
169 std::string traceback_line = PyUnicode_AsUTF8(item);
170 if (!traceback_line.empty() && traceback_line[traceback_line.length() - 1] == '\n') {
171 traceback_line.erase(traceback_line.length() - 1);

Callers 4

addToPythonPathFunction · 0.85
setupMethod · 0.85
runMethod · 0.85
addToPythonPathMethod · 0.85

Calls 3

ShowContinueErrorFunction · 0.85
formatFunction · 0.85
lengthMethod · 0.80

Tested by

no test coverage detected