from traceback import extract_tb, format_exception_only from PySide6.QtWidgets import QWidget, QTreeWidget, QTreeWidgetItem, QLabel from PySide6.QtGui import QAction from PySide6.QtCore import Qt, Slot as pyqtSlot, Signal as pyqtSignal from ..mixins import ComponentMixin from ..utils import layout class TracebackTree(QTreeWidget): name = "Traceback Viewer" def __init__(self, parent): super(TracebackTree, self).__init__(parent) self.setHeaderHidden(False) self.setItemsExpandable(False) self.setRootIsDecorated(False) self.setContextMenuPolicy(Qt.ActionsContextMenu) self.setColumnCount(3) self.setHeaderLabels(["File", "Line", "Code"]) self.root = self.invisibleRootItem() class TracebackPane(QWidget, ComponentMixin): sigHighlightLine = pyqtSignal(int) def __init__(self, parent): super(TracebackPane, self).__init__(parent) self.tree = TracebackTree(self) self.current_exception = QLabel(self) self.current_exception.setStyleSheet("QLabel {color : red; }") layout(self, (self.current_exception, self.tree), self) self.tree.currentItemChanged.connect(self.handleSelection) @pyqtSlot(object, str) def addTraceback(self, exc_info, code): self.tree.clear() if exc_info: t, exc, tb = exc_info root = self.tree.root code = code.splitlines() tb = [ t for t in extract_tb(tb) if "" in t.filename ] # ignore highest frames (debug, exec) for el in tb: # workaround of the traceback module if el.line == "": line = code[el.lineno - 1].strip() else: line = el.line root.addChild(QTreeWidgetItem([el.filename, str(el.lineno), line])) exc_name = t.__name__ exc_msg = str(exc) exc_msg = exc_msg.replace("<", "<").replace(">", ">") # replace <> self.current_exception.setText("{}: {}".format(exc_name, exc_msg)) # handle the special case of a SyntaxError if t is SyntaxError: root.addChild( QTreeWidgetItem( [ exc.filename, str(exc.lineno), exc.text.strip() if exc.text else "", ] ) ) else: self.current_exception.setText("") @pyqtSlot(QTreeWidgetItem, QTreeWidgetItem) def handleSelection(self, item, *args): if item: f, line = item.data(0, 0), int(item.data(1, 0)) if "" in f: self.sigHighlightLine.emit(line)