]> git.ipfire.org Git - thirdparty/Python/cpython.git/commitdiff
Issue #24137: Run IDLE, test_idle, and htest with tkinter default root disabled.
authorTerry Jan Reedy <tjreedy@udel.edu>
Tue, 21 Jun 2016 22:41:38 +0000 (18:41 -0400)
committerTerry Jan Reedy <tjreedy@udel.edu>
Tue, 21 Jun 2016 22:41:38 +0000 (18:41 -0400)
Fix code and tests that fail with this restriction.
Fix htests to not create a second and redundant root and mainloop.

15 files changed:
Lib/idlelib/debugobj.py
Lib/idlelib/dynoption.py
Lib/idlelib/grep.py
Lib/idlelib/idle_test/htest.py
Lib/idlelib/idle_test/test_searchbase.py
Lib/idlelib/idle_test/test_text.py
Lib/idlelib/multicall.py
Lib/idlelib/percolator.py
Lib/idlelib/pyshell.py
Lib/idlelib/redirector.py
Lib/idlelib/stackviewer.py
Lib/idlelib/statusbar.py
Lib/idlelib/tabbedpages.py
Lib/idlelib/undo.py
Lib/test/test_idle.py

index 4016c032d45ddec5827d4bd933aedb162754f0e3..0d8b2b2c7d7e2608d612a64add09912f565018d5 100644 (file)
@@ -122,21 +122,20 @@ def make_objecttreeitem(labeltext, object, setfunction=None):
     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
index 515b4bafc2c4435b9163518e098e453be455a1eb..922ad5e4afbda6d9b35126d9a8d4cc20b651eba5 100644 (file)
@@ -34,9 +34,9 @@ class DynOptionMenu(OptionMenu):
             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))
index 28132a89177ffaf1253d271c690ce470771bc0f3..6324b4f112f91410804c21e9ed42e0c3fe8754d0 100644 (file)
@@ -3,7 +3,6 @@ import fnmatch
 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 @@ class GrepDialog(SearchDialogBase):
 
 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 @@ def _grep_dialog(parent):  # htest #
         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
index d0177bb5ad19147faf530623b344d831e04d80cf..701f4d9fe638acc4d2cc010141c70905b51e92d5 100644 (file)
@@ -68,6 +68,7 @@ outwin.OutputWindow (indirectly being tested with grep test)
 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 @@ def run(*tests):
                 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
 
index 5ff9476c873d69c7a5c166719f1cc462e00b6a66..a0b1231ecdc2776dd2c9c5eb91af915c550872cf 100644 (file)
@@ -74,7 +74,7 @@ class SearchDialogBaseTest(unittest.TestCase):
     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 @@ class SearchDialogBaseTest(unittest.TestCase):
         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 @@ class SearchDialogBaseTest(unittest.TestCase):
 
     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 @@ class SearchDialogBaseTest(unittest.TestCase):
         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 @@ class SearchDialogBaseTest(unittest.TestCase):
                     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 = ''
index 7e823df3db8abf16837ea089e8de96a46875aa41..a5ba7bb2136654e59cb0410d58d71cdadba23440 100644 (file)
@@ -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 @@ class MockTextTest(TextTest, unittest.TestCase):
         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 @@ class TkTextTest(TextTest, unittest.TestCase):
         cls.root.destroy()
         del cls.root
 
+    def setUp(self):
+        self.text = self.Text(self.root)
+
 
 if __name__ == '__main__':
     unittest.main(verbosity=2, exit=False)
index 8462854921e9c9c4fe2d4dc1c081b8301045a1ba..bf02f597f3ac9d47ccb269b6994a14fa9564f022 100644 (file)
@@ -414,12 +414,12 @@ def MultiCallCreator(widget):
     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 @@ def _multi_call(parent):
     bindseq("<FocusOut>")
     bindseq("<Enter>")
     bindseq("<Leave>")
-    root.mainloop()
 
 if __name__ == "__main__":
     from idlelib.idle_test.htest import run
index 227144581be96b7d0e69a7d8176ccc3b49a2814c..2111e036e7ea58c9a94d5e09899fe5a41ec249a2 100644 (file)
@@ -89,10 +89,10 @@ def _percolator(parent):  # htest #
         (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()
 
index 0f7a01d77ba276de644d2f50aea52d684e21f397..3e8351fdf3f55b678744381f94c7723c64cbb0a8 100755 (executable)
@@ -1547,7 +1547,9 @@ def main():
     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 @@ def main():
         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)
index 5ca7a2d5ffa42105802401daa6dd7018cb548345..3a110557d9e7535926ec8f73cbea36a341055aaa 100644 (file)
@@ -151,14 +151,14 @@ class OriginalCommand:
 
 
 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 @@ def _widget_redirector(parent):  # htest #
         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)
index 87c964e7af06d527c0f872a4ba2363746bc1f7a4..b3b99bcefd03333766037eaf21937b0c4329b445 100644 (file)
@@ -121,11 +121,11 @@ class VariablesTreeItem(ObjectTreeItem):
         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 @@ def _stack_viewer(parent):
     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
index e82ba9ab2fb97752d1f1fad76621c5278395725f..c093920be49810b7466b2763c6e8def8a0ca8eb3 100644 (file)
@@ -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 @@ class MultiStatusBar(Frame):
         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
index 965f9f8593dc920be7f48ba3f639b65a49c7b2b0..5f67097b5a9a36ca2a208e8c568f0d4cb97fae71 100644 (file)
@@ -467,31 +467,29 @@ class TabbedPageSet(Frame):
 
         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
index 3e94b69bbea6f8e7a45219d6dfcba082aa697b68..ccc962a122ec08585c63fee729a0a6c7d4d99ebb 100644 (file)
@@ -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 @@ class CommandSequence(Command):
 
 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 @@ def _undo_delegator(parent):  # htest #
 
 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)
index 46f1a5c3eca0a3b7b0973bab669566ef7bcda9d7..9d5239409faab2049a3a0d3ed8421daa11184373 100644 (file)
@@ -6,6 +6,7 @@ import_module('threading')  # imported by PyShell, imports _thread
 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