Python-checkins
Threads by month
- ----- 2025 -----
- January
- ----- 2024 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2023 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2022 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2021 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2020 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2019 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2018 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2017 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2016 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2015 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2014 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2013 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2012 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2011 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2010 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2009 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2008 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2007 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2006 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2005 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2004 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2003 -----
- December
- November
- October
- September
- August
October 2017
- 3 participants
- 331 discussions
[3.6] bpo-31460: Simplify the API of IDLE's Module Browser. (GH-3842) (#3843)
by Terry Jan Reedy Oct. 1, 2017
by Terry Jan Reedy Oct. 1, 2017
Oct. 1, 2017
https://github.com/python/cpython/commit/c8198c92320bc35b1e3de5ff0118bd8e20…
commit: c8198c92320bc35b1e3de5ff0118bd8e20e8d68a
branch: 3.6
author: Terry Jan Reedy <tjreedy(a)udel.edu>
committer: GitHub <noreply(a)github.com>
date: 2017-09-30T20:32:29-04:00
summary:
[3.6] bpo-31460: Simplify the API of IDLE's Module Browser. (GH-3842) (#3843)
Passing a widget instead of an flist with a root widget opens the option of
creating a browser frame that is only part of a window. Passing a full file
name instead of pieces assumed to come from a .py file opens the possibility
of browsing python files that do not end in .py.
(cherry picked from commit d6bb65f)
files:
A Misc/NEWS.d/next/IDLE/2017-09-30-19-03-26.bpo-31460.HpveI6.rst
M Lib/idlelib/browser.py
M Lib/idlelib/editor.py
M Lib/idlelib/idle_test/test_browser.py
diff --git a/Lib/idlelib/browser.py b/Lib/idlelib/browser.py
index 010d8c34982..090eb2876ea 100644
--- a/Lib/idlelib/browser.py
+++ b/Lib/idlelib/browser.py
@@ -5,9 +5,8 @@
- reparse when source changed (maybe just a button would be OK?)
(or recheck on window popup)
- add popup menu with more options (e.g. doc strings, base classes, imports)
-- show function argument list? (have to do pattern matching on source)
-- should the classes and methods lists also be in the module's menu bar?
- add base classes to class browser tree
+- finish removing limitation to x.py files (ModuleBrowserTreeItem)
"""
import os
@@ -58,19 +57,18 @@ def transform_children(child_dict, modname=None):
class ModuleBrowser:
"""Browse module classes and functions in IDLE.
"""
- # This class is the base class for pathbrowser.PathBrowser.
+ # This class is also the base class for pathbrowser.PathBrowser.
# Init and close are inherited, other methods are overriden.
+ # PathBrowser.__init__ does not call __init__ below.
- def __init__(self, flist, name, path, *, _htest=False, _utest=False):
- # XXX This API should change, if the file doesn't end in ".py"
- # XXX the code here is bogus!
+ def __init__(self, master, path, *, _htest=False, _utest=False):
"""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.
+ master: parent for widgets.
+ path: full path of file to browse.
+ _htest - bool; change box location when running htest.
+ -utest - bool; suppress contents when running unittest.
Global variables:
file_open: Function used for opening a file.
@@ -84,35 +82,36 @@ def __init__(self, flist, name, path, *, _htest=False, _utest=False):
global file_open
if not (_htest or _utest):
file_open = pyshell.flist.open
- self.name = name
- self.file = os.path.join(path[0], self.name + ".py")
+ self.master = master
+ self.path = path
self._htest = _htest
self._utest = _utest
- self.init(flist)
+ self.init()
def close(self, event=None):
"Dismiss the window and the tree nodes."
self.top.destroy()
self.node.destroy()
- def init(self, flist):
+ def init(self):
"Create browser tkinter widgets, including the tree."
- self.flist = flist
+ root = self.master
# reset pyclbr
pyclbr._modules.clear()
# create top
- self.top = top = ListedToplevel(flist.root)
+ self.top = top = ListedToplevel(root)
top.protocol("WM_DELETE_WINDOW", self.close)
top.bind("<Escape>", self.close)
if self._htest: # place dialog below parent if running htest
top.geometry("+%d+%d" %
- (flist.root.winfo_rootx(), flist.root.winfo_rooty() + 200))
+ (root.winfo_rootx(), root.winfo_rooty() + 200))
self.settitle()
top.focus_set()
# create scrolled canvas
theme = idleConf.CurrentTheme()
background = idleConf.GetHighlight(theme, 'normal')['background']
- sc = ScrolledCanvas(top, bg=background, highlightthickness=0, takefocus=1)
+ sc = ScrolledCanvas(top, bg=background, highlightthickness=0,
+ takefocus=1)
sc.frame.pack(expand=1, fill="both")
item = self.rootnode()
self.node = node = TreeNode(sc.canvas, None, item)
@@ -122,18 +121,19 @@ def init(self, flist):
def settitle(self):
"Set the window title."
- self.top.wm_title("Module Browser - " + self.name)
+ self.top.wm_title("Module Browser - " + os.path.basename(self.path))
self.top.wm_iconname("Module Browser")
def rootnode(self):
"Return a ModuleBrowserTreeItem as the root of the tree."
- return ModuleBrowserTreeItem(self.file)
+ return ModuleBrowserTreeItem(self.path)
class ModuleBrowserTreeItem(TreeItem):
"""Browser tree for Python module.
Uses TreeItem as the basis for the structure of the tree.
+ Used by both browsers.
"""
def __init__(self, file):
@@ -170,8 +170,8 @@ def IsExpandable(self):
def listchildren(self):
"Return sequenced classes and functions in the module."
- dir, file = os.path.split(self.file)
- name, ext = os.path.splitext(file)
+ dir, base = os.path.split(self.file)
+ name, ext = os.path.splitext(base)
if os.path.normcase(ext) != ".py":
return []
try:
@@ -227,25 +227,22 @@ def OnDoubleClick(self):
def _module_browser(parent): # htest #
- try:
- file = sys.argv[1] # If pass file on command line
- # If this succeeds, unittest will fail.
- except IndexError:
+ if len(sys.argv) > 1: # If pass file on command line.
+ file = sys.argv[1]
+ else:
file = __file__
- # Add objects for htest
+ # Add nested objects for htest.
class Nested_in_func(TreeNode):
def nested_in_class(): pass
def closure():
class Nested_in_closure: pass
- dir, file = os.path.split(file)
- name = os.path.splitext(file)[0]
- flist = pyshell.PyShellFileList(parent)
global file_open
- file_open = flist.open
- ModuleBrowser(flist, name, [dir], _htest=True)
+ file_open = pyshell.PyShellFileList(parent).open
+ ModuleBrowser(parent, file, _htest=True)
if __name__ == "__main__":
- from unittest import main
- main('idlelib.idle_test.test_browser', verbosity=2, exit=False)
+ if len(sys.argv) == 1: # If pass file on command line, unittest fails.
+ from unittest import main
+ main('idlelib.idle_test.test_browser', verbosity=2, exit=False)
from idlelib.idle_test.htest import run
run(_module_browser)
diff --git a/Lib/idlelib/editor.py b/Lib/idlelib/editor.py
index 5b16ccee8a6..87d1eef01ec 100644
--- a/Lib/idlelib/editor.py
+++ b/Lib/idlelib/editor.py
@@ -664,10 +664,8 @@ def open_module_browser(self, event=None):
filename = self.open_module()
if filename is None:
return "break"
- head, tail = os.path.split(filename)
- base, ext = os.path.splitext(tail)
from idlelib import browser
- browser.ModuleBrowser(self.flist, base, [head])
+ browser.ModuleBrowser(self.root, filename)
return "break"
def open_path_browser(self, event=None):
diff --git a/Lib/idlelib/idle_test/test_browser.py b/Lib/idlelib/idle_test/test_browser.py
index b9ae0419f8c..c8184957821 100644
--- a/Lib/idlelib/idle_test/test_browser.py
+++ b/Lib/idlelib/idle_test/test_browser.py
@@ -24,30 +24,24 @@ def setUpClass(cls):
requires('gui')
cls.root = Tk()
cls.root.withdraw()
- cls.flist = filelist.FileList(cls.root)
- cls.file = __file__
- cls.path = os.path.dirname(cls.file)
- cls.module = os.path.basename(cls.file).rstrip('.py')
- cls.mb = browser.ModuleBrowser(cls.flist, cls.module, [cls.path], _utest=True)
+ cls.mb = browser.ModuleBrowser(cls.root, __file__, _utest=True)
@classmethod
def tearDownClass(cls):
cls.mb.close()
cls.root.destroy()
- del cls.root, cls.flist, cls.mb
+ del cls.root, cls.mb
def test_init(self):
mb = self.mb
eq = self.assertEqual
- eq(mb.name, self.module)
- eq(mb.file, self.file)
- eq(mb.flist, self.flist)
+ eq(mb.path, __file__)
eq(pyclbr._modules, {})
self.assertIsInstance(mb.node, TreeNode)
def test_settitle(self):
mb = self.mb
- self.assertIn(self.module, mb.top.title())
+ self.assertIn(os.path.basename(__file__), mb.top.title())
self.assertEqual(mb.top.iconname(), 'Module Browser')
def test_rootnode(self):
diff --git a/Misc/NEWS.d/next/IDLE/2017-09-30-19-03-26.bpo-31460.HpveI6.rst b/Misc/NEWS.d/next/IDLE/2017-09-30-19-03-26.bpo-31460.HpveI6.rst
new file mode 100644
index 00000000000..6492115260a
--- /dev/null
+++ b/Misc/NEWS.d/next/IDLE/2017-09-30-19-03-26.bpo-31460.HpveI6.rst
@@ -0,0 +1,6 @@
+Simplify the API of IDLE's Module Browser.
+
+Passing a widget instead of an flist with a root widget opens the option of
+creating a browser frame that is only part of a window. Passing a full file
+name instead of pieces assumed to come from a .py file opens the possibility
+of browsing python files that do not end in .py.
1
0