diff options
Diffstat (limited to 'Lib/idlelib/stackviewer.py')
| -rw-r--r-- | Lib/idlelib/stackviewer.py | 153 | 
1 files changed, 153 insertions, 0 deletions
| diff --git a/Lib/idlelib/stackviewer.py b/Lib/idlelib/stackviewer.py new file mode 100644 index 0000000..0698def --- /dev/null +++ b/Lib/idlelib/stackviewer.py @@ -0,0 +1,153 @@ +import linecache +import os +import re +import sys + +import tkinter as tk + +from idlelib.debugobj import ObjectTreeItem, make_objecttreeitem +from idlelib.tree import TreeNode, TreeItem, ScrolledCanvas + +def StackBrowser(root, flist=None, tb=None, top=None): +    if top is None: +        top = tk.Toplevel(root) +    sc = ScrolledCanvas(top, bg="white", highlightthickness=0) +    sc.frame.pack(expand=1, fill="both") +    item = StackTreeItem(flist, tb) +    node = TreeNode(sc.canvas, None, item) +    node.expand() + + +class StackTreeItem(TreeItem): + +    def __init__(self, flist=None, tb=None): +        self.flist = flist +        self.stack = self.get_stack(tb) +        self.text = self.get_exception() + +    def get_stack(self, tb): +        if tb is None: +            tb = sys.last_traceback +        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 get_exception(self): +        type = sys.last_type +        value = sys.last_value +        if hasattr(type, "__name__"): +            type = type.__name__ +        s = str(type) +        if value is not None: +            s = s + ": " + str(value) +        return s + +    def GetText(self): +        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: +        exc_type, exc_value, exc_tb = sys.exc_info() + +    # inject stack trace to sys +    sys.last_type = exc_type +    sys.last_value = exc_value +    sys.last_traceback = exc_tb + +    StackBrowser(top, flist=flist, top=top, tb=exc_tb) + +    # restore sys to original state +    del sys.last_type +    del sys.last_value +    del sys.last_traceback + +if __name__ == '__main__': +    from idlelib.idle_test.htest import run +    run(_stack_viewer) | 
