wxPython4 sequels: fix Wx exceptions ignored because no traceback
authorEdouard Tisserant <edouard.tisserant@gmail.com>
Sun, 17 Jul 2022 17:47:11 +0200
changeset 3546 ee51d1deadfd
parent 3545 67e1707f24c8
child 3547 8a9a7d180b93
wxPython4 sequels: fix Wx exceptions ignored because no traceback

Some exception triggered on wxPython side have None as traceback,
and exception hanlder was discarding them.
controls/LocationCellEditor.py
editors/Viewer.py
util/ExceptionHandler.py
--- a/controls/LocationCellEditor.py	Fri Jul 15 14:50:07 2022 +0200
+++ b/controls/LocationCellEditor.py	Sun Jul 17 17:47:11 2022 +0200
@@ -178,7 +178,7 @@
             self.CellControl.SetVarType(self.Table.GetValueByName(row, 'Type'))
         self.CellControl.SetFocus()
 
-    def EndEditInternal(self, row, col, grid, old_loc):
+    def EndEdit(self, row, col, grid, old_loc):
         loc = self.CellControl.GetValue()
         changed = loc != old_loc
         if changed:
@@ -201,13 +201,8 @@
         self.CellControl.Disable()
         return changed
 
-    if wx.VERSION >= (3, 0, 0):
-        def EndEdit(self, row, col, grid, oldval):
-            return self.EndEditInternal(row, col, grid, oldval)
-    else:
-        def EndEdit(self, row, col, grid):
-            old_loc = self.Table.GetValueByName(row, 'Location')
-            return self.EndEditInternal(row, col, grid, old_loc)
+    def ApplyEdit(self, row, col, grid):
+        pass
 
     def SetSize(self, rect):
         self.CellControl.SetDimensions(rect.x + 1, rect.y,
--- a/editors/Viewer.py	Fri Jul 15 14:50:07 2022 +0200
+++ b/editors/Viewer.py	Sun Jul 17 17:47:11 2022 +0200
@@ -317,7 +317,7 @@
                             selected = None
                         dialog.Destroy()
                         if selected is None:
-                            return
+                            return False
                         if selected == 0:
                             location = "%I" + location
                         elif selected == 1:
@@ -333,7 +333,7 @@
                     var_name = dlg.GetValue() if dlg.ShowModal() == wx.ID_OK else None
                     dlg.Destroy()
                     if var_name is None:
-                        return
+                        return False
                     elif var_name.upper() in [name.upper() for name in self.ParentWindow.Controler.GetProjectPouNames(self.ParentWindow.Debug)]:
                         message = _("\"%s\" pou already exists!") % var_name
                     elif not var_name.upper() in [name.upper() for name in self.ParentWindow.Controler.GetEditedElementVariables(tagname, self.ParentWindow.Debug)]:
@@ -363,7 +363,7 @@
                     var_name = dlg.GetValue() if dlg.ShowModal() == wx.ID_OK else None
                     dlg.Destroy()
                     if var_name is None:
-                        return
+                        return False
                     elif var_name.upper() in [name.upper() for name in self.ParentWindow.Controler.GetProjectPouNames(self.ParentWindow.Debug)]:
                         message = _("\"%s\" pou already exists!") % var_name
                     elif not var_name.upper() in [name.upper() for name in self.ParentWindow.Controler.GetEditedElementVariables(tagname, self.ParentWindow.Debug)]:
@@ -385,7 +385,7 @@
                 var_name = dlg.GetValue() if dlg.ShowModal() == wx.ID_OK else None
                 dlg.Destroy()
                 if var_name is None:
-                    return
+                    return False
                 elif var_name.upper() in [name.upper() for name in self.ParentWindow.Controler.GetProjectPouNames(self.ParentWindow.Debug)]:
                     message = _("\"%s\" pou already exists!") % var_name
                 elif not var_name.upper() in [name.upper() for name in self.ParentWindow.Controler.GetEditedElementVariables(tagname, self.ParentWindow.Debug)]:
@@ -419,6 +419,8 @@
                 message = _("Variable don't belong to this POU!")
         if message is not None:
             wx.CallAfter(self.ShowMessage, message)
+            return False
+        return True
 
     def GenerateTreeMenu(self, x, y, scaling, menu, base_path, var_class, tree):
         for child_name, child_type, (child_tree, child_dimensions) in tree:
--- a/util/ExceptionHandler.py	Fri Jul 15 14:50:07 2022 +0200
+++ b/util/ExceptionHandler.py	Sun Jul 17 17:47:11 2022 +0200
@@ -81,8 +81,14 @@
 
 
 def get_last_traceback(tb):
-    while tb.tb_next:
-        tb = tb.tb_next
+    while True:
+        if not hasattr(tb, "tb_next"):
+            break
+        if tb.tb_next:
+            tb = tb.tb_next
+        else:
+            break
+
     return tb
 
 
@@ -111,7 +117,8 @@
         if e_traceback:
             info['traceback'] = ''.join(traceback.format_tb(e_traceback)) + '%s: %s' % (e_type, e_value)
             last_tb = get_last_traceback(e_traceback)
-            exception_locals = last_tb.tb_frame.f_locals  # the locals at the level of the stack trace where the exception actually occurred
+            # save locals at the level of the stack trace where the exception actually occurred
+            exception_locals = last_tb.tb_frame.f_locals if last_tb else {};
             info['locals'] = format_namespace(exception_locals)
             if 'self' in exception_locals:
                 try:
@@ -134,7 +141,8 @@
     def handle_exception(e_type, e_value, e_traceback, exit=False):
         traceback.print_exception(e_type, e_value, e_traceback)  # this is very helpful when there's an exception in the rest of this func
         last_tb = get_last_traceback(e_traceback)
-        ex = (last_tb.tb_frame.f_code.co_filename, last_tb.tb_frame.f_lineno)
+        ex = (last_tb.tb_frame.f_code.co_filename if last_tb else "unknown",
+              last_tb.tb_frame.f_lineno if last_tb else None)
         if ex not in ignored_exceptions:
             ignored_exceptions.append(ex)
             date = time.ctime()