17aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer"""Class browser. 27aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer 37aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David SchererXXX TO DO: 47aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer 57aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer- reparse when source changed (maybe just a button would be OK?) 67aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer (or recheck on window popup) 77aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer- add popup menu with more options (e.g. doc strings, base classes, imports) 87aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer- show function argument list? (have to do pattern matching on source) 97aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer- should the classes and methods lists also be in the module's menu bar? 107aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer- add base classes to class browser tree 117aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer""" 127aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer 137aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Schererimport os 147aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Schererimport sys 157aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Schererimport pyclbr 167aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer 17d630c04ab1ab35e2ec6eeeaba9bdcb9f8e730e78Florent Xiclunafrom idlelib import PyShell 18d630c04ab1ab35e2ec6eeeaba9bdcb9f8e730e78Florent Xiclunafrom idlelib.WindowList import ListedToplevel 19d630c04ab1ab35e2ec6eeeaba9bdcb9f8e730e78Florent Xiclunafrom idlelib.TreeWidget import TreeNode, TreeItem, ScrolledCanvas 20d630c04ab1ab35e2ec6eeeaba9bdcb9f8e730e78Florent Xiclunafrom idlelib.configHandler import idleConf 217aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer 22cf834769e4f2c3b14c93091334f2334284c9d8c0Terry Jan Reedyfile_open = None # Method...Item and Class...Item use this. 23cf834769e4f2c3b14c93091334f2334284c9d8c0Terry Jan Reedy# Normally PyShell.flist.open, but there is no PyShell.flist for htest. 24cf834769e4f2c3b14c93091334f2334284c9d8c0Terry Jan Reedy 257aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Schererclass ClassBrowser: 267aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer 2762012fc719818b6087b01c93fcc1cd0d2b4d8932Terry Jan Reedy def __init__(self, flist, name, path, _htest=False): 287aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer # XXX This API should change, if the file doesn't end in ".py" 297aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer # XXX the code here is bogus! 3062012fc719818b6087b01c93fcc1cd0d2b4d8932Terry Jan Reedy """ 3162012fc719818b6087b01c93fcc1cd0d2b4d8932Terry Jan Reedy _htest - bool, change box when location running htest. 3262012fc719818b6087b01c93fcc1cd0d2b4d8932Terry Jan Reedy """ 33cf834769e4f2c3b14c93091334f2334284c9d8c0Terry Jan Reedy global file_open 34cf834769e4f2c3b14c93091334f2334284c9d8c0Terry Jan Reedy if not _htest: 35cf834769e4f2c3b14c93091334f2334284c9d8c0Terry Jan Reedy file_open = PyShell.flist.open 367aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer self.name = name 377aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer self.file = os.path.join(path[0], self.name + ".py") 3862012fc719818b6087b01c93fcc1cd0d2b4d8932Terry Jan Reedy self._htest = _htest 397aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer self.init(flist) 407aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer 417aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer def close(self, event=None): 427aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer self.top.destroy() 437aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer self.node.destroy() 447aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer 457aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer def init(self, flist): 467aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer self.flist = flist 477aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer # reset pyclbr 487aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer pyclbr._modules.clear() 497aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer # create top 507aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer self.top = top = ListedToplevel(flist.root) 517aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer top.protocol("WM_DELETE_WINDOW", self.close) 527aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer top.bind("<Escape>", self.close) 5362012fc719818b6087b01c93fcc1cd0d2b4d8932Terry Jan Reedy if self._htest: # place dialog below parent if running htest 5462012fc719818b6087b01c93fcc1cd0d2b4d8932Terry Jan Reedy top.geometry("+%d+%d" % 5562012fc719818b6087b01c93fcc1cd0d2b4d8932Terry Jan Reedy (flist.root.winfo_rootx(), flist.root.winfo_rooty() + 200)) 567aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer self.settitle() 577aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer top.focus_set() 587aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer # create scrolled canvas 5935aa5d07a2865f34d178e7c35c1f1eeb73289eacTerry Jan Reedy theme = idleConf.CurrentTheme() 6073360a3e61274ffcc4c9fc3d09746bd6603e92a5Kurt B. Kaiser background = idleConf.GetHighlight(theme, 'normal')['background'] 6173360a3e61274ffcc4c9fc3d09746bd6603e92a5Kurt B. Kaiser sc = ScrolledCanvas(top, bg=background, highlightthickness=0, takefocus=1) 627aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer sc.frame.pack(expand=1, fill="both") 637aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer item = self.rootnode() 647aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer self.node = node = TreeNode(sc.canvas, None, item) 657aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer node.update() 667aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer node.expand() 677aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer 687aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer def settitle(self): 697aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer self.top.wm_title("Class Browser - " + self.name) 707aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer self.top.wm_iconname("Class Browser") 717aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer 727aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer def rootnode(self): 737aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer return ModuleBrowserTreeItem(self.file) 747aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer 757aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Schererclass ModuleBrowserTreeItem(TreeItem): 767aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer 777aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer def __init__(self, file): 787aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer self.file = file 797aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer 807aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer def GetText(self): 817aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer return os.path.basename(self.file) 827aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer 837aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer def GetIconName(self): 847aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer return "python" 857aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer 867aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer def GetSubList(self): 877aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer sublist = [] 887aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer for name in self.listclasses(): 897aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer item = ClassBrowserTreeItem(name, self.classes, self.file) 907aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer sublist.append(item) 917aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer return sublist 927aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer 937aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer def OnDoubleClick(self): 947aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer if os.path.normcase(self.file[-3:]) != ".py": 957aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer return 967aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer if not os.path.exists(self.file): 977aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer return 987aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer PyShell.flist.open(self.file) 997aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer 1007aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer def IsExpandable(self): 1017aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer return os.path.normcase(self.file[-3:]) == ".py" 102d6c4c9e846660cb501491ec0b98f5086ef3fcc7fKurt B. Kaiser 1037aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer def listclasses(self): 1047aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer dir, file = os.path.split(self.file) 1057aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer name, ext = os.path.splitext(file) 1067aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer if os.path.normcase(ext) != ".py": 1077aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer return [] 1087aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer try: 1097aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer dict = pyclbr.readmodule_ex(name, [dir] + sys.path) 1109bc505616b4bc88b29993f351218c3083bd3f3e8Terry Jan Reedy except ImportError: 1117aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer return [] 1127aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer items = [] 1137aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer self.classes = {} 1147aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer for key, cl in dict.items(): 1157aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer if cl.module == name: 1167aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer s = key 1176550051691d604c728ed56e4acf90dc6535981f9Raymond Hettinger if hasattr(cl, 'super') and cl.super: 1187aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer supers = [] 1197aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer for sup in cl.super: 1207aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer if type(sup) is type(''): 1217aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer sname = sup 1227aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer else: 1237aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer sname = sup.name 1247aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer if sup.module != cl.module: 1257aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer sname = "%s.%s" % (sup.module, sname) 1267aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer supers.append(sname) 127a2876442047ac41abce63b5d0e987e9d807c694fKurt B. Kaiser s = s + "(%s)" % ", ".join(supers) 1287aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer items.append((cl.lineno, s)) 1297aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer self.classes[s] = cl 1307aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer items.sort() 1317aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer list = [] 1327aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer for item, s in items: 1337aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer list.append(s) 1347aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer return list 1357aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer 1367aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Schererclass ClassBrowserTreeItem(TreeItem): 1377aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer 1387aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer def __init__(self, name, classes, file): 1397aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer self.name = name 1407aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer self.classes = classes 1417aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer self.file = file 1427aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer try: 1437aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer self.cl = self.classes[self.name] 1447aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer except (IndexError, KeyError): 1457aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer self.cl = None 1467aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer self.isfunction = isinstance(self.cl, pyclbr.Function) 1477aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer 1487aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer def GetText(self): 1497aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer if self.isfunction: 1507aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer return "def " + self.name + "(...)" 1517aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer else: 1527aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer return "class " + self.name 1537aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer 1547aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer def GetIconName(self): 1557aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer if self.isfunction: 1567aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer return "python" 1577aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer else: 1587aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer return "folder" 1597aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer 1607aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer def IsExpandable(self): 1617aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer if self.cl: 1620b743441a60640824360bdff15780fc5d40489d6Kurt B. Kaiser try: 1630b743441a60640824360bdff15780fc5d40489d6Kurt B. Kaiser return not not self.cl.methods 1640b743441a60640824360bdff15780fc5d40489d6Kurt B. Kaiser except AttributeError: 1650b743441a60640824360bdff15780fc5d40489d6Kurt B. Kaiser return False 1667aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer 1677aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer def GetSubList(self): 1687aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer if not self.cl: 1697aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer return [] 1707aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer sublist = [] 1717aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer for name in self.listmethods(): 1727aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer item = MethodBrowserTreeItem(name, self.cl, self.file) 1737aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer sublist.append(item) 1747aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer return sublist 1757aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer 1767aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer def OnDoubleClick(self): 1777aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer if not os.path.exists(self.file): 1787aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer return 179cf834769e4f2c3b14c93091334f2334284c9d8c0Terry Jan Reedy edit = file_open(self.file) 1807aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer if hasattr(self.cl, 'lineno'): 1817aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer lineno = self.cl.lineno 1827aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer edit.gotoline(lineno) 1837aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer 1847aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer def listmethods(self): 1857aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer if not self.cl: 1867aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer return [] 1877aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer items = [] 1887aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer for name, lineno in self.cl.methods.items(): 1897aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer items.append((lineno, name)) 1907aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer items.sort() 1917aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer list = [] 1927aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer for item, name in items: 1937aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer list.append(name) 1947aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer return list 1957aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer 1967aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Schererclass MethodBrowserTreeItem(TreeItem): 1977aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer 1987aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer def __init__(self, name, cl, file): 1997aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer self.name = name 2007aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer self.cl = cl 2017aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer self.file = file 2027aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer 2037aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer def GetText(self): 2047aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer return "def " + self.name + "(...)" 2057aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer 2067aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer def GetIconName(self): 2077aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer return "python" # XXX 2087aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer 2097aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer def IsExpandable(self): 2107aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer return 0 2117aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer 2127aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer def OnDoubleClick(self): 2137aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer if not os.path.exists(self.file): 2147aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer return 215cf834769e4f2c3b14c93091334f2334284c9d8c0Terry Jan Reedy edit = file_open(self.file) 2167aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer edit.gotoline(self.cl.methods[self.name]) 2177aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer 21862012fc719818b6087b01c93fcc1cd0d2b4d8932Terry Jan Reedydef _class_browser(parent): #Wrapper for htest 2197aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer try: 2207aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer file = __file__ 2217aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer except NameError: 2227aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer file = sys.argv[0] 2237aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer if sys.argv[1:]: 2247aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer file = sys.argv[1] 2257aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer else: 2267aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer file = sys.argv[0] 2277aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer dir, file = os.path.split(file) 2287aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer name = os.path.splitext(file)[0] 22962012fc719818b6087b01c93fcc1cd0d2b4d8932Terry Jan Reedy flist = PyShell.PyShellFileList(parent) 230cf834769e4f2c3b14c93091334f2334284c9d8c0Terry Jan Reedy global file_open 231cf834769e4f2c3b14c93091334f2334284c9d8c0Terry Jan Reedy file_open = flist.open 23262012fc719818b6087b01c93fcc1cd0d2b4d8932Terry Jan Reedy ClassBrowser(flist, name, [dir], _htest=True) 2337aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer 2347aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Schererif __name__ == "__main__": 23562012fc719818b6087b01c93fcc1cd0d2b4d8932Terry Jan Reedy from idlelib.idle_test.htest import run 23662012fc719818b6087b01c93fcc1cd0d2b4d8932Terry Jan Reedy run(_class_browser) 237