Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
97 changes: 93 additions & 4 deletions Lib/idlelib/browser.py
Original file line number Diff line number Diff line change
Expand Up @@ -23,12 +23,28 @@
# Normally pyshell.flist.open, but there is no pyshell.flist for htest.

class ClassBrowser:
"""Browse module classes and functions in IDLE.
"""

def __init__(self, flist, name, path, _htest=False):
# XXX This API should change, if the file doesn't end in ".py"
# XXX the code here is bogus!
"""
_htest - bool, change box when location running htest.
"""Create a window for browsing a module's structure.

Args:
flist: filelist.FileList instance used as the root for the window.
name: Python module to parse.
path: Module search path.
_htest - bool, change box when location running htest.

Global variables:
file_open: Function used for opening a file.

Instance variables:
name: Module name.
file: Full path and module with .py extension. Used in
creating ModuleBrowserTreeItem as the rootnode for
the tree and subsequently in the children.
"""
global file_open
if not _htest:
Expand All @@ -39,10 +55,12 @@ def __init__(self, flist, name, path, _htest=False):
self.init(flist)

def close(self, event=None):
"Dismiss the window and the tree nodes."
self.top.destroy()
self.node.destroy()

def init(self, flist):
"Create browser tkinter widgets, including the tree."
self.flist = flist
# reset pyclbr
pyclbr._modules.clear()
Expand All @@ -66,41 +84,71 @@ def init(self, flist):
node.expand()

def settitle(self):
"Set the window title."
self.top.wm_title("Class Browser - " + self.name)
self.top.wm_iconname("Class Browser")

def rootnode(self):
"Return a ModuleBrowserTreeItem as the root of the tree."
return ModuleBrowserTreeItem(self.file)

class ModuleBrowserTreeItem(TreeItem):
"""Browser tree for Python module.

Uses TreeItem as the basis for the structure of the tree.
"""

def __init__(self, file):
"""Create a TreeItem for the file.

Args:
file: Full path and module name.
"""
self.file = file

def GetText(self):
"Return the module name as the text string to display."
return os.path.basename(self.file)

def GetIconName(self):
"Return the name of the icon to display."
return "python"

def GetSubList(self):
"""Return the list of ClassBrowserTreeItem items.

Each item returned from listclasses is the first level of
classes/functions within the module.
"""
sublist = []
for name in self.listclasses():
item = ClassBrowserTreeItem(name, self.classes, self.file)
sublist.append(item)
return sublist

def OnDoubleClick(self):
"Open a module in an editor window when double clicked."
if os.path.normcase(self.file[-3:]) != ".py":
return
if not os.path.exists(self.file):
return
pyshell.flist.open(self.file)

def IsExpandable(self):
"Return True if Python (.py) file."
return os.path.normcase(self.file[-3:]) == ".py"

def listclasses(self):
"""Return list of classes and functions in the module.

The dictionary output from pyclbr is re-written as a
list of tuples in the form (lineno, name) and
then sorted so that the classes and functions are
processed in line number order. The returned list only
contains the name and not the line number. An instance
variable self.classes contains the pyclbr dictionary values,
which are instances of Class and Function.
"""
dir, file = os.path.split(self.file)
name, ext = os.path.splitext(file)
if os.path.normcase(ext) != ".py":
Expand Down Expand Up @@ -134,9 +182,25 @@ def listclasses(self):
return list

class ClassBrowserTreeItem(TreeItem):
"""Browser tree for classes within a module.

Uses TreeItem as the basis for the structure of the tree.
"""

def __init__(self, name, classes, file):
"""Create a TreeItem for the class/function.

Args:
name: Name of the class/function.
classes: Dictonary of Class/Function instances from pyclbr.
file: Full path and module name.

Instance variables:
self.cl: Class/Function instance for the class/function name.
self.isfunction: True if self.cl is a Function.
"""
self.name = name
# XXX - Does classes need to be an instance variable?
self.classes = classes
self.file = file
try:
Expand All @@ -146,25 +210,33 @@ def __init__(self, name, classes, file):
self.isfunction = isinstance(self.cl, pyclbr.Function)

def GetText(self):
"Return the name of the function/class to display."
if self.isfunction:
return "def " + self.name + "(...)"
else:
return "class " + self.name

def GetIconName(self):
"Return the name of the icon to display."
if self.isfunction:
return "python"
else:
return "folder"

def IsExpandable(self):
"Return True if this class has methods."
if self.cl:
try:
return not not self.cl.methods
except AttributeError:
return False
return None

def GetSubList(self):
"""Return Class methods as a list of MethodBrowserTreeItem items.

Each item is a method within the class.
"""
if not self.cl:
return []
sublist = []
Expand All @@ -174,6 +246,7 @@ def GetSubList(self):
return sublist

def OnDoubleClick(self):
"Open module with file_open and position to lineno, if it exists."
if not os.path.exists(self.file):
return
edit = file_open(self.file)
Expand All @@ -182,6 +255,7 @@ def OnDoubleClick(self):
edit.gotoline(lineno)

def listmethods(self):
"Return list of methods within a class sorted by lineno."
if not self.cl:
return []
items = []
Expand All @@ -194,22 +268,37 @@ def listmethods(self):
return list

class MethodBrowserTreeItem(TreeItem):
"""Browser tree for methods within a class.

Uses TreeItem as the basis for the structure of the tree.
"""

def __init__(self, name, cl, file):
"""Create a TreeItem for the methods.

Args:
name: Name of the class/function.
cl: pyclbr.Class instance for name.
file: Full path and module name.
"""
self.name = name
self.cl = cl
self.file = file

def GetText(self):
"Return the method name to display."
return "def " + self.name + "(...)"

def GetIconName(self):
return "python" # XXX
"Return the name of the icon to display."
return "python"

def IsExpandable(self):
return 0
"Return False as there are no tree items after methods."
return False

def OnDoubleClick(self):
"Open module with file_open and position at the method start."
if not os.path.exists(self.file):
return
edit = file_open(self.file)
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
IDLE: Add docstrings to browser.py. Patch by Cheryl Sabella.