123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132 |
- import linecache
- import os
- import tkinter as tk
- from idlelib.debugobj import ObjectTreeItem, make_objecttreeitem
- from idlelib.tree import TreeNode, TreeItem, ScrolledCanvas
- def StackBrowser(root, exc, flist=None, top=None):
- global sc, item, node # For testing.
- if top is None:
- top = tk.Toplevel(root)
- sc = ScrolledCanvas(top, bg="white", highlightthickness=0)
- sc.frame.pack(expand=1, fill="both")
- item = StackTreeItem(exc, flist)
- node = TreeNode(sc.canvas, None, item)
- node.expand()
- class StackTreeItem(TreeItem):
- def __init__(self, exc, flist=None):
- self.flist = flist
- self.stack = self.get_stack(None if exc is None else exc.__traceback__)
- self.text = f"{type(exc).__name__}: {str(exc)}"
- def get_stack(self, tb):
- stack = []
- if tb and tb.tb_frame is None:
- tb = tb.tb_next
- while tb is not None:
- stack.append((tb.tb_frame, tb.tb_lineno))
- tb = tb.tb_next
- return stack
- def GetText(self): # Titlecase names are overrides.
- return self.text
- def GetSubList(self):
- sublist = []
- for info in self.stack:
- item = FrameTreeItem(info, self.flist)
- sublist.append(item)
- return sublist
- class FrameTreeItem(TreeItem):
- def __init__(self, info, flist):
- self.info = info
- self.flist = flist
- def GetText(self):
- frame, lineno = self.info
- try:
- modname = frame.f_globals["__name__"]
- except:
- modname = "?"
- code = frame.f_code
- filename = code.co_filename
- funcname = code.co_name
- sourceline = linecache.getline(filename, lineno)
- sourceline = sourceline.strip()
- if funcname in ("?", "", None):
- item = "%s, line %d: %s" % (modname, lineno, sourceline)
- else:
- item = "%s.%s(...), line %d: %s" % (modname, funcname,
- lineno, sourceline)
- return item
- def GetSubList(self):
- frame, lineno = self.info
- sublist = []
- if frame.f_globals is not frame.f_locals:
- item = VariablesTreeItem("<locals>", frame.f_locals, self.flist)
- sublist.append(item)
- item = VariablesTreeItem("<globals>", frame.f_globals, self.flist)
- sublist.append(item)
- return sublist
- def OnDoubleClick(self):
- if self.flist:
- frame, lineno = self.info
- filename = frame.f_code.co_filename
- if os.path.isfile(filename):
- self.flist.gotofileline(filename, lineno)
- class VariablesTreeItem(ObjectTreeItem):
- def GetText(self):
- return self.labeltext
- def GetLabelText(self):
- return None
- def IsExpandable(self):
- return len(self.object) > 0
- def GetSubList(self):
- sublist = []
- for key in self.object.keys():
- try:
- value = self.object[key]
- except KeyError:
- continue
- def setfunction(value, key=key, object=self.object):
- object[key] = value
- item = make_objecttreeitem(key + " =", value, setfunction)
- sublist.append(item)
- return sublist
- def _stack_viewer(parent): # htest #
- from idlelib.pyshell import PyShellFileList
- top = tk.Toplevel(parent)
- top.title("Test StackViewer")
- x, y = map(int, parent.geometry().split('+')[1:])
- top.geometry("+%d+%d" % (x + 50, y + 175))
- flist = PyShellFileList(top)
- try: # to obtain a traceback object
- intentional_name_error
- except NameError as e:
- StackBrowser(top, e, flist=flist, top=top)
- if __name__ == '__main__':
- from unittest import main
- main('idlelib.idle_test.test_stackviewer', verbosity=2, exit=False)
- from idlelib.idle_test.htest import run
- run(_stack_viewer)
|