Skip to content

Commit

Permalink
[ui] ScriptEditor: Updated Core ScriptEditor Manager to show better e…
Browse files Browse the repository at this point in the history
…xceptions

ScriptEditorManager now also allows the code to be saved and retrieved back. Exceptions are now shown with a better output to the user.
  • Loading branch information
waaake committed Oct 28, 2024
1 parent 88f9d4b commit 3e0024e
Showing 1 changed file with 60 additions and 4 deletions.
64 changes: 60 additions & 4 deletions meshroom/ui/components/scriptEditor.py
Original file line number Diff line number Diff line change
@@ -1,9 +1,15 @@
from PySide2.QtCore import QObject, Slot
from PySide2.QtCore import QObject, Slot, QSettings

from io import StringIO
from contextlib import redirect_stdout
import traceback

class ScriptEditorManager(QObject):
""" Manages the script editor history and logs.
"""

_GROUP = "ScriptEditor"
_KEY = "script"

def __init__(self, parent=None):
super(ScriptEditorManager, self).__init__(parent=parent)
Expand All @@ -13,20 +19,52 @@ def __init__(self, parent=None):
self._globals = {}
self._locals = {}

# Protected
def _defaultScript(self):
""" Returns the default script for the script editor.
"""
lines = (
"from meshroom.ui import uiInstance\n",
"graph = uiInstance.activeProject.graph",
"for node in graph.nodes:",
" print(node.name)"
)

return "\n".join(lines)

def _lastScript(self):
""" Returns the last script from the user settings.
"""
settings = QSettings()
settings.beginGroup(self._GROUP)
return settings.value(self._KEY)

# Public
@Slot(str, result=str)
def process(self, script):
""" Execute the provided input script, capture the output from the standard output, and return it. """
# Saves the state if an exception has occured
exception = False

stdout = StringIO()
with redirect_stdout(stdout):
try:
exec(script, self._globals, self._locals)
except Exception as exception:
# Format and print the exception to stdout, which will be captured
print("{}: {}".format(type(exception).__name__, exception))
except Exception:
# Update that we have an exception that is thrown
exception = True
# Print the backtrace
traceback.print_exc(file=stdout)

result = stdout.getvalue().strip()

# Strip out additional part
if exception:
# We know that we're executing the above statement and that caused the exception
# What we want to show to the user is just the part that happened while executing the script
# So just split with the last part and show it to the user
result = result.split("self._locals)", 1)[-1]

# Add the script to the history and move up the index to the top of history stack
self._history.append(script)
self._index = len(self._history)
Expand Down Expand Up @@ -58,3 +96,21 @@ def getPreviousScript(self):
elif self._index == 0 and len(self._history):
return self._history[self._index]
return ""

@Slot(result=str)
def loadLastScript(self):
""" Returns the last executed script from the prefs.
"""
return self._lastScript() or self._defaultScript()

@Slot(str)
def saveScript(self, script):
""" Returns the last executed script from the prefs.
Args:
script (str): The script to save.
"""
settings = QSettings()
settings.beginGroup(self._GROUP)
settings.setValue(self._KEY, script)
settings.sync()

0 comments on commit 3e0024e

Please sign in to comment.