Skip to content

Commit

Permalink
Added ErrorRedirector, which pushes Python runtime errors to a pop-up…
Browse files Browse the repository at this point in the history
…. Also fixed MATLAB error output to be more concise.
  • Loading branch information
newpomax committed May 21, 2021
1 parent 68e67c3 commit 40fd2de
Show file tree
Hide file tree
Showing 3 changed files with 72 additions and 9 deletions.
10 changes: 9 additions & 1 deletion PythonLib/CmdPane.py
Original file line number Diff line number Diff line change
Expand Up @@ -85,10 +85,18 @@ def on_change(self):

def _cmd_thread(self, cmd):
output = StringIO()
errout = StringIO()
try:
self.entry.unbind("<Return>") # prevent additional commands from being sent
self.matlabeng.eval(cmd, nargout = 0, stdout = output, stderr = output)
self.matlabeng.eval(cmd, nargout = 0, stdout = output, stderr = errout)
except:
pass # errors are caught in errout, which will be output differently from runtime errors
finally:
errs = errout.getvalue()
if errs != None and errs != '':
errs = errs.split('\n') # First line is "error using eval", which we don't need to print
errs = '\n'.join(errs[1:-1])
print("{0}".format(errs))
results = output.getvalue()
if results == None or results == '':
pass
Expand Down
55 changes: 55 additions & 0 deletions PythonLib/ErrorRedirector.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,55 @@
import tkinter as tk
from tkinter import messagebox
from tkinter import scrolledtext

NUM_LINES = 20

class ErrorRedirector:
def __init__(self, master):
self.master = master # tk root
self.err_popup = None
self.stxt = None

def stxt_init(self):
self.err_popup = tk.Toplevel(self.master)
self.err_popup.wm_title('Runtime Errors Encountered')
self.err_popup.iconbitmap(default="PythonLib/ssi_logo.ico")
self.stxt = scrolledtext.ScrolledText(master=self.err_popup, wrap='word', font = ('Courier New',11), foreground='black', background='white',relief='sunken',height=1)
err_icon = tk.Label(self.err_popup, image = "::tk::icons::warning")
err_icon.grid(row=0,column=0,sticky='nsew')
self.stxt.grid(row=0,column=1,sticky='nsew')
self.err_popup.columnconfigure(0,weight=1)
self.err_popup.columnconfigure(1,weight=3)
self.err_popup.rowconfigure(0,weight=1)
self.write("Runtime Errors - Please contact PropSim support if problems persist.\n")
self.err_popup.protocol("WM_DELETE_WINDOW", self.on_close)


def check_range(self):
if float(self.stxt.index("end-1c")) == NUM_LINES+2:
self.stxt.delete("1.0", "1.end + 1 char")

def write(self, msg):
if self.err_popup == None:
self.stxt_init()
self.master.bell()
err_msg = "{0}".format(msg)

self.stxt['state'] = 'normal'
self.stxt.insert(tk.END, err_msg)
self.stxt.see(tk.END)
self.check_range()
self.stxt['state'] = 'disabled'

def on_close(self):
self.err_popup.destroy()
self.err_popup = None # reset so that pre-write check catches the need to re-build the window

def flush(self):
pass

def __enter__(self):
return self

def __exit__(self, *args):
pass
16 changes: 8 additions & 8 deletions PythonLib/MainWindow.py
Original file line number Diff line number Diff line change
Expand Up @@ -36,10 +36,10 @@
# Results: each has a name, unit, and an associated plot name(s) (None if not plotted); by default, all are assumed to belong to the 'ans' struct

from .InputPane import InputPane
# from .OutputPane import OutputPane
from .PlotPane import PlotPane
from .CmdPane import CmdPane
from .PrintRedirector import PrintRedirector
from .ErrorRedirector import ErrorRedirector
from .Menubar import MenuBar

# IMPORT SIMPAGES and then add them to the simPages list to have them show up on the application
Expand Down Expand Up @@ -109,12 +109,12 @@ def run(self):
''' Starts the application loop, including the error logger and print redirector. '''
old_stdout = sys.stdout
old_stderr = sys.stderr
# error_logger = ErrorLogger(self, old_stderr, ERROR_LOG)
#with error_logger as sys.stderr:
with self.printRedirector as sys.stdout:
# Send a friendly message to get started
print("Welcome to PropSim! This is where all print-out is directed. You can also use the command line below to interact\n"
"with the active MATLAB session.")
self.mainloop() # start GUI application running, on close will call kill() function above
error_redirect = ErrorRedirector(self) # redirects Python runtime errors not caught by print outs to pop-ups
with error_redirect as sys.stderr:
with self.printRedirector as sys.stdout:
# Send a friendly message to get started
print("Welcome to PropSim! This is where all print-out is directed. You can also use the command line below to interact\n"
"with the active MATLAB session.")
self.mainloop() # start GUI application running, on close will call kill() function above
sys.stdout = old_stdout
sys.stderr = old_stderr

0 comments on commit 40fd2de

Please sign in to comment.