[Python-checkins] cpython: Issue #24137: Run IDLE, test_idle, and htest with tkinter default root disabled.

terry.reedy python-checkins at python.org
Tue Jun 21 18:42:00 EDT 2016


https://hg.python.org/cpython/rev/064b29dde096
changeset: 102117:064b29dde096
user: Terry Jan Reedy <tjreedy at udel.edu>
date: Tue Jun 21 18:41:38 2016 -0400
summary:
 Issue #24137: Run IDLE, test_idle, and htest with tkinter default root disabled.
Fix code and tests that fail with this restriction.
Fix htests to not create a second and redundant root and mainloop.
files:
 Lib/idlelib/debugobj.py | 17 +++---
 Lib/idlelib/dynoption.py | 4 +-
 Lib/idlelib/grep.py | 15 +++---
 Lib/idlelib/idle_test/htest.py | 3 +-
 Lib/idlelib/idle_test/test_searchbase.py | 10 ++-
 Lib/idlelib/idle_test/test_text.py | 21 ++++++--
 Lib/idlelib/multicall.py | 11 ++--
 Lib/idlelib/percolator.py | 4 +-
 Lib/idlelib/pyshell.py | 5 +-
 Lib/idlelib/redirector.py | 13 ++---
 Lib/idlelib/stackviewer.py | 10 ++--
 Lib/idlelib/statusbar.py | 28 +++++------
 Lib/idlelib/tabbedpages.py | 22 ++++-----
 Lib/idlelib/undo.py | 12 ++--
 Lib/test/test_idle.py | 1 +
 15 files changed, 92 insertions(+), 84 deletions(-)
diff --git a/Lib/idlelib/debugobj.py b/Lib/idlelib/debugobj.py
--- a/Lib/idlelib/debugobj.py
+++ b/Lib/idlelib/debugobj.py
@@ -122,21 +122,20 @@
 return c(labeltext, object, setfunction)
 
 
-def _object_browser(parent):
+def _object_browser(parent): # htest #
 import sys
- from tkinter import Tk
- root = Tk()
- root.title("Test debug object browser")
+ from tkinter import Toplevel
+ top = Toplevel(parent)
+ top.title("Test debug object browser")
 width, height, x, y = list(map(int, re.split('[x+]', parent.geometry())))
- root.geometry("+%d+%d"%(x, y + 150))
- root.configure(bd=0, bg="yellow")
- root.focus_set()
- sc = ScrolledCanvas(root, bg="white", highlightthickness=0, takefocus=1)
+ top.geometry("+%d+%d"%(x + 100, y + 175))
+ top.configure(bd=0, bg="yellow")
+ top.focus_set()
+ sc = ScrolledCanvas(top, bg="white", highlightthickness=0, takefocus=1)
 sc.frame.pack(expand=1, fill="both")
 item = make_objecttreeitem("sys", sys)
 node = TreeNode(sc.canvas, None, item)
 node.update()
- root.mainloop()
 
 if __name__ == '__main__':
 from idlelib.idle_test.htest import run
diff --git a/Lib/idlelib/dynoption.py b/Lib/idlelib/dynoption.py
--- a/Lib/idlelib/dynoption.py
+++ b/Lib/idlelib/dynoption.py
@@ -34,9 +34,9 @@
 self.variable.set(value)
 
 def _dyn_option_menu(parent): # htest #
- from tkinter import Toplevel
+ from tkinter import Toplevel # + StringVar, Button
 
- top = Toplevel()
+ top = Toplevel(parent)
 top.title("Tets dynamic option menu")
 top.geometry("200x100+%d+%d" % (parent.winfo_rootx() + 200,
 parent.winfo_rooty() + 150))
diff --git a/Lib/idlelib/grep.py b/Lib/idlelib/grep.py
--- a/Lib/idlelib/grep.py
+++ b/Lib/idlelib/grep.py
@@ -3,7 +3,6 @@
 import re # for htest
 import sys
 from tkinter import StringVar, BooleanVar, Checkbutton # for GrepDialog
-from tkinter import Tk, Text, Button, SEL, END # for htest
 from idlelib import searchengine
 from idlelib.searchbase import SearchDialogBase
 # Importing OutputWindow fails due to import loop
@@ -132,13 +131,14 @@
 
 def _grep_dialog(parent): # htest #
 from idlelib.pyshell import PyShellFileList
