diff --git a/plugins/extensions/pykrita/plugin/plugins/scripter/debugcontroller.py b/plugins/extensions/pykrita/plugin/plugins/scripter/debugcontroller.py --- a/plugins/extensions/pykrita/plugin/plugins/scripter/debugcontroller.py +++ b/plugins/extensions/pykrita/plugin/plugins/scripter/debugcontroller.py @@ -46,13 +46,16 @@ def currentLine(self): try: if self._debugger: - return int(self._debugger.application_data['code']['lineNumber']) + return int(self.debuggerData['code']['lineNumber']) except: return 0 def updateUIDebugger(self): widget = self.scripter.uicontroller.findStackWidget('Debugger') + exception = self._debuggerException() + if exception: + self.scripter.uicontroller.showException(exception) if not self.isActive or self._quitDebugger(): widget.disableToolbar(True) @@ -67,9 +70,14 @@ except: return - def _quitDebugger(self): try: - return self._debugger.application_data['quit'] + return self.debuggerData['quit'] + except: + return False + + def _debuggerException(self): + try: + return self.debuggerData['exception'] except: return False diff --git a/plugins/extensions/pykrita/plugin/plugins/scripter/debugger_scripter/debugger.py b/plugins/extensions/pykrita/plugin/plugins/scripter/debugger_scripter/debugger.py --- a/plugins/extensions/pykrita/plugin/plugins/scripter/debugger_scripter/debugger.py +++ b/plugins/extensions/pykrita/plugin/plugins/scripter/debugger_scripter/debugger.py @@ -3,8 +3,7 @@ import inspect import multiprocessing import re - - +import asyncio from . import debuggerformatter @@ -18,13 +17,19 @@ self.scripter = scripter self.applicationq = multiprocessing.Queue() self.filePath = self.scripter.documentcontroller.activeDocument.filePath - # Create the debug process - self.debugprocess = multiprocessing.Process(target=self.run, args=(cmd,)) self.application_data = {} + self.exception_data = {} + self.debugprocess = multiprocessing.Process(target=self.run, args=(cmd,)) self.currentLine = 0 - # initialize parent + bdb.Bdb.reset(self) + def run(self, cmd): + try: + super(Debugger, self).run(cmd) + except Execept as e: + raise e + def user_call(self, frame, args): name = frame.f_code.co_name or "" @@ -49,55 +54,45 @@ if self.quit: return self.set_quit() - if self.currentLine==0: return else: - # Wait for a debug command cmd = self.debugq.get() if cmd == "step": - # If stepping through code, return this handler return - if cmd == "stop": - # If stopping execution, raise an exception return self.set_quit() def user_return(self, frame, value): name = frame.f_code.co_name or "" + if name == '': self.applicationq.put({ "quit": True}) def user_exception(self, frame, exception): - name = frame.f_code.co_name or "" + self.applicationq.put({ "exception": str(exception[1])}) async def display(self): """Coroutine for updating the UI""" - # Wait for the application queue to have an update to the GUI while True: if self.applicationq.empty(): await asyncio.sleep(0.3) else: - # The application queue has at least one item, let's act on every item that's in it while not self.applicationq.empty(): - # Get info to the GUI - self.application_data = self.applicationq.get() - self.scripter.uicontroller.repaintDebugArea() - return + self.application_data.update(self.applicationq.get()) + self.scripter.uicontroller.repaintDebugArea() + return async def start(self): await self.display() async def step(self): - # Tell the debugger we want to step in self.debugq.put("step") - await self.display() async def stop(self): - # Tell the debugger we're stopping execution self.debugq.put("stop") self.applicationq.put({ "quit": True}) await self.display() diff --git a/plugins/extensions/pykrita/plugin/plugins/scripter/debugger_scripter/debuggerformatter.py b/plugins/extensions/pykrita/plugin/plugins/scripter/debugger_scripter/debuggerformatter.py --- a/plugins/extensions/pykrita/plugin/plugins/scripter/debugger_scripter/debuggerformatter.py +++ b/plugins/extensions/pykrita/plugin/plugins/scripter/debugger_scripter/debuggerformatter.py @@ -19,7 +19,7 @@ types.ModuleType, types.FunctionType] - return [{k: v} for k, v in data.items() if not (k in exclude_keys or + return [{k: {'value': str(v), 'type': str(type(v))}} for k, v in data.items() if not (k in exclude_keys or type(v) in exclude_valuetypes or re.search(r'^(__).*\1$', k) or inspect.isclass(v) or diff --git a/plugins/extensions/pykrita/plugin/plugins/scripter/ui_scripter/actions/runaction/runaction.py b/plugins/extensions/pykrita/plugin/plugins/scripter/ui_scripter/actions/runaction/runaction.py --- a/plugins/extensions/pykrita/plugin/plugins/scripter/ui_scripter/actions/runaction/runaction.py +++ b/plugins/extensions/pykrita/plugin/plugins/scripter/ui_scripter/actions/runaction/runaction.py @@ -4,6 +4,7 @@ from . import docwrapper import os + class RunAction(QAction): def __init__(self, scripter, parent=None): @@ -36,11 +37,8 @@ script = self.editor.document().toPlainText() try: bc = compile(document.data, document.filePath, "exec") + exec(bc) except Exception as e: - QMessageBox.critical(self.editor, "Error compiling script", str(e)) - return - - exec(bc) - + self.scripter.uicontroller.showException(str(e)) sys.stdout = stdout sys.stderr = stderr diff --git a/plugins/extensions/pykrita/plugin/plugins/scripter/ui_scripter/stackwidgets/debuggerwidget/debuggertable.py b/plugins/extensions/pykrita/plugin/plugins/scripter/ui_scripter/stackwidgets/debuggerwidget/debuggertable.py --- a/plugins/extensions/pykrita/plugin/plugins/scripter/ui_scripter/stackwidgets/debuggerwidget/debuggertable.py +++ b/plugins/extensions/pykrita/plugin/plugins/scripter/ui_scripter/stackwidgets/debuggerwidget/debuggertable.py @@ -16,7 +16,7 @@ self.clearContents() self.setRowCount(0) - if data and not data.get('quit'): + if data and not data.get('quit') and not data.get('exception'): locals_list = data['frame']['locals'] globals_list = data['frame']['globals'] @@ -29,5 +29,5 @@ self.insertRow(row) self.setItem(row, 0, QTableWidgetItem(str(scope_key))) self.setItem(row, 1, QTableWidgetItem(key)) - self.setItem(row, 2, QTableWidgetItem(str(value))) - self.setItem(row, 3, QTableWidgetItem(str(type(value)))) + self.setItem(row, 2, QTableWidgetItem(value['value'])) + self.setItem(row, 3, QTableWidgetItem(value['type'])) diff --git a/plugins/extensions/pykrita/plugin/plugins/scripter/uicontroller.py b/plugins/extensions/pykrita/plugin/plugins/scripter/uicontroller.py --- a/plugins/extensions/pykrita/plugin/plugins/scripter/uicontroller.py +++ b/plugins/extensions/pykrita/plugin/plugins/scripter/uicontroller.py @@ -20,6 +20,7 @@ self.actions = [] self.mainWidget.setWindowModality(Qt.NonModal) + def initialize(self, scripter): self.editor = pythoneditor.CodeEditor(scripter) self.widgetSelector = QComboBox() @@ -117,6 +118,9 @@ if widget.objectName() == widgetName: return widget + def showException(self, exception): + QMessageBox.critical(self.editor, "Error running script", str(exception)) + def setDocumentEditor(self, document): self.editor.clear() self.editor.moveCursor(QTextCursor.Start)