ยปCore Development>Code coverage>Lib/idlelib/ClassBrowser.py

Python code coverage for Lib/idlelib/ClassBrowser.py

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