#ifndef NO_PYTHON #include #include #include "nextpnr.h" namespace py = boost::python; NEXTPNR_NAMESPACE_BEGIN // Parses the value of the active python exception // NOTE SHOULD NOT BE CALLED IF NO EXCEPTION std::string parse_python_exception() { PyObject *type_ptr = NULL, *value_ptr = NULL, *traceback_ptr = NULL; // Fetch the exception info from the Python C API PyErr_Fetch(&type_ptr, &value_ptr, &traceback_ptr); // Fallback error std::string ret("Unfetchable Python error"); // If the fetch got a type pointer, parse the type into the exception string if (type_ptr != NULL) { py::handle<> h_type(type_ptr); py::str type_pstr(h_type); // Extract the string from the boost::python object py::extract e_type_pstr(type_pstr); // If a valid string extraction is available, use it // otherwise use fallback if (e_type_pstr.check()) ret = e_type_pstr(); else ret = "Unknown exception type"; } // Do the same for the exception value (the stringification of the // exception) if (value_ptr != NULL) { py::handle<> h_val(value_ptr); py::str a(h_val); py::extract returned(a); if (returned.check()) ret += ": " + returned(); else ret += std::string(": Unparseable Python error: "); } // Parse lines from the traceback using the Python traceback module if (traceback_ptr != NULL) { py::handle<> h_tb(traceback_ptr); // Load the traceback module and the format_tb function py::object tb(py::import("traceback")); py::object fmt_tb(tb.attr("format_tb")); // Call format_tb to get a list of traceback strings py::object tb_list(fmt_tb(h_tb)); // Join the traceback strings into a single string py::object tb_str(py::str("\n").join(tb_list)); // Extract the string, check the extraction, and fallback in necessary py::extract returned(tb_str); if (returned.check()) ret += ": " + returned(); else ret += std::string(": Unparseable Python traceback"); } return ret; } NEXTPNR_NAMESPACE_END #endif // NO_PYTHON