- root = Tk()
- root.title("Test GrepDialog")
+ from tkinter import Toplevel, Text, Button, SEL, END
+ top = Toplevel(parent)
+ top.title("Test GrepDialog")
 width, height, x, y = list(map(int, re.split('[x+]', parent.geometry())))
- root.geometry("+%d+%d"%(x, y + 150))
+ top.geometry("+%d+%d"%(x, y + 150))
 
- flist = PyShellFileList(root)
- text = Text(root, height=5)
+ flist = PyShellFileList(top)
+ text = Text(top, height=5)
 text.pack()
 
 def show_grep_dialog():
@@ -146,9 +146,8 @@
 grep(text, flist=flist)
 text.tag_remove(SEL, "1.0", END)
 
- button = Button(root, text="Show GrepDialog", command=show_grep_dialog)
+ button = Button(top, text="Show GrepDialog", command=show_grep_dialog)
 button.pack()
- root.mainloop()
 
 if __name__ == "__main__":
 import unittest
diff --git a/Lib/idlelib/idle_test/htest.py b/Lib/idlelib/idle_test/htest.py
--- a/Lib/idlelib/idle_test/htest.py
+++ b/Lib/idlelib/idle_test/htest.py
@@ -68,6 +68,7 @@
 from importlib import import_module
 import tkinter as tk
 from tkinter.ttk import Scrollbar
