bpo-30881: IDLE: add docstrings to browser.py (#2638)

Patch by Cheryl Sabella.
This commit is contained in:
csabella 2017-07-11 02:34:01 -04:00 committed by terryjreedy
parent 5b62b35e6f
commit ba352270b7
2 changed files with 94 additions and 4 deletions

View file

@ -23,12 +23,28 @@ file_open = None # Method...Item and Class...Item use this.
# Normally pyshell.flist.open, but there is no pyshell.flist for htest. # Normally pyshell.flist.open, but there is no pyshell.flist for htest.
class ClassBrowser: class ClassBrowser:
"""Browse module classes and functions in IDLE.
"""
def __init__(self, flist, name, path, _htest=False): def __init__(self, flist, name, path, _htest=False):
# XXX This API should change, if the file doesn't end in ".py" # XXX This API should change, if the file doesn't end in ".py"
# XXX the code here is bogus! # XXX the code here is bogus!
""" """Create a window for browsing a module's structure.
_htest - bool, change box when location running htest.
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 global file_open
if not _htest: if not _htest:
@ -39,10 +55,12 @@ class ClassBrowser:
self.init(flist) self.init(flist)
def close(self, event=None): def close(self, event=None):
"Dismiss the window and the tree nodes."
self.top.destroy() self.top.destroy()
self.node.destroy() self.node.destroy()
def init(self, flist): def init(self, flist):
"Create browser tkinter widgets, including the tree."
self.flist = flist self.flist = flist
# reset pyclbr # reset pyclbr
pyclbr._modules.clear() pyclbr._modules.clear()
@ -66,24 +84,42 @@ class ClassBrowser:
node.expand() node.expand()
def settitle(self): def settitle(self):
"Set the window title."
self.top.wm_title("Class Browser - " + self.name) self.top.wm_title("Class Browser - " + self.name)
self.top.wm_iconname("Class Browser") self.top.wm_iconname("Class Browser")
def rootnode(self): def rootnode(self):
"Return a ModuleBrowserTreeItem as the root of the tree."
return ModuleBrowserTreeItem(self.file) return ModuleBrowserTreeItem(self.file)
class ModuleBrowserTreeItem(TreeItem): class ModuleBrowserTreeItem(TreeItem):
"""Browser tree for Python module.
Uses TreeItem as the basis for the structure of the tree.
"""
def __init__(self, file): def __init__(self, file):
"""Create a TreeItem for the file.
Args:
file: Full path and module name.
"""
self.file = file self.file = file
def GetText(self): def GetText(self):
"Return the module name as the text string to display."
return os.path.basename(self.file) return os.path.basename(self.file)
def GetIconName(self): def GetIconName(self):
"Return the name of the icon to display."
return "python" return "python"
def GetSubList(self): 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 = [] sublist = []
for name in self.listclasses(): for name in self.listclasses():
item = ClassBrowserTreeItem(name, self.classes, self.file) item = ClassBrowserTreeItem(name, self.classes, self.file)
@ -91,6 +127,7 @@ class ModuleBrowserTreeItem(TreeItem):
return sublist return sublist
def OnDoubleClick(self): def OnDoubleClick(self):
"Open a module in an editor window when double clicked."
if os.path.normcase(self.file[-3:]) != ".py": if os.path.normcase(self.file[-3:]) != ".py":
return return
if not os.path.exists(self.file): if not os.path.exists(self.file):
@ -98,9 +135,20 @@ class ModuleBrowserTreeItem(TreeItem):
pyshell.flist.open(self.file) pyshell.flist.open(self.file)
def IsExpandable(self): def IsExpandable(self):
"Return True if Python (.py) file."
return os.path.normcase(self.file[-3:]) == ".py" return os.path.normcase(self.file[-3:]) == ".py"
def listclasses(self): 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) dir, file = os.path.split(self.file)
name, ext = os.path.splitext(file) name, ext = os.path.splitext(file)
if os.path.normcase(ext) != ".py": if os.path.normcase(ext) != ".py":
@ -134,9 +182,25 @@ class ModuleBrowserTreeItem(TreeItem):
return list return list
class ClassBrowserTreeItem(TreeItem): 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): 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 self.name = name
# XXX - Does classes need to be an instance variable?
self.classes = classes self.classes = classes
self.file = file self.file = file
try: try:
@ -146,25 +210,33 @@ class ClassBrowserTreeItem(TreeItem):
self.isfunction = isinstance(self.cl, pyclbr.Function) self.isfunction = isinstance(self.cl, pyclbr.Function)
def GetText(self): def GetText(self):
"Return the name of the function/class to display."
if self.isfunction: if self.isfunction:
return "def " + self.name + "(...)" return "def " + self.name + "(...)"
else: else:
return "class " + self.name return "class " + self.name
def GetIconName(self): def GetIconName(self):
"Return the name of the icon to display."
if self.isfunction: if self.isfunction:
return "python" return "python"
else: else:
return "folder" return "folder"
def IsExpandable(self): def IsExpandable(self):
"Return True if this class has methods."
if self.cl: if self.cl:
try: try:
return not not self.cl.methods return not not self.cl.methods
except AttributeError: except AttributeError:
return False return False
return None
def GetSubList(self): def GetSubList(self):
"""Return Class methods as a list of MethodBrowserTreeItem items.
Each item is a method within the class.
"""
if not self.cl: if not self.cl:
return [] return []
sublist = [] sublist = []
@ -174,6 +246,7 @@ class ClassBrowserTreeItem(TreeItem):
return sublist return sublist
def OnDoubleClick(self): def OnDoubleClick(self):
"Open module with file_open and position to lineno, if it exists."
if not os.path.exists(self.file): if not os.path.exists(self.file):
return return
edit = file_open(self.file) edit = file_open(self.file)
@ -182,6 +255,7 @@ class ClassBrowserTreeItem(TreeItem):
edit.gotoline(lineno) edit.gotoline(lineno)
def listmethods(self): def listmethods(self):
"Return list of methods within a class sorted by lineno."
if not self.cl: if not self.cl:
return [] return []
items = [] items = []
@ -194,22 +268,37 @@ class ClassBrowserTreeItem(TreeItem):
return list return list
class MethodBrowserTreeItem(TreeItem): 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): 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.name = name
self.cl = cl self.cl = cl
self.file = file self.file = file
def GetText(self): def GetText(self):
"Return the method name to display."
return "def " + self.name + "(...)" return "def " + self.name + "(...)"
def GetIconName(self): def GetIconName(self):
return "python" # XXX "Return the name of the icon to display."
return "python"
def IsExpandable(self): def IsExpandable(self):
return 0 "Return False as there are no tree items after methods."
return False
def OnDoubleClick(self): def OnDoubleClick(self):
"Open module with file_open and position at the method start."
if not os.path.exists(self.file): if not os.path.exists(self.file):
return return
edit = file_open(self.file) edit = file_open(self.file)

View file

@ -0,0 +1 @@
IDLE: Add docstrings to browser.py. Patch by Cheryl Sabella.