Viewing file: ClassBrowser.py (6.02 KB) -rw-r--r-- Select action/file-type: (+) | (+) | (+) | Code (+) | Session (+) | (+) | SDB (+) | (+) | (+) | (+) | (+) | (+) |
"""Class browser.
XXX TO DO:
- reparse when source changed (maybe just a button would be OK?) (or recheck on window popup) - add popup menu with more options (e.g. doc strings, base classes, imports) - show function argument list? (have to do pattern matching on source) - should the classes and methods lists also be in the module's menu bar? - add base classes to class browser tree """
import os import sys import pyclbr
import PyShell from WindowList import ListedToplevel from TreeWidget import TreeNode, TreeItem, ScrolledCanvas
class ClassBrowser:
def __init__(self, flist, name, path): # XXX This API should change, if the file doesn't end in ".py" # XXX the code here is bogus! self.name = name self.file = os.path.join(path[0], self.name + ".py") self.init(flist)
def close(self, event=None): self.top.destroy() self.node.destroy()
def init(self, flist): self.flist = flist # reset pyclbr pyclbr._modules.clear() # create top self.top = top = ListedToplevel(flist.root) top.protocol("WM_DELETE_WINDOW", self.close) top.bind("<Escape>", self.close) self.settitle() top.focus_set() # create scrolled canvas sc = ScrolledCanvas(top, bg="white", highlightthickness=0, takefocus=1) sc.frame.pack(expand=1, fill="both") item = self.rootnode() self.node = node = TreeNode(sc.canvas, None, item) node.update() node.expand()
def settitle(self): self.top.wm_title("Class Browser - " + self.name) self.top.wm_iconname("Class Browser")
def rootnode(self): return ModuleBrowserTreeItem(self.file)
class ModuleBrowserTreeItem(TreeItem):
def __init__(self, file): self.file = file
def GetText(self): return os.path.basename(self.file)
def GetIconName(self): return "python"
def GetSubList(self): sublist = [] for name in self.listclasses(): item = ClassBrowserTreeItem(name, self.classes, self.file) sublist.append(item) return sublist
def OnDoubleClick(self): if os.path.normcase(self.file[-3:]) != ".py": return if not os.path.exists(self.file): return PyShell.flist.open(self.file)
def IsExpandable(self): return os.path.normcase(self.file[-3:]) == ".py"
def listclasses(self): dir, file = os.path.split(self.file) name, ext = os.path.splitext(file) if os.path.normcase(ext) != ".py": return [] try: dict = pyclbr.readmodule_ex(name, [dir] + sys.path) except ImportError, msg: return [] items = [] self.classes = {} for key, cl in dict.items(): if cl.module == name: s = key if hasattr(cl, 'super') and cl.super: supers = [] for sup in cl.super: if type(sup) is type(''): sname = sup else: sname = sup.name if sup.module != cl.module: sname = "%s.%s" % (sup.module, sname) supers.append(sname) s = s + "(%s)" % ", ".join(supers) items.append((cl.lineno, s)) self.classes[s] = cl items.sort() list = [] for item, s in items: list.append(s) return list
class ClassBrowserTreeItem(TreeItem):
def __init__(self, name, classes, file): self.name = name self.classes = classes self.file = file try: self.cl = self.classes[self.name] except (IndexError, KeyError): self.cl = None self.isfunction = isinstance(self.cl, pyclbr.Function)
def GetText(self): if self.isfunction: return "def " + self.name + "(...)" else: return "class " + self.name
def GetIconName(self): if self.isfunction: return "python" else: return "folder"
def IsExpandable(self): if self.cl: try: return not not self.cl.methods except AttributeError: return False
def GetSubList(self): if not self.cl: return [] sublist = [] for name in self.listmethods(): item = MethodBrowserTreeItem(name, self.cl, self.file) sublist.append(item) return sublist
def OnDoubleClick(self): if not os.path.exists(self.file): return edit = PyShell.flist.open(self.file) if hasattr(self.cl, 'lineno'): lineno = self.cl.lineno edit.gotoline(lineno)
def listmethods(self): if not self.cl: return [] items = [] for name, lineno in self.cl.methods.items(): items.append((lineno, name)) items.sort() list = [] for item, name in items: list.append(name) return list
class MethodBrowserTreeItem(TreeItem):
def __init__(self, name, cl, file): self.name = name self.cl = cl self.file = file
def GetText(self): return "def " + self.name + "(...)"
def GetIconName(self): return "python" # XXX
def IsExpandable(self): return 0
def OnDoubleClick(self): if not os.path.exists(self.file): return edit = PyShell.flist.open(self.file) edit.gotoline(self.cl.methods[self.name])
def main(): try: file = __file__ except NameError: file = sys.argv[0] if sys.argv[1:]: file = sys.argv[1] else: file = sys.argv[0] dir, file = os.path.split(file) name = os.path.splitext(file)[0] ClassBrowser(PyShell.flist, name, [dir]) if sys.stdin is sys.__stdin__: mainloop()
if __name__ == "__main__": main()
|