Merge pull request #557 from campagnola/console-updates
Allow console stack to be set outside of exceptions
This commit is contained in:
commit
3ddba03d08
@ -53,6 +53,7 @@ class ConsoleWidget(QtGui.QWidget):
|
|||||||
self.editor = editor
|
self.editor = editor
|
||||||
self.multiline = None
|
self.multiline = None
|
||||||
self.inCmd = False
|
self.inCmd = False
|
||||||
|
self.frames = [] # stack frames to access when an item in the stack list is selected
|
||||||
|
|
||||||
self.ui = template.Ui_Form()
|
self.ui = template.Ui_Form()
|
||||||
self.ui.setupUi(self)
|
self.ui.setupUi(self)
|
||||||
@ -133,14 +134,14 @@ class ConsoleWidget(QtGui.QWidget):
|
|||||||
def globals(self):
|
def globals(self):
|
||||||
frame = self.currentFrame()
|
frame = self.currentFrame()
|
||||||
if frame is not None and self.ui.runSelectedFrameCheck.isChecked():
|
if frame is not None and self.ui.runSelectedFrameCheck.isChecked():
|
||||||
return self.currentFrame().tb_frame.f_globals
|
return self.currentFrame().f_globals
|
||||||
else:
|
else:
|
||||||
return self.localNamespace
|
return self.localNamespace
|
||||||
|
|
||||||
def locals(self):
|
def locals(self):
|
||||||
frame = self.currentFrame()
|
frame = self.currentFrame()
|
||||||
if frame is not None and self.ui.runSelectedFrameCheck.isChecked():
|
if frame is not None and self.ui.runSelectedFrameCheck.isChecked():
|
||||||
return self.currentFrame().tb_frame.f_locals
|
return self.currentFrame().f_locals
|
||||||
else:
|
else:
|
||||||
return self.localNamespace
|
return self.localNamespace
|
||||||
|
|
||||||
@ -149,10 +150,7 @@ class ConsoleWidget(QtGui.QWidget):
|
|||||||
if self.currentTraceback is None:
|
if self.currentTraceback is None:
|
||||||
return None
|
return None
|
||||||
index = self.ui.exceptionStackList.currentRow()
|
index = self.ui.exceptionStackList.currentRow()
|
||||||
tb = self.currentTraceback
|
return self.frames[index]
|
||||||
for i in range(index):
|
|
||||||
tb = tb.tb_next
|
|
||||||
return tb
|
|
||||||
|
|
||||||
def execSingle(self, cmd):
|
def execSingle(self, cmd):
|
||||||
try:
|
try:
|
||||||
@ -171,7 +169,6 @@ class ConsoleWidget(QtGui.QWidget):
|
|||||||
except:
|
except:
|
||||||
self.displayException()
|
self.displayException()
|
||||||
|
|
||||||
|
|
||||||
def execMulti(self, nextLine):
|
def execMulti(self, nextLine):
|
||||||
#self.stdout.write(nextLine+"\n")
|
#self.stdout.write(nextLine+"\n")
|
||||||
if nextLine.strip() != '':
|
if nextLine.strip() != '':
|
||||||
@ -202,6 +199,10 @@ class ConsoleWidget(QtGui.QWidget):
|
|||||||
self.multiline = None
|
self.multiline = None
|
||||||
|
|
||||||
def write(self, strn, html=False):
|
def write(self, strn, html=False):
|
||||||
|
isGuiThread = QtCore.QThread.currentThread() == QtCore.QCoreApplication.instance().thread()
|
||||||
|
if not isGuiThread:
|
||||||
|
self.stdout.write(strn)
|
||||||
|
return
|
||||||
self.output.moveCursor(QtGui.QTextCursor.End)
|
self.output.moveCursor(QtGui.QTextCursor.End)
|
||||||
if html:
|
if html:
|
||||||
self.output.textCursor().insertHtml(strn)
|
self.output.textCursor().insertHtml(strn)
|
||||||
@ -293,14 +294,6 @@ class ConsoleWidget(QtGui.QWidget):
|
|||||||
fileName = tb.tb_frame.f_code.co_filename
|
fileName = tb.tb_frame.f_code.co_filename
|
||||||
subprocess.Popen(self.editor.format(fileName=fileName, lineNum=lineNum), shell=True)
|
subprocess.Popen(self.editor.format(fileName=fileName, lineNum=lineNum), shell=True)
|
||||||
|
|
||||||
|
|
||||||
#def allExceptionsHandler(self, *args):
|
|
||||||
#self.exceptionHandler(*args)
|
|
||||||
|
|
||||||
#def nextExceptionHandler(self, *args):
|
|
||||||
#self.ui.catchNextExceptionBtn.setChecked(False)
|
|
||||||
#self.exceptionHandler(*args)
|
|
||||||
|
|
||||||
def updateSysTrace(self):
|
def updateSysTrace(self):
|
||||||
## Install or uninstall sys.settrace handler
|
## Install or uninstall sys.settrace handler
|
||||||
|
|
||||||
@ -319,24 +312,72 @@ class ConsoleWidget(QtGui.QWidget):
|
|||||||
else:
|
else:
|
||||||
sys.settrace(self.systrace)
|
sys.settrace(self.systrace)
|
||||||
|
|
||||||
def exceptionHandler(self, excType, exc, tb):
|
def exceptionHandler(self, excType, exc, tb, systrace=False):
|
||||||
if self.ui.catchNextExceptionBtn.isChecked():
|
if self.ui.catchNextExceptionBtn.isChecked():
|
||||||
self.ui.catchNextExceptionBtn.setChecked(False)
|
self.ui.catchNextExceptionBtn.setChecked(False)
|
||||||
elif not self.ui.catchAllExceptionsBtn.isChecked():
|
elif not self.ui.catchAllExceptionsBtn.isChecked():
|
||||||
return
|
return
|
||||||
|
|
||||||
self.ui.clearExceptionBtn.setEnabled(True)
|
|
||||||
self.currentTraceback = tb
|
self.currentTraceback = tb
|
||||||
|
|
||||||
excMessage = ''.join(traceback.format_exception_only(excType, exc))
|
excMessage = ''.join(traceback.format_exception_only(excType, exc))
|
||||||
self.ui.exceptionInfoLabel.setText(excMessage)
|
self.ui.exceptionInfoLabel.setText(excMessage)
|
||||||
|
|
||||||
|
if systrace:
|
||||||
|
# exceptions caught using systrace don't need the usual
|
||||||
|
# call stack + traceback handling
|
||||||
|
self.setStack(sys._getframe().f_back.f_back)
|
||||||
|
else:
|
||||||
|
self.setStack(frame=sys._getframe().f_back, tb=tb)
|
||||||
|
|
||||||
|
def setStack(self, frame=None, tb=None):
|
||||||
|
"""Display a call stack and exception traceback.
|
||||||
|
|
||||||
|
This allows the user to probe the contents of any frame in the given stack.
|
||||||
|
|
||||||
|
*frame* may either be a Frame instance or None, in which case the current
|
||||||
|
frame is retrieved from ``sys._getframe()``.
|
||||||
|
|
||||||
|
If *tb* is provided then the frames in the traceback will be appended to
|
||||||
|
the end of the stack list. If *tb* is None, then sys.exc_info() will
|
||||||
|
be checked instead.
|
||||||
|
"""
|
||||||
|
self.ui.clearExceptionBtn.setEnabled(True)
|
||||||
|
|
||||||
|
if frame is None:
|
||||||
|
frame = sys._getframe().f_back
|
||||||
|
|
||||||
|
if tb is None:
|
||||||
|
tb = sys.exc_info()[2]
|
||||||
|
|
||||||
self.ui.exceptionStackList.clear()
|
self.ui.exceptionStackList.clear()
|
||||||
|
self.frames = []
|
||||||
|
|
||||||
|
# Build stack up to this point
|
||||||
|
for index, line in enumerate(traceback.extract_stack(frame)):
|
||||||
|
self.ui.exceptionStackList.addItem('File "%s", line %s, in %s()\n %s' % line)
|
||||||
|
while frame is not None:
|
||||||
|
self.frames.insert(0, frame)
|
||||||
|
frame = frame.f_back
|
||||||
|
|
||||||
|
if tb is None:
|
||||||
|
return
|
||||||
|
|
||||||
|
self.ui.exceptionStackList.addItem('-- exception caught here: --')
|
||||||
|
item = self.ui.exceptionStackList.item(self.ui.exceptionStackList.count()-1)
|
||||||
|
item.setBackground(QtGui.QBrush(QtGui.QColor(200, 200, 200)))
|
||||||
|
self.frames.append(None)
|
||||||
|
|
||||||
|
# And finish the rest of the stack up to the exception
|
||||||
for index, line in enumerate(traceback.extract_tb(tb)):
|
for index, line in enumerate(traceback.extract_tb(tb)):
|
||||||
self.ui.exceptionStackList.addItem('File "%s", line %s, in %s()\n %s' % line)
|
self.ui.exceptionStackList.addItem('File "%s", line %s, in %s()\n %s' % line)
|
||||||
|
while tb is not None:
|
||||||
|
self.frames.append(tb.tb_frame)
|
||||||
|
tb = tb.tb_next
|
||||||
|
|
||||||
def systrace(self, frame, event, arg):
|
def systrace(self, frame, event, arg):
|
||||||
if event == 'exception' and self.checkException(*arg):
|
if event == 'exception' and self.checkException(*arg):
|
||||||
self.exceptionHandler(*arg)
|
self.exceptionHandler(*arg, systrace=True)
|
||||||
return self.systrace
|
return self.systrace
|
||||||
|
|
||||||
def checkException(self, excType, exc, tb):
|
def checkException(self, excType, exc, tb):
|
||||||
|
@ -86,7 +86,10 @@
|
|||||||
<property name="bottomMargin">
|
<property name="bottomMargin">
|
||||||
<number>0</number>
|
<number>0</number>
|
||||||
</property>
|
</property>
|
||||||
<property name="spacing">
|
<property name="horizontalSpacing">
|
||||||
|
<number>2</number>
|
||||||
|
</property>
|
||||||
|
<property name="verticalSpacing">
|
||||||
<number>0</number>
|
<number>0</number>
|
||||||
</property>
|
</property>
|
||||||
<item row="0" column="6">
|
<item row="0" column="6">
|
||||||
@ -95,7 +98,7 @@
|
|||||||
<bool>false</bool>
|
<bool>false</bool>
|
||||||
</property>
|
</property>
|
||||||
<property name="text">
|
<property name="text">
|
||||||
<string>Clear Exception</string>
|
<string>Clear Stack</string>
|
||||||
</property>
|
</property>
|
||||||
</widget>
|
</widget>
|
||||||
</item>
|
</item>
|
||||||
@ -149,7 +152,7 @@
|
|||||||
<item row="1" column="0" colspan="7">
|
<item row="1" column="0" colspan="7">
|
||||||
<widget class="QLabel" name="exceptionInfoLabel">
|
<widget class="QLabel" name="exceptionInfoLabel">
|
||||||
<property name="text">
|
<property name="text">
|
||||||
<string>Exception Info</string>
|
<string>Stack Trace</string>
|
||||||
</property>
|
</property>
|
||||||
</widget>
|
</widget>
|
||||||
</item>
|
</item>
|
||||||
|
@ -2,7 +2,7 @@
|
|||||||
|
|
||||||
# Form implementation generated from reading ui file 'template.ui'
|
# Form implementation generated from reading ui file 'template.ui'
|
||||||
#
|
#
|
||||||
# Created: Fri May 02 18:55:28 2014
|
# Created: Wed Apr 08 16:28:53 2015
|
||||||
# by: PyQt4 UI code generator 4.10.4
|
# by: PyQt4 UI code generator 4.10.4
|
||||||
#
|
#
|
||||||
# WARNING! All changes made in this file will be lost!
|
# WARNING! All changes made in this file will be lost!
|
||||||
@ -68,8 +68,9 @@ class Ui_Form(object):
|
|||||||
self.exceptionGroup = QtGui.QGroupBox(self.splitter)
|
self.exceptionGroup = QtGui.QGroupBox(self.splitter)
|
||||||
self.exceptionGroup.setObjectName(_fromUtf8("exceptionGroup"))
|
self.exceptionGroup.setObjectName(_fromUtf8("exceptionGroup"))
|
||||||
self.gridLayout_2 = QtGui.QGridLayout(self.exceptionGroup)
|
self.gridLayout_2 = QtGui.QGridLayout(self.exceptionGroup)
|
||||||
self.gridLayout_2.setSpacing(0)
|
|
||||||
self.gridLayout_2.setContentsMargins(-1, 0, -1, 0)
|
self.gridLayout_2.setContentsMargins(-1, 0, -1, 0)
|
||||||
|
self.gridLayout_2.setHorizontalSpacing(2)
|
||||||
|
self.gridLayout_2.setVerticalSpacing(0)
|
||||||
self.gridLayout_2.setObjectName(_fromUtf8("gridLayout_2"))
|
self.gridLayout_2.setObjectName(_fromUtf8("gridLayout_2"))
|
||||||
self.clearExceptionBtn = QtGui.QPushButton(self.exceptionGroup)
|
self.clearExceptionBtn = QtGui.QPushButton(self.exceptionGroup)
|
||||||
self.clearExceptionBtn.setEnabled(False)
|
self.clearExceptionBtn.setEnabled(False)
|
||||||
@ -116,12 +117,12 @@ class Ui_Form(object):
|
|||||||
self.historyBtn.setText(_translate("Form", "History..", None))
|
self.historyBtn.setText(_translate("Form", "History..", None))
|
||||||
self.exceptionBtn.setText(_translate("Form", "Exceptions..", None))
|
self.exceptionBtn.setText(_translate("Form", "Exceptions..", None))
|
||||||
self.exceptionGroup.setTitle(_translate("Form", "Exception Handling", None))
|
self.exceptionGroup.setTitle(_translate("Form", "Exception Handling", None))
|
||||||
self.clearExceptionBtn.setText(_translate("Form", "Clear Exception", None))
|
self.clearExceptionBtn.setText(_translate("Form", "Clear Stack", None))
|
||||||
self.catchAllExceptionsBtn.setText(_translate("Form", "Show All Exceptions", None))
|
self.catchAllExceptionsBtn.setText(_translate("Form", "Show All Exceptions", None))
|
||||||
self.catchNextExceptionBtn.setText(_translate("Form", "Show Next Exception", None))
|
self.catchNextExceptionBtn.setText(_translate("Form", "Show Next Exception", None))
|
||||||
self.onlyUncaughtCheck.setText(_translate("Form", "Only Uncaught Exceptions", None))
|
self.onlyUncaughtCheck.setText(_translate("Form", "Only Uncaught Exceptions", None))
|
||||||
self.runSelectedFrameCheck.setText(_translate("Form", "Run commands in selected stack frame", None))
|
self.runSelectedFrameCheck.setText(_translate("Form", "Run commands in selected stack frame", None))
|
||||||
self.exceptionInfoLabel.setText(_translate("Form", "Exception Info", None))
|
self.exceptionInfoLabel.setText(_translate("Form", "Stack Trace", None))
|
||||||
self.label.setText(_translate("Form", "Filter (regex):", None))
|
self.label.setText(_translate("Form", "Filter (regex):", None))
|
||||||
|
|
||||||
from .CmdInput import CmdInput
|
from .CmdInput import CmdInput
|
||||||
|
@ -100,7 +100,7 @@ class Ui_Form(object):
|
|||||||
self.catchNextExceptionBtn.setText(QtGui.QApplication.translate("Form", "Show Next Exception", None, QtGui.QApplication.UnicodeUTF8))
|
self.catchNextExceptionBtn.setText(QtGui.QApplication.translate("Form", "Show Next Exception", None, QtGui.QApplication.UnicodeUTF8))
|
||||||
self.onlyUncaughtCheck.setText(QtGui.QApplication.translate("Form", "Only Uncaught Exceptions", None, QtGui.QApplication.UnicodeUTF8))
|
self.onlyUncaughtCheck.setText(QtGui.QApplication.translate("Form", "Only Uncaught Exceptions", None, QtGui.QApplication.UnicodeUTF8))
|
||||||
self.runSelectedFrameCheck.setText(QtGui.QApplication.translate("Form", "Run commands in selected stack frame", None, QtGui.QApplication.UnicodeUTF8))
|
self.runSelectedFrameCheck.setText(QtGui.QApplication.translate("Form", "Run commands in selected stack frame", None, QtGui.QApplication.UnicodeUTF8))
|
||||||
self.exceptionInfoLabel.setText(QtGui.QApplication.translate("Form", "Exception Info", None, QtGui.QApplication.UnicodeUTF8))
|
self.exceptionInfoLabel.setText(QtGui.QApplication.translate("Form", "Stack Trace", None, QtGui.QApplication.UnicodeUTF8))
|
||||||
self.clearExceptionBtn.setText(QtGui.QApplication.translate("Form", "Clear Exception", None, QtGui.QApplication.UnicodeUTF8))
|
self.clearExceptionBtn.setText(QtGui.QApplication.translate("Form", "Clear Stack", None, QtGui.QApplication.UnicodeUTF8))
|
||||||
|
|
||||||
from .CmdInput import CmdInput
|
from .CmdInput import CmdInput
|
||||||
|
Loading…
Reference in New Issue
Block a user