Remove internal mgp.py
file from Python traceback
Reviewers: llugovic Reviewed By: llugovic Subscribers: pullbot Differential Revision: https://phabricator.memgraph.io/D2740
This commit is contained in:
parent
90c83de7c2
commit
3cd89e1fe4
@ -206,32 +206,39 @@ struct [[nodiscard]] ExceptionInfo final {
|
|||||||
Object traceback;
|
Object traceback;
|
||||||
};
|
};
|
||||||
|
|
||||||
/// Write ExceptionInfo to stream just like the Python interpreter would.
|
/// Format ExceptionInfo as a string just like the Python interpreter would. The
|
||||||
inline std::ostream &operator<<(std::ostream &os,
|
/// argument `skip_first_line` allows the user to skip the first line of the
|
||||||
const ExceptionInfo &exc_info) {
|
/// traceback. It is useful if the first line in the traceback always prints
|
||||||
if (!exc_info.type) return os;
|
/// some internal wrapper function.
|
||||||
|
[[nodiscard]] inline std::string FormatException(const ExceptionInfo &exc_info,
|
||||||
|
bool skip_first_line = false) {
|
||||||
|
if (!exc_info.type) return "";
|
||||||
Object traceback_mod(PyImport_ImportModule("traceback"));
|
Object traceback_mod(PyImport_ImportModule("traceback"));
|
||||||
CHECK(traceback_mod);
|
CHECK(traceback_mod);
|
||||||
Object format_exception_fn(traceback_mod.GetAttr("format_exception"));
|
Object format_exception_fn(traceback_mod.GetAttr("format_exception"));
|
||||||
CHECK(format_exception_fn);
|
CHECK(format_exception_fn);
|
||||||
|
Object traceback_root(exc_info.traceback);
|
||||||
|
if (skip_first_line && traceback_root) {
|
||||||
|
traceback_root = traceback_root.GetAttr("tb_next");
|
||||||
|
}
|
||||||
auto list = format_exception_fn.Call(
|
auto list = format_exception_fn.Call(
|
||||||
exc_info.type, exc_info.value ? exc_info.value.Ptr() : Py_None,
|
exc_info.type, exc_info.value ? exc_info.value.Ptr() : Py_None,
|
||||||
exc_info.traceback ? exc_info.traceback.Ptr() : Py_None);
|
traceback_root ? traceback_root.Ptr() : Py_None);
|
||||||
CHECK(list);
|
CHECK(list);
|
||||||
|
std::stringstream ss;
|
||||||
auto len = PyList_GET_SIZE(list.Ptr());
|
auto len = PyList_GET_SIZE(list.Ptr());
|
||||||
for (Py_ssize_t i = 0; i < len; ++i) {
|
for (Py_ssize_t i = 0; i < len; ++i) {
|
||||||
auto *py_str = PyList_GET_ITEM(list.Ptr(), i);
|
auto *py_str = PyList_GET_ITEM(list.Ptr(), i);
|
||||||
os << PyUnicode_AsUTF8(py_str);
|
ss << PyUnicode_AsUTF8(py_str);
|
||||||
}
|
}
|
||||||
return os;
|
return ss.str();
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Format ExceptionInfo as a string just like the Python interpreter would.
|
/// Write ExceptionInfo to stream just like the Python interpreter would.
|
||||||
[[nodiscard]] inline std::string FormatException(
|
inline std::ostream &operator<<(std::ostream &os,
|
||||||
const ExceptionInfo &exc_info) {
|
const ExceptionInfo &exc_info) {
|
||||||
std::stringstream ss;
|
os << FormatException(exc_info);
|
||||||
ss << exc_info;
|
return os;
|
||||||
return ss.str();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Get the current exception info and clear the current exception indicator.
|
/// Get the current exception info and clear the current exception indicator.
|
||||||
|
@ -509,7 +509,11 @@ void CallPythonProcedure(py::Object py_cb, const mgp_list *args,
|
|||||||
auto error_to_msg = [](const std::optional<py::ExceptionInfo> &exc_info)
|
auto error_to_msg = [](const std::optional<py::ExceptionInfo> &exc_info)
|
||||||
-> std::optional<std::string> {
|
-> std::optional<std::string> {
|
||||||
if (!exc_info) return std::nullopt;
|
if (!exc_info) return std::nullopt;
|
||||||
return py::FormatException(*exc_info);
|
// Here we tell the traceback formatter to skip the first line of the
|
||||||
|
// traceback because that line will always be our wrapper function in our
|
||||||
|
// internal `mgp.py` file. With that line skipped, the user will always
|
||||||
|
// get only the relevant traceback that happened in his Python code.
|
||||||
|
return py::FormatException(*exc_info, /* skip_first_line = */ true);
|
||||||
};
|
};
|
||||||
|
|
||||||
auto call = [&](py::Object py_graph) -> std::optional<py::ExceptionInfo> {
|
auto call = [&](py::Object py_graph) -> std::optional<py::ExceptionInfo> {
|
||||||
|
Loading…
Reference in New Issue
Block a user