Exemple #1
0
class ConsoleWidget(QWidget):
    def __init__(self, exc_info, parent=None):
        QWidget.__init__(self, parent)

        self.compiler = code.CommandCompiler()  # for console

        self.tb = exc_info[2]
        self.entries = traceback.extract_tb(self.tb)

        self.console = QLineEdit()
        self.console.setPlaceholderText(">>> Python Console")
        self.console.returnPressed.connect(self.exec_console)
        self.console.setFont(QFont("Courier"))

        self.console_out = QTextEdit()
        self.console_out.setReadOnly(True)
        self.console_out.setFont(QFont("Courier"))
        self.console_out.setVisible(False)  # initially hidden

        self.console_outs = [''] * len(self.entries)

        self.frame_vars = [None] * len(self.entries)

        l = QVBoxLayout()
        l.addWidget(self.console_out)
        l.addWidget(self.console)
        l.setContentsMargins(0, 0, 0, 0)
        self.setLayout(l)

    def go_to_frame(self, index):
        self.console_out.setPlainText(self.console_outs[index])
        self.current_frame_index = index

    def exec_console(self):

        index = self.current_frame_index
        if index < 0: return

        # cache frame variables (globals and locals)
        # because every time we ask for frame.f_locals, a new dict instance
        # is created - we keep our local cache that may contain some changes
        if self.frame_vars[index] is None:
            #print "init", index
            frame = frame_from_traceback(self.tb, index)
            self.frame_vars[index] = (dict(frame.f_globals),
                                      dict(frame.f_locals))

        frame_vars = self.frame_vars[index]
        #print frame_vars[1]

        line = self.console.text()
        try:
            c = self.compiler(line, "<console>", "single")
        except (OverflowError, SyntaxError, ValueError) as e:
            QMessageBox.critical(self, "Error", str(e))
            return

        if c is None:
            QMessageBox.critical(self, "Error", "Code not complete")
            return

        import io
        io = io.StringIO() if sys.version_info.major >= 3 else io.BytesIO()
        try:
            with stdout_redirected(io):
                exec(c, frame_vars[0], frame_vars[1])
        except:
            etype, value, tb = sys.exc_info()
            QMessageBox.critical(self, "Error",
                                 etype.__name__ + "\n" + str(value))
            return

        stuff = self.console_outs[index]
        stuff += ">>> " + line + "\n"
        stuff += io.getvalue()
        self.console_outs[index] = stuff

        self.console_out.setPlainText(stuff)
        self.console_out.setVisible(True)
        # make sure we are at the end
        c = self.console_out.textCursor()
        c.movePosition(QTextCursor.End)
        self.console_out.setTextCursor(c)
        self.console_out.ensureCursorVisible()

        self.console.setText('')