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 # XXX Patch pyclbr with dummies if it's vintage Python 1.5.2:
19 if not hasattr(pyclbr
, "readmodule_ex"):
20 pyclbr
.readmodule_ex
= pyclbr
.readmodule
21 if not hasattr(pyclbr
, "Function"):
22 class Function(pyclbr
.Class
):
24 pyclbr
.Function
= Function
27 from WindowList
import ListedToplevel
28 from TreeWidget
import TreeNode
, TreeItem
, ScrolledCanvas
32 def __init__(self
, flist
, name
, path
):
33 # XXX This API should change, if the file doesn't end in ".py"
34 # XXX the code here is bogus!
36 self
.file = os
.path
.join(path
[0], self
.name
+ ".py")
39 def close(self
, event
=None):
43 def init(self
, flist
):
46 pyclbr
._modules
.clear()
48 self
.top
= top
= ListedToplevel(flist
.root
)
49 top
.protocol("WM_DELETE_WINDOW", self
.close
)
50 top
.bind("<Escape>", self
.close
)
53 # create scrolled canvas
54 sc
= ScrolledCanvas(top
, bg
="white", highlightthickness
=0, takefocus
=1)
55 sc
.frame
.pack(expand
=1, fill
="both")
56 item
= self
.rootnode()
57 self
.node
= node
= TreeNode(sc
.canvas
, None, item
)
62 self
.top
.wm_title("Class Browser - " + self
.name
)
63 self
.top
.wm_iconname("Class Browser")
66 return ModuleBrowserTreeItem(self
.file)
68 class ModuleBrowserTreeItem(TreeItem
):
70 def __init__(self
, file):
74 return os
.path
.basename(self
.file)
76 def GetIconName(self
):
81 for name
in self
.listclasses():
82 item
= ClassBrowserTreeItem(name
, self
.classes
, self
.file)
86 def OnDoubleClick(self
):
87 if os
.path
.normcase(self
.file[-3:]) != ".py":
89 if not os
.path
.exists(self
.file):
91 PyShell
.flist
.open(self
.file)
93 def IsExpandable(self
):
94 return os
.path
.normcase(self
.file[-3:]) == ".py"
96 def listclasses(self
):
97 dir, file = os
.path
.split(self
.file)
98 name
, ext
= os
.path
.splitext(file)
99 if os
.path
.normcase(ext
) != ".py":
102 dict = pyclbr
.readmodule_ex(name
, [dir] + sys
.path
)
103 except ImportError, msg
:
107 for key
, cl
in dict.items():
108 if cl
.module
== name
:
113 if type(sup
) is type(''):
117 if sup
.module
!= cl
.module
:
118 sname
= "%s.%s" % (sup
.module
, sname
)
120 s
= s
+ "(%s)" % string
.join(supers
, ", ")
121 items
.append((cl
.lineno
, s
))
125 for item
, s
in items
:
129 class ClassBrowserTreeItem(TreeItem
):
131 def __init__(self
, name
, classes
, file):
133 self
.classes
= classes
136 self
.cl
= self
.classes
[self
.name
]
137 except (IndexError, KeyError):
139 self
.isfunction
= isinstance(self
.cl
, pyclbr
.Function
)
143 return "def " + self
.name
+ "(...)"
145 return "class " + self
.name
147 def GetIconName(self
):
153 def IsExpandable(self
):
155 return not not self
.cl
.methods
157 def GetSubList(self
):
161 for name
in self
.listmethods():
162 item
= MethodBrowserTreeItem(name
, self
.cl
, self
.file)
166 def OnDoubleClick(self
):
167 if not os
.path
.exists(self
.file):
169 edit
= PyShell
.flist
.open(self
.file)
170 if hasattr(self
.cl
, 'lineno'):
171 lineno
= self
.cl
.lineno
172 edit
.gotoline(lineno
)
174 def listmethods(self
):
178 for name
, lineno
in self
.cl
.methods
.items():
179 items
.append((lineno
, name
))
182 for item
, name
in items
:
186 class MethodBrowserTreeItem(TreeItem
):
188 def __init__(self
, name
, cl
, file):
194 return "def " + self
.name
+ "(...)"
196 def GetIconName(self
):
197 return "python" # XXX
199 def IsExpandable(self
):
202 def OnDoubleClick(self
):
203 if not os
.path
.exists(self
.file):
205 edit
= PyShell
.flist
.open(self
.file)
206 edit
.gotoline(self
.cl
.methods
[self
.name
])
217 dir, file = os
.path
.split(file)
218 name
= os
.path
.splitext(file)[0]
219 ClassBrowser(PyShell
.flist
, name
, [dir])
220 if sys
.stdin
is sys
.__stdin
__:
223 if __name__
== "__main__":