home *** CD-ROM | disk | FTP | other *** search
/ PC World 2005 June / PCWorld_2005-06_cd.bin / software / vyzkuste / firewally / firewally.exe / framework-2.3.exe / ClassBrowser.py < prev    next >
Text File  |  2003-12-30  |  6KB  |  219 lines

  1. """Class browser.
  2.  
  3. XXX TO DO:
  4.  
  5. - reparse when source changed (maybe just a button would be OK?)
  6.     (or recheck on window popup)
  7. - add popup menu with more options (e.g. doc strings, base classes, imports)
  8. - show function argument list? (have to do pattern matching on source)
  9. - should the classes and methods lists also be in the module's menu bar?
  10. - add base classes to class browser tree
  11. """
  12.  
  13. import os
  14. import sys
  15. import pyclbr
  16.  
  17. import PyShell
  18. from WindowList import ListedToplevel
  19. from TreeWidget import TreeNode, TreeItem, ScrolledCanvas
  20.  
  21. class ClassBrowser:
  22.  
  23.     def __init__(self, flist, name, path):
  24.         # XXX This API should change, if the file doesn't end in ".py"
  25.         # XXX the code here is bogus!
  26.         self.name = name
  27.         self.file = os.path.join(path[0], self.name + ".py")
  28.         self.init(flist)
  29.  
  30.     def close(self, event=None):
  31.         self.top.destroy()
  32.         self.node.destroy()
  33.  
  34.     def init(self, flist):
  35.         self.flist = flist
  36.         # reset pyclbr
  37.         pyclbr._modules.clear()
  38.         # create top
  39.         self.top = top = ListedToplevel(flist.root)
  40.         top.protocol("WM_DELETE_WINDOW", self.close)
  41.         top.bind("<Escape>", self.close)
  42.         self.settitle()
  43.         top.focus_set()
  44.         # create scrolled canvas
  45.         sc = ScrolledCanvas(top, bg="white", highlightthickness=0, takefocus=1)
  46.         sc.frame.pack(expand=1, fill="both")
  47.         item = self.rootnode()
  48.         self.node = node = TreeNode(sc.canvas, None, item)
  49.         node.update()
  50.         node.expand()
  51.  
  52.     def settitle(self):
  53.         self.top.wm_title("Class Browser - " + self.name)
  54.         self.top.wm_iconname("Class Browser")
  55.  
  56.     def rootnode(self):
  57.         return ModuleBrowserTreeItem(self.file)
  58.  
  59. class ModuleBrowserTreeItem(TreeItem):
  60.  
  61.     def __init__(self, file):
  62.         self.file = file
  63.  
  64.     def GetText(self):
  65.         return os.path.basename(self.file)
  66.  
  67.     def GetIconName(self):
  68.         return "python"
  69.  
  70.     def GetSubList(self):
  71.         sublist = []
  72.         for name in self.listclasses():
  73.             item = ClassBrowserTreeItem(name, self.classes, self.file)
  74.             sublist.append(item)
  75.         return sublist
  76.  
  77.     def OnDoubleClick(self):
  78.         if os.path.normcase(self.file[-3:]) != ".py":
  79.             return
  80.         if not os.path.exists(self.file):
  81.             return
  82.         PyShell.flist.open(self.file)
  83.  
  84.     def IsExpandable(self):
  85.         return os.path.normcase(self.file[-3:]) == ".py"
  86.  
  87.     def listclasses(self):
  88.         dir, file = os.path.split(self.file)
  89.         name, ext = os.path.splitext(file)
  90.         if os.path.normcase(ext) != ".py":
  91.             return []
  92.         try:
  93.             dict = pyclbr.readmodule_ex(name, [dir] + sys.path)
  94.         except ImportError, msg:
  95.             return []
  96.         items = []
  97.         self.classes = {}
  98.         for key, cl in dict.items():
  99.             if cl.module == name:
  100.                 s = key
  101.                 if hasattr(cl, 'super') and cl.super:
  102.                     supers = []
  103.                     for sup in cl.super:
  104.                         if type(sup) is type(''):
  105.                             sname = sup
  106.                         else:
  107.                             sname = sup.name
  108.                             if sup.module != cl.module:
  109.                                 sname = "%s.%s" % (sup.module, sname)
  110.                         supers.append(sname)
  111.                     s = s + "(%s)" % ", ".join(supers)
  112.                 items.append((cl.lineno, s))
  113.                 self.classes[s] = cl
  114.         items.sort()
  115.         list = []
  116.         for item, s in items:
  117.             list.append(s)
  118.         return list
  119.  
  120. class ClassBrowserTreeItem(TreeItem):
  121.  
  122.     def __init__(self, name, classes, file):
  123.         self.name = name
  124.         self.classes = classes
  125.         self.file = file
  126.         try:
  127.             self.cl = self.classes[self.name]
  128.         except (IndexError, KeyError):
  129.             self.cl = None
  130.         self.isfunction = isinstance(self.cl, pyclbr.Function)
  131.  
  132.     def GetText(self):
  133.         if self.isfunction:
  134.             return "def " + self.name + "(...)"
  135.         else:
  136.             return "class " + self.name
  137.  
  138.     def GetIconName(self):
  139.         if self.isfunction:
  140.             return "python"
  141.         else:
  142.             return "folder"
  143.  
  144.     def IsExpandable(self):
  145.         if self.cl:
  146.             try:
  147.                 return not not self.cl.methods
  148.             except AttributeError:
  149.                 return False
  150.  
  151.     def GetSubList(self):
  152.         if not self.cl:
  153.             return []
  154.         sublist = []
  155.         for name in self.listmethods():
  156.             item = MethodBrowserTreeItem(name, self.cl, self.file)
  157.             sublist.append(item)
  158.         return sublist
  159.  
  160.     def OnDoubleClick(self):
  161.         if not os.path.exists(self.file):
  162.             return
  163.         edit = PyShell.flist.open(self.file)
  164.         if hasattr(self.cl, 'lineno'):
  165.             lineno = self.cl.lineno
  166.             edit.gotoline(lineno)
  167.  
  168.     def listmethods(self):
  169.         if not self.cl:
  170.             return []
  171.         items = []
  172.         for name, lineno in self.cl.methods.items():
  173.             items.append((lineno, name))
  174.         items.sort()
  175.         list = []
  176.         for item, name in items:
  177.             list.append(name)
  178.         return list
  179.  
  180. class MethodBrowserTreeItem(TreeItem):
  181.  
  182.     def __init__(self, name, cl, file):
  183.         self.name = name
  184.         self.cl = cl
  185.         self.file = file
  186.  
  187.     def GetText(self):
  188.         return "def " + self.name + "(...)"
  189.  
  190.     def GetIconName(self):
  191.         return "python" # XXX
  192.  
  193.     def IsExpandable(self):
  194.         return 0
  195.  
  196.     def OnDoubleClick(self):
  197.         if not os.path.exists(self.file):
  198.             return
  199.         edit = PyShell.flist.open(self.file)
  200.         edit.gotoline(self.cl.methods[self.name])
  201.  
  202. def main():
  203.     try:
  204.         file = __file__
  205.     except NameError:
  206.         file = sys.argv[0]
  207.         if sys.argv[1:]:
  208.             file = sys.argv[1]
  209.         else:
  210.             file = sys.argv[0]
  211.     dir, file = os.path.split(file)
  212.     name = os.path.splitext(file)[0]
  213.     ClassBrowser(PyShell.flist, name, [dir])
  214.     if sys.stdin is sys.__stdin__:
  215.         mainloop()
  216.  
  217. if __name__ == "__main__":
  218.     main()
  219.