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