File indexing completed on 2025-01-19 03:59:51

0001 import io
0002 import sys
0003 import parser
0004 import inspect
0005 import traceback
0006 import contextlib
0007 
0008 from PyQt5.QtWidgets import *
0009 
0010 
0011 class Console(QWidget):
0012     def __init__(self, *a):
0013         super().__init__(*a)
0014         self.context_global = {}
0015         self.context_local = {}
0016 
0017         layout = QVBoxLayout()
0018         self.setLayout(layout)
0019 
0020         self.lines = QPlainTextEdit()
0021         self.lines.setReadOnly(True)
0022         layout.addWidget(self.lines)
0023 
0024         self.input = QLineEdit()
0025         self.input.returnPressed.connect(self.on_input)
0026         layout.addWidget(self.input)
0027 
0028     def set_font(self, font):
0029         self.lines.setFont(font)
0030         self.input.setFont(font)
0031 
0032     def define(self, name, value):
0033         self.context_global[name] = value
0034 
0035     def on_input(self):
0036         self.eval(self.input.text())
0037         self.input.clear()
0038 
0039     def eval(self, line):
0040         self.lines.appendPlainText(">>> " + line)
0041 
0042         try:
0043             try:
0044                 expression = True
0045                 code = compile(line, "<console>", "eval")
0046             except SyntaxError:
0047                 expression = False
0048                 code = compile(line, "<console>", "single")
0049 
0050             sterrout = io.StringIO()
0051             with contextlib.redirect_stderr(sterrout):
0052                 with contextlib.redirect_stdout(sterrout):
0053                     if expression:
0054                         value = eval(code, self.context_global, self.context_local)
0055                     else:
0056                         value = None
0057                         exec(code, self.context_global, self.context_local)
0058 
0059             stdstreams = sterrout.getvalue()
0060             if stdstreams:
0061                 if stdstreams.endswith("\n"):
0062                     stdstreams = stdstreams[:-1]
0063                 self.lines.appendPlainText(stdstreams)
0064             if value is not None:
0065                 self.lines.appendPlainText(repr(value))
0066         except Exception:
0067             etype, value, tb = sys.exc_info()
0068             # Find how many frames to print to hide the current frame and above
0069             parent = inspect.currentframe().f_back
0070             i = 0
0071             for frame, ln in traceback.walk_tb(tb):
0072                 i += 1
0073                 if frame.f_back == parent:
0074                     i = 0
0075 
0076             file = io.StringIO()
0077             traceback.print_exception(etype, value, tb, limit=-i, file=file)
0078             self.lines.appendPlainText(file.getvalue())
0079 
0080         self.lines.verticalScrollBar().setValue(self.lines.verticalScrollBar().maximum())