+tk.NoDefaultRoot()
 
 AboutDialog_spec = {
 'file': 'help_about',
@@ -364,7 +365,7 @@
 test = getattr(mod, test_name)
 test_list.append((test_spec, test))
 
- test_name = tk.StringVar('')
+ test_name = tk.StringVar(root)
 callable_object = None
 test_kwds = None
 
diff --git a/Lib/idlelib/idle_test/test_searchbase.py b/Lib/idlelib/idle_test/test_searchbase.py
--- a/Lib/idlelib/idle_test/test_searchbase.py
+++ b/Lib/idlelib/idle_test/test_searchbase.py
@@ -74,7 +74,7 @@
 def test_make_entry(self):
 equal = self.assertEqual
 self.dialog.row = 0
- self.dialog.top = Toplevel(self.root)
+ self.dialog.top = self.root
 entry, label = self.dialog.make_entry("Test:", 'hello')
 equal(label['text'], 'Test:')
 
@@ -87,6 +87,7 @@
 equal(self.dialog.row, 1)
 
 def test_create_entries(self):
+ self.dialog.top = self.root
 self.dialog.row = 0
 self.engine.setpat('hello')
 self.dialog.create_entries()
@@ -94,7 +95,7 @@
 
 def test_make_frame(self):
 self.dialog.row = 0
- self.dialog.top = Toplevel(self.root)
+ self.dialog.top = self.root
 frame, label = self.dialog.make_frame()
 self.assertEqual(label, '')
 self.assertIsInstance(frame, Frame)
@@ -104,7 +105,7 @@
 self.assertIsInstance(frame, Frame)
 
 def btn_test_setup(self, meth):
- self.dialog.top = Toplevel(self.root)
+ self.dialog.top = self.root
 self.dialog.row = 0
 return meth()
 
@@ -145,12 +146,13 @@
 self.assertEqual(var.get(), state)
 
 def test_make_button(self):
- self.dialog.top = Toplevel(self.root)
+ self.dialog.top = self.root
 self.dialog.buttonframe = Frame(self.dialog.top)
 btn = self.dialog.make_button('Test', self.dialog.close)
 self.assertEqual(btn['text'], 'Test')
 
 def test_create_command_buttons(self):
+ self.dialog.top = self.root
 self.dialog.create_command_buttons()
 # Look for close button command in buttonframe
 closebuttoncommand = ''
diff --git a/Lib/idlelib/idle_test/test_text.py b/Lib/idlelib/idle_test/test_text.py
--- a/Lib/idlelib/idle_test/test_text.py
+++ b/Lib/idlelib/idle_test/test_text.py
@@ -1,17 +1,19 @@
-# Test mock_tk.Text class against tkinter.Text class by running same tests with both.
+''' Test mock_tk.Text class against tkinter.Text class
+
+Run same tests with both by creating a mixin class.
+'''
 import unittest
 from test.support import requires
-
 from _tkinter import TclError
 
 class TextTest(object):
+ "Define items common to both sets of tests."
 
- hw = 'hello\nworld' # usual initial insert after initialization
+ hw = 'hello\nworld' # Several tests insert this after after initialization.
 hwn = hw+'\n' # \n present at initialization, before insert
 
- Text = None
- def setUp(self):
- self.text = self.Text()
+ # setUpClass defines cls.Text and maybe cls.root.
+ # setUp defines self.text from Text and maybe root.
 
 def test_init(self):
 self.assertEqual(self.text.get('1.0'), '\n')
@@ -196,6 +198,10 @@
 from idlelib.idle_test.mock_tk import Text
 cls.Text = Text
 
+ def setUp(self):
+ self.text = self.Text()
+
+
 def test_decode(self):
 # test endflags (-1, 0) not tested by test_index (which uses +1)
 decode = self.text._decode
@@ -222,6 +228,9 @@
 cls.root.destroy()
 del cls.root
 
+ def setUp(self):
+ self.text = self.Text(self.root)
+
 
 if __name__ == '__main__':
 unittest.main(verbosity=2, exit=False)
diff --git a/Lib/idlelib/multicall.py b/Lib/idlelib/multicall.py
--- a/Lib/idlelib/multicall.py
+++ b/Lib/idlelib/multicall.py
@@ -414,12 +414,12 @@
 return MultiCall
 
 
-def _multi_call(parent):
- root = tkinter.Tk()
- root.title("Test MultiCall")
+def _multi_call(parent): # htest #
+ top = tkinter.Toplevel(parent)
+ top.title("Test MultiCall")
 width, height, x, y = list(map(int, re.split('[x+]', parent.geometry())))
- root.geometry("+%d+%d"%(x, y + 150))
- text = MultiCallCreator(tkinter.Text)(root)
+ top.geometry("+%d+%d"%(x, y + 150))
+ text = MultiCallCreator(tkinter.Text)(top)
 text.pack()
 def bindseq(seq, n=[0]):
 def handler(event):
@@ -439,7 +439,6 @@
 bindseq("<FocusOut>")
 bindseq("<Enter>")
 bindseq("<Leave>")
- root.mainloop()
 
 if __name__ == "__main__":
 from idlelib.idle_test.htest import run
diff --git a/Lib/idlelib/percolator.py b/Lib/idlelib/percolator.py
--- a/Lib/idlelib/percolator.py
+++ b/Lib/idlelib/percolator.py
@@ -89,10 +89,10 @@
 (pin if var2.get() else pout)(t2)
 
 text.pack()
- var1 = tk.IntVar()
+ var1 = tk.IntVar(parent)
 cb1 = tk.Checkbutton(box, text="Tracer1", command=toggle1, variable=var1)
 cb1.pack()
- var2 = tk.IntVar()
+ var2 = tk.IntVar(parent)
 cb2 = tk.Checkbutton(box, text="Tracer2", command=toggle2, variable=var2)
 cb2.pack()
 
diff --git a/Lib/idlelib/pyshell.py b/Lib/idlelib/pyshell.py
--- a/Lib/idlelib/pyshell.py
+++ b/Lib/idlelib/pyshell.py
@@ -1547,7 +1547,9 @@
 enable_edit = enable_edit or edit_start
 enable_shell = enable_shell or not enable_edit
 
- # start editor and/or shell windows:
+ # Setup root.
+ if use_subprocess: # Don't break user code run in IDLE process
+ NoDefaultRoot()
 root = Tk(className="Idle")
 root.withdraw()
 
@@ -1563,6 +1565,7 @@
 icons = [PhotoImage(file=iconfile) for iconfile in iconfiles]
 root.wm_iconphoto(True, *icons)
 
+ # start editor and/or shell windows:
 fixwordbreaks(root)
 fix_x11_paste(root)
 flist = PyShellFileList(root)
diff --git a/Lib/idlelib/redirector.py b/Lib/idlelib/redirector.py
--- a/Lib/idlelib/redirector.py
+++ b/Lib/idlelib/redirector.py
@@ -151,14 +151,14 @@
 
 
 def _widget_redirector(parent): # htest #
- from tkinter import Tk, Text
+ from tkinter import Toplevel, Text
 import re
 
- root = Tk()
- root.title("Test WidgetRedirector")
+ top = Toplevel(parent)
+ top.title("Test WidgetRedirector")
 width, height, x, y = list(map(int, re.split('[x+]', parent.geometry())))
- root.geometry("+%d+%d"%(x, y + 150))
- text = Text(root)
+ top.geometry("+%d+%d"%(x, y + 150))
+ text = Text(top)
 text.pack()
 text.focus_set()
 redir = WidgetRedirector(text)
@@ -166,11 +166,10 @@
 print("insert", args)
 original_insert(*args)
 original_insert = redir.register("insert", my_insert)
- root.mainloop()
 
 if __name__ == "__main__":
 import unittest
- unittest.main('idlelib.idle_test.test_widgetredir',
+ unittest.main('idlelib.idle_test.test_redirector',
 verbosity=2, exit=False)
 from idlelib.idle_test.htest import run
 run(_widget_redirector)
diff --git a/Lib/idlelib/stackviewer.py b/Lib/idlelib/stackviewer.py
--- a/Lib/idlelib/stackviewer.py
+++ b/Lib/idlelib/stackviewer.py
@@ -121,11 +121,11 @@
 return sublist
 
 def _stack_viewer(parent):
- root = tk.Tk()
- root.title("Test StackViewer")
+ top = tk.Toplevel(parent)
+ top.title("Test StackViewer")
 width, height, x, y = list(map(int, re.split('[x+]', parent.geometry())))
- root.geometry("+%d+%d"%(x, y + 150))
- flist = PyShellFileList(root)
+ top.geometry("+%d+%d"%(x, y + 150))
+ flist = PyShellFileList(top)
 try: # to obtain a traceback object
 intentional_name_error
 except NameError:
@@ -136,7 +136,7 @@
 sys.last_value = exc_value
 sys.last_traceback = exc_tb
 
- StackBrowser(root, flist=flist, top=root, tb=exc_tb)
+ StackBrowser(top, flist=flist, top=top, tb=exc_tb)
 
 # restore sys to original state
 del sys.last_type
diff --git a/Lib/idlelib/statusbar.py b/Lib/idlelib/statusbar.py
--- a/Lib/idlelib/statusbar.py
+++ b/Lib/idlelib/statusbar.py
@@ -1,16 +1,14 @@
-from tkinter import *
+from tkinter import Frame, Label
 
 class MultiStatusBar(Frame):
 
- def __init__(self, master=None, **kw):
- if master is None:
- master = Tk()
+ def __init__(self, master, **kw):
 Frame.__init__(self, master, **kw)
 self.labels = {}
 
- def set_label(self, name, text='', side=LEFT, width=0):
+ def set_label(self, name, text='', side='left', width=0):
 if name not in self.labels:
- label = Label(self, borderwidth=0, anchor=W)
+ label = Label(self, borderwidth=0, anchor='w')
 label.pack(side=side, pady=0, padx=4)
 self.labels[name] = label
 else:
@@ -20,27 +18,27 @@
 label.config(text=text)
 
 def _multistatus_bar(parent):
- root = Tk()
+ import re
+ from tkinter import Toplevel, Frame, Text, Button
+ top = Toplevel(parent)
 width, height, x, y = list(map(int, re.split('[x+]', parent.geometry())))
- root.geometry("+%d+%d" %(x, y + 150))
- root.title("Test multistatus bar")
- frame = Frame(root)
+ top.geometry("+%d+%d" %(x, y + 150))
+ top.title("Test multistatus bar")
+ frame = Frame(top)
 text = Text(frame)
 text.pack()
 msb = MultiStatusBar(frame)
 msb.set_label("one", "hello")
 msb.set_label("two", "world")
- msb.pack(side=BOTTOM, fill=X)
+ msb.pack(side='bottom', fill='x')
 
 def change():
 msb.set_label("one", "foo")
 msb.set_label("two", "bar")
 
- button = Button(root, text="Update status", command=change)
- button.pack(side=BOTTOM)
+ button = Button(top, text="Update status", command=change)
+ button.pack(side='bottom')
 frame.pack()
- frame.mainloop()
- root.mainloop()
 
 if __name__ == '__main__':
 from idlelib.idle_test.htest import run
diff --git a/Lib/idlelib/tabbedpages.py b/Lib/idlelib/tabbedpages.py
--- a/Lib/idlelib/tabbedpages.py
+++ b/Lib/idlelib/tabbedpages.py
@@ -467,31 +467,29 @@
 
 self._tab_set.set_selected_tab(page_name)
 
-def _tabbed_pages(parent):
- # test dialog
- root=Tk()
+def _tabbed_pages(parent): # htest #
+ import re
+ top=Toplevel(parent)
 width, height, x, y = list(map(int, re.split('[x+]', parent.geometry())))
- root.geometry("+%d+%d"%(x, y + 175))
- root.title("Test tabbed pages")
- tabPage=TabbedPageSet(root, page_names=['Foobar','Baz'], n_rows=0,
+ top.geometry("+%d+%d"%(x, y + 175))
+ top.title("Test tabbed pages")
+ tabPage=TabbedPageSet(top, page_names=['Foobar','Baz'], n_rows=0,
 expand_tabs=False,
 )
 tabPage.pack(side=TOP, expand=TRUE, fill=BOTH)
 Label(tabPage.pages['Foobar'].frame, text='Foo', pady=20).pack()
 Label(tabPage.pages['Foobar'].frame, text='Bar', pady=20).pack()
 Label(tabPage.pages['Baz'].frame, text='Baz').pack()
- entryPgName=Entry(root)
- buttonAdd=Button(root, text='Add Page',
+ entryPgName=Entry(top)
+ buttonAdd=Button(top, text='Add Page',
 command=lambda:tabPage.add_page(entryPgName.get()))
- buttonRemove=Button(root, text='Remove Page',
+ buttonRemove=Button(top, text='Remove Page',
 command=lambda:tabPage.remove_page(entryPgName.get()))
- labelPgName=Label(root, text='name of page to add/remove:')
+ labelPgName=Label(top, text='name of page to add/remove:')
 buttonAdd.pack(padx=5, pady=5)
 buttonRemove.pack(padx=5, pady=5)
 labelPgName.pack(padx=5)
 entryPgName.pack(padx=5)
- root.mainloop()
-
 
 if __name__ == '__main__':
 from idlelib.idle_test.htest import run
diff --git a/Lib/idlelib/undo.py b/Lib/idlelib/undo.py
--- a/Lib/idlelib/undo.py
+++ b/Lib/idlelib/undo.py
@@ -1,7 +1,7 @@
 import string
-from tkinter import *
-
 from idlelib.delegator import Delegator
+# tkintter import not needed because module does not create widgets,
+# although many methods operate on text widget arguments.
 
 #$ event <<redo>>
 #$ win <Control-y>
@@ -339,12 +339,12 @@
 
 def _undo_delegator(parent): # htest #
 import re
- import tkinter as tk
+ from tkinter import Toplevel, Text, Button
 from idlelib.percolator import Percolator
- undowin = tk.Toplevel()
+ undowin = Toplevel(parent)
 undowin.title("Test UndoDelegator")
 width, height, x, y = list(map(int, re.split('[x+]', parent.geometry())))
- undowin.geometry("+%d+%d"%(x, y + 150))
+ undowin.geometry("+%d+%d"%(x, y + 175))
 
 text = Text(undowin, height=10)
 text.pack()
@@ -362,7 +362,7 @@
 
 if __name__ == "__main__":
 import unittest
- unittest.main('idlelib.idle_test.test_undodelegator', verbosity=2,
+ unittest.main('idlelib.idle_test.test_undo', verbosity=2,
 exit=False)
 from idlelib.idle_test.htest import run
 run(_undo_delegator)
diff --git a/Lib/test/test_idle.py b/Lib/test/test_idle.py
--- a/Lib/test/test_idle.py
+++ b/Lib/test/test_idle.py
@@ -6,6 +6,7 @@
 tk = import_module('tkinter') # imports _tkinter
 if tk.TkVersion < 8.5:
 raise unittest.SkipTest("IDLE requires tk 8.5 or later.")
+tk.NoDefaultRoot()
 idletest = import_module('idlelib.idle_test')
 
 # Without test_main present, regrtest.runtest_inner (line1219) calls
-- 
Repository URL: https://hg.python.org/cpython


More information about the Python-checkins mailing list

AltStyle によって変換されたページ (->オリジナル) /