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
18 from WindowList
import ListedToplevel
19 from TreeWidget
import TreeNode
, TreeItem
, ScrolledCanvas
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!
27 self
.file = os
.path
.join(path
[0], self
.name
+ ".py")
30 def close(self
, event
=None):
34 def init(self
, flist
):
37 pyclbr
._modules
.clear()
39 self
.top
= top
= ListedToplevel(flist
.root
)
40 top
.protocol("WM_DELETE_WINDOW", self
.close
)
41 top
.bind("<Escape>", self
.close
)
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
)
53 self
.top
.wm_title("Class Browser - " + self
.name
)
54 self
.top
.wm_iconname("Class Browser")
57 return ModuleBrowserTreeItem(self
.file)
59 class ModuleBrowserTreeItem(TreeItem
):
61 def __init__(self
, file):
65 return os
.path
.basename(self
.file)
67 def GetIconName(self
):
72 for name
in self
.listclasses():
73 item
= ClassBrowserTreeItem(name
, self
.classes
, self
.file)
77 def OnDoubleClick(self
):
78 if os
.path
.normcase(self
.file[-3:]) != ".py":
80 if not os
.path
.exists(self
.file):
82 PyShell
.flist
.open(self
.file)
84 def IsExpandable(self
):
85 return os
.path
.normcase(self
.file[-3:]) == ".py"
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":
93 dict = pyclbr
.readmodule_ex(name
, [dir] + sys
.path
)
94 except ImportError, msg
:
98 for key
, cl
in dict.items():
104 if type(sup
) is type(''):
108 if sup
.module
!= cl
.module
:
109 sname
= "%s.%s" % (sup
.module
, sname
)
111 s
= s
+ "(%s)" % ", ".join(supers
)
112 items
.append((cl
.lineno
, s
))
116 for item
, s
in items
:
120 class ClassBrowserTreeItem(TreeItem
):
122 def __init__(self
, name
, classes
, file):
124 self
.classes
= classes
127 self
.cl
= self
.classes
[self
.name
]
128 except (IndexError, KeyError):
130 self
.isfunction
= isinstance(self
.cl
, pyclbr
.Function
)
134 return "def " + self
.name
+ "(...)"
136 return "class " + self
.name
138 def GetIconName(self
):
144 def IsExpandable(self
):
146 return not not self
.cl
.methods
148 def GetSubList(self
):
152 for name
in self
.listmethods():
153 item
= MethodBrowserTreeItem(name
, self
.cl
, self
.file)
157 def OnDoubleClick(self
):
158 if not os
.path
.exists(self
.file):
160 edit
= PyShell
.flist
.open(self
.file)
161 if hasattr(self
.cl
, 'lineno'):
162 lineno
= self
.cl
.lineno
163 edit
.gotoline(lineno
)
165 def listmethods(self
):
169 for name
, lineno
in self
.cl
.methods
.items():
170 items
.append((lineno
, name
))
173 for item
, name
in items
:
177 class MethodBrowserTreeItem(TreeItem
):
179 def __init__(self
, name
, cl
, file):
185 return "def " + self
.name
+ "(...)"
187 def GetIconName(self
):
188 return "python" # XXX
190 def IsExpandable(self
):
193 def OnDoubleClick(self
):
194 if not os
.path
.exists(self
.file):
196 edit
= PyShell
.flist
.open(self
.file)
197 edit
.gotoline(self
.cl
.methods
[self
.name
])
208 dir, file = os
.path
.split(file)
209 name
= os
.path
.splitext(file)[0]
210 ClassBrowser(PyShell
.flist
, name
, [dir])
211 if sys
.stdin
is sys
.__stdin
__:
214 if __name__
== "__main__":