Commit b60adc54 authored by Terry Jan Reedy's avatar Terry Jan Reedy

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.
parent aacd53f6
...@@ -122,21 +122,20 @@ def make_objecttreeitem(labeltext, object, setfunction=None): ...@@ -122,21 +122,20 @@ def make_objecttreeitem(labeltext, object, setfunction=None):
return c(labeltext, object, setfunction) return c(labeltext, object, setfunction)
def _object_browser(parent): def _object_browser(parent): # htest #
import sys import sys
from tkinter import Tk from tkinter import Toplevel
root = Tk() top = Toplevel(parent)
root.title("Test debug object browser") top.title("Test debug object browser")
width, height, x, y = list(map(int, re.split('[x+]', parent.geometry()))) width, height, x, y = list(map(int, re.split('[x+]', parent.geometry())))
root.geometry("+%d+%d"%(x, y + 150)) top.geometry("+%d+%d"%(x + 100, y + 175))
root.configure(bd=0, bg="yellow") top.configure(bd=0, bg="yellow")
root.focus_set() top.focus_set()
sc = ScrolledCanvas(root, bg="white", highlightthickness=0, takefocus=1) sc = ScrolledCanvas(top, bg="white", highlightthickness=0, takefocus=1)
sc.frame.pack(expand=1, fill="both") sc.frame.pack(expand=1, fill="both")
item = make_objecttreeitem("sys", sys) item = make_objecttreeitem("sys", sys)
node = TreeNode(sc.canvas, None, item) node = TreeNode(sc.canvas, None, item)
node.update() node.update()
root.mainloop()
if __name__ == '__main__': if __name__ == '__main__':
from idlelib.idle_test.htest import run from idlelib.idle_test.htest import run
......
...@@ -34,9 +34,9 @@ class DynOptionMenu(OptionMenu): ...@@ -34,9 +34,9 @@ class DynOptionMenu(OptionMenu):
self.variable.set(value) self.variable.set(value)
def _dyn_option_menu(parent): # htest # 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.title("Tets dynamic option menu")
top.geometry("200x100+%d+%d" % (parent.winfo_rootx() + 200, top.geometry("200x100+%d+%d" % (parent.winfo_rootx() + 200,
parent.winfo_rooty() + 150)) parent.winfo_rooty() + 150))
......
...@@ -3,7 +3,6 @@ import fnmatch ...@@ -3,7 +3,6 @@ import fnmatch
import re # for htest import re # for htest
import sys import sys
from tkinter import StringVar, BooleanVar, Checkbutton # for GrepDialog from tkinter import StringVar, BooleanVar, Checkbutton # for GrepDialog
from tkinter import Tk, Text, Button, SEL, END # for htest
from idlelib import searchengine from idlelib import searchengine
from idlelib.searchbase import SearchDialogBase from idlelib.searchbase import SearchDialogBase
# Importing OutputWindow fails due to import loop # Importing OutputWindow fails due to import loop
...@@ -132,13 +131,14 @@ class GrepDialog(SearchDialogBase): ...@@ -132,13 +131,14 @@ class GrepDialog(SearchDialogBase):
def _grep_dialog(parent): # htest # def _grep_dialog(parent): # htest #
from idlelib.pyshell import PyShellFileList from idlelib.pyshell import PyShellFileList
root = Tk() from tkinter import Toplevel, Text, Button, SEL, END
root.title("Test GrepDialog") top = Toplevel(parent)
top.title("Test GrepDialog")
width, height, x, y = list(map(int, re.split('[x+]', parent.geometry()))) 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) flist = PyShellFileList(top)
text = Text(root, height=5) text = Text(top, height=5)
text.pack() text.pack()
def show_grep_dialog(): def show_grep_dialog():
...@@ -146,9 +146,8 @@ def _grep_dialog(parent): # htest # ...@@ -146,9 +146,8 @@ def _grep_dialog(parent): # htest #
grep(text, flist=flist) grep(text, flist=flist)
text.tag_remove(SEL, "1.0", END) 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() button.pack()
root.mainloop()
if __name__ == "__main__": if __name__ == "__main__":
import unittest import unittest
......
...@@ -68,6 +68,7 @@ outwin.OutputWindow (indirectly being tested with grep test) ...@@ -68,6 +68,7 @@ outwin.OutputWindow (indirectly being tested with grep test)
from importlib import import_module from importlib import import_module
import tkinter as tk import tkinter as tk
from tkinter.ttk import Scrollbar from tkinter.ttk import Scrollbar
tk.NoDefaultRoot()
AboutDialog_spec = { AboutDialog_spec = {
'file': 'help_about', 'file': 'help_about',
...@@ -364,7 +365,7 @@ def run(*tests): ...@@ -364,7 +365,7 @@ def run(*tests):
test = getattr(mod, test_name) test = getattr(mod, test_name)
test_list.append((test_spec, test)) test_list.append((test_spec, test))
test_name = tk.StringVar('') test_name = tk.StringVar(root)
callable_object = None callable_object = None
test_kwds = None test_kwds = None
......
...@@ -74,7 +74,7 @@ class SearchDialogBaseTest(unittest.TestCase): ...@@ -74,7 +74,7 @@ class SearchDialogBaseTest(unittest.TestCase):
def test_make_entry(self): def test_make_entry(self):
equal = self.assertEqual equal = self.assertEqual
self.dialog.row = 0 self.dialog.row = 0
self.dialog.top = Toplevel(self.root) self.dialog.top = self.root
entry, label = self.dialog.make_entry("Test:", 'hello') entry, label = self.dialog.make_entry("Test:", 'hello')
equal(label['text'], 'Test:') equal(label['text'], 'Test:')
...@@ -87,6 +87,7 @@ class SearchDialogBaseTest(unittest.TestCase): ...@@ -87,6 +87,7 @@ class SearchDialogBaseTest(unittest.TestCase):
equal(self.dialog.row, 1) equal(self.dialog.row, 1)
def test_create_entries(self): def test_create_entries(self):
self.dialog.top = self.root
self.dialog.row = 0 self.dialog.row = 0
self.engine.setpat('hello') self.engine.setpat('hello')
self.dialog.create_entries() self.dialog.create_entries()
...@@ -94,7 +95,7 @@ class SearchDialogBaseTest(unittest.TestCase): ...@@ -94,7 +95,7 @@ class SearchDialogBaseTest(unittest.TestCase):
def test_make_frame(self): def test_make_frame(self):
self.dialog.row = 0 self.dialog.row = 0
self.dialog.top = Toplevel(self.root) self.dialog.top = self.root
frame, label = self.dialog.make_frame() frame, label = self.dialog.make_frame()
self.assertEqual(label, '') self.assertEqual(label, '')
self.assertIsInstance(frame, Frame) self.assertIsInstance(frame, Frame)
...@@ -104,7 +105,7 @@ class SearchDialogBaseTest(unittest.TestCase): ...@@ -104,7 +105,7 @@ class SearchDialogBaseTest(unittest.TestCase):
self.assertIsInstance(frame, Frame) self.assertIsInstance(frame, Frame)
def btn_test_setup(self, meth): def btn_test_setup(self, meth):
self.dialog.top = Toplevel(self.root) self.dialog.top = self.root
self.dialog.row = 0 self.dialog.row = 0
return meth() return meth()
...@@ -145,12 +146,13 @@ class SearchDialogBaseTest(unittest.TestCase): ...@@ -145,12 +146,13 @@ class SearchDialogBaseTest(unittest.TestCase):
self.assertEqual(var.get(), state) self.assertEqual(var.get(), state)
def test_make_button(self): def test_make_button(self):
self.dialog.top = Toplevel(self.root) self.dialog.top = self.root
self.dialog.buttonframe = Frame(self.dialog.top) self.dialog.buttonframe = Frame(self.dialog.top)
btn = self.dialog.make_button('Test', self.dialog.close) btn = self.dialog.make_button('Test', self.dialog.close)
self.assertEqual(btn['text'], 'Test') self.assertEqual(btn['text'], 'Test')
def test_create_command_buttons(self): def test_create_command_buttons(self):
self.dialog.top = self.root
self.dialog.create_command_buttons() self.dialog.create_command_buttons()
# Look for close button command in buttonframe # Look for close button command in buttonframe
closebuttoncommand = '' closebuttoncommand = ''
......
# 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 import unittest
from test.support import requires from test.support import requires
from _tkinter import TclError from _tkinter import TclError
class TextTest(object): 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 hwn = hw+'\n' # \n present at initialization, before insert
Text = None # setUpClass defines cls.Text and maybe cls.root.
def setUp(self): # setUp defines self.text from Text and maybe root.
self.text = self.Text()
def test_init(self): def test_init(self):
self.assertEqual(self.text.get('1.0'), '\n') self.assertEqual(self.text.get('1.0'), '\n')
...@@ -196,6 +198,10 @@ class MockTextTest(TextTest, unittest.TestCase): ...@@ -196,6 +198,10 @@ class MockTextTest(TextTest, unittest.TestCase):
from idlelib.idle_test.mock_tk import Text from idlelib.idle_test.mock_tk import Text
cls.Text = Text cls.Text = Text
def setUp(self):
self.text = self.Text()
def test_decode(self): def test_decode(self):
# test endflags (-1, 0) not tested by test_index (which uses +1) # test endflags (-1, 0) not tested by test_index (which uses +1)
decode = self.text._decode decode = self.text._decode
...@@ -222,6 +228,9 @@ class TkTextTest(TextTest, unittest.TestCase): ...@@ -222,6 +228,9 @@ class TkTextTest(TextTest, unittest.TestCase):
cls.root.destroy() cls.root.destroy()
del cls.root del cls.root
def setUp(self):
self.text = self.Text(self.root)
if __name__ == '__main__': if __name__ == '__main__':
unittest.main(verbosity=2, exit=False) unittest.main(verbosity=2, exit=False)
...@@ -414,12 +414,12 @@ def MultiCallCreator(widget): ...@@ -414,12 +414,12 @@ def MultiCallCreator(widget):
return MultiCall return MultiCall
def _multi_call(parent): def _multi_call(parent): # htest #
root = tkinter.Tk() top = tkinter.Toplevel(parent)
root.title("Test MultiCall") top.title("Test MultiCall")
width, height, x, y = list(map(int, re.split('[x+]', parent.geometry()))) 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))
text = MultiCallCreator(tkinter.Text)(root) text = MultiCallCreator(tkinter.Text)(top)
text.pack() text.pack()
def bindseq(seq, n=[0]): def bindseq(seq, n=[0]):
def handler(event): def handler(event):
...@@ -439,7 +439,6 @@ def _multi_call(parent): ...@@ -439,7 +439,6 @@ def _multi_call(parent):
bindseq("<FocusOut>") bindseq("<FocusOut>")
bindseq("<Enter>") bindseq("<Enter>")
bindseq("<Leave>") bindseq("<Leave>")
root.mainloop()
if __name__ == "__main__": if __name__ == "__main__":
from idlelib.idle_test.htest import run from idlelib.idle_test.htest import run
......
...@@ -89,10 +89,10 @@ def _percolator(parent): # htest # ...@@ -89,10 +89,10 @@ def _percolator(parent): # htest #
(pin if var2.get() else pout)(t2) (pin if var2.get() else pout)(t2)
text.pack() text.pack()
var1 = tk.IntVar() var1 = tk.IntVar(parent)
cb1 = tk.Checkbutton(box, text="Tracer1", command=toggle1, variable=var1) cb1 = tk.Checkbutton(box, text="Tracer1", command=toggle1, variable=var1)
cb1.pack() cb1.pack()
var2 = tk.IntVar() var2 = tk.IntVar(parent)
cb2 = tk.Checkbutton(box, text="Tracer2", command=toggle2, variable=var2) cb2 = tk.Checkbutton(box, text="Tracer2", command=toggle2, variable=var2)
cb2.pack() cb2.pack()
......
...@@ -1547,7 +1547,9 @@ def main(): ...@@ -1547,7 +1547,9 @@ def main():
enable_edit = enable_edit or edit_start enable_edit = enable_edit or edit_start
enable_shell = enable_shell or not enable_edit 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 = Tk(className="Idle")
root.withdraw() root.withdraw()
...@@ -1563,6 +1565,7 @@ def main(): ...@@ -1563,6 +1565,7 @@ def main():
icons = [PhotoImage(file=iconfile) for iconfile in iconfiles] icons = [PhotoImage(file=iconfile) for iconfile in iconfiles]
root.wm_iconphoto(True, *icons) root.wm_iconphoto(True, *icons)
# start editor and/or shell windows:
fixwordbreaks(root) fixwordbreaks(root)
fix_x11_paste(root) fix_x11_paste(root)
flist = PyShellFileList(root) flist = PyShellFileList(root)
......
...@@ -151,14 +151,14 @@ class OriginalCommand: ...@@ -151,14 +151,14 @@ class OriginalCommand:
def _widget_redirector(parent): # htest # def _widget_redirector(parent): # htest #
from tkinter import Tk, Text from tkinter import Toplevel, Text
import re import re
root = Tk() top = Toplevel(parent)
root.title("Test WidgetRedirector") top.title("Test WidgetRedirector")
width, height, x, y = list(map(int, re.split('[x+]', parent.geometry()))) 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))
text = Text(root) text = Text(top)
text.pack() text.pack()
text.focus_set() text.focus_set()
redir = WidgetRedirector(text) redir = WidgetRedirector(text)
...@@ -166,11 +166,10 @@ def _widget_redirector(parent): # htest # ...@@ -166,11 +166,10 @@ def _widget_redirector(parent): # htest #
print("insert", args) print("insert", args)
original_insert(*args) original_insert(*args)
original_insert = redir.register("insert", my_insert) original_insert = redir.register("insert", my_insert)
root.mainloop()
if __name__ == "__main__": if __name__ == "__main__":
import unittest import unittest
unittest.main('idlelib.idle_test.test_widgetredir', unittest.main('idlelib.idle_test.test_redirector',
verbosity=2, exit=False) verbosity=2, exit=False)
from idlelib.idle_test.htest import run from idlelib.idle_test.htest import run
run(_widget_redirector) run(_widget_redirector)
...@@ -121,11 +121,11 @@ class VariablesTreeItem(ObjectTreeItem): ...@@ -121,11 +121,11 @@ class VariablesTreeItem(ObjectTreeItem):
return sublist return sublist
def _stack_viewer(parent): def _stack_viewer(parent):
root = tk.Tk() top = tk.Toplevel(parent)
root.title("Test StackViewer") top.title("Test StackViewer")
width, height, x, y = list(map(int, re.split('[x+]', parent.geometry()))) 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) flist = PyShellFileList(top)
try: # to obtain a traceback object try: # to obtain a traceback object
intentional_name_error intentional_name_error
except NameError: except NameError:
...@@ -136,7 +136,7 @@ def _stack_viewer(parent): ...@@ -136,7 +136,7 @@ def _stack_viewer(parent):
sys.last_value = exc_value sys.last_value = exc_value
sys.last_traceback = exc_tb 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 # restore sys to original state
del sys.last_type del sys.last_type
......
from tkinter import * from tkinter import Frame, Label
class MultiStatusBar(Frame): class MultiStatusBar(Frame):
def __init__(self, master=None, **kw): def __init__(self, master, **kw):
if master is None:
master = Tk()
Frame.__init__(self, master, **kw) Frame.__init__(self, master, **kw)
self.labels = {} 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: 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) label.pack(side=side, pady=0, padx=4)
self.labels[name] = label self.labels[name] = label
else: else:
...@@ -20,27 +18,27 @@ class MultiStatusBar(Frame): ...@@ -20,27 +18,27 @@ class MultiStatusBar(Frame):
label.config(text=text) label.config(text=text)
def _multistatus_bar(parent): 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()))) 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))
root.title("Test multistatus bar") top.title("Test multistatus bar")
frame = Frame(root) frame = Frame(top)
text = Text(frame) text = Text(frame)
text.pack() text.pack()
msb = MultiStatusBar(frame) msb = MultiStatusBar(frame)
msb.set_label("one", "hello") msb.set_label("one", "hello")
msb.set_label("two", "world") msb.set_label("two", "world")
msb.pack(side=BOTTOM, fill=X) msb.pack(side='bottom', fill='x')
def change(): def change():
msb.set_label("one", "foo") msb.set_label("one", "foo")
msb.set_label("two", "bar") msb.set_label("two", "bar")
button = Button(root, text="Update status", command=change) button = Button(top, text="Update status", command=change)
button.pack(side=BOTTOM) button.pack(side='bottom')
frame.pack() frame.pack()
frame.mainloop()
root.mainloop()
if __name__ == '__main__': if __name__ == '__main__':
from idlelib.idle_test.htest import run from idlelib.idle_test.htest import run
......
...@@ -467,31 +467,29 @@ class TabbedPageSet(Frame): ...@@ -467,31 +467,29 @@ class TabbedPageSet(Frame):
self._tab_set.set_selected_tab(page_name) self._tab_set.set_selected_tab(page_name)
def _tabbed_pages(parent): def _tabbed_pages(parent): # htest #
# test dialog import re
root=Tk() top=Toplevel(parent)
width, height, x, y = list(map(int, re.split('[x+]', parent.geometry()))) width, height, x, y = list(map(int, re.split('[x+]', parent.geometry())))
root.geometry("+%d+%d"%(x, y + 175)) top.geometry("+%d+%d"%(x, y + 175))
root.title("Test tabbed pages") top.title("Test tabbed pages")
tabPage=TabbedPageSet(root, page_names=['Foobar','Baz'], n_rows=0, tabPage=TabbedPageSet(top, page_names=['Foobar','Baz'], n_rows=0,
expand_tabs=False, expand_tabs=False,
) )
tabPage.pack(side=TOP, expand=TRUE, fill=BOTH) tabPage.pack(side=TOP, expand=TRUE, fill=BOTH)
Label(tabPage.pages['Foobar'].frame, text='Foo', pady=20).pack() Label(tabPage.pages['Foobar'].frame, text='Foo', pady=20).pack()
Label(tabPage.pages['Foobar'].frame, text='Bar', pady=20).pack() Label(tabPage.pages['Foobar'].frame, text='Bar', pady=20).pack()
Label(tabPage.pages['Baz'].frame, text='Baz').pack() Label(tabPage.pages['Baz'].frame, text='Baz').pack()
entryPgName=Entry(root) entryPgName=Entry(top)
buttonAdd=Button(root, text='Add Page', buttonAdd=Button(top, text='Add Page',
command=lambda:tabPage.add_page(entryPgName.get())) 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())) 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) buttonAdd.pack(padx=5, pady=5)
buttonRemove.pack(padx=5, pady=5) buttonRemove.pack(padx=5, pady=5)
labelPgName.pack(padx=5) labelPgName.pack(padx=5)
entryPgName.pack(padx=5) entryPgName.pack(padx=5)
root.mainloop()
if __name__ == '__main__': if __name__ == '__main__':
from idlelib.idle_test.htest import run from idlelib.idle_test.htest import run
......
import string import string
from tkinter import *
from idlelib.delegator import Delegator 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>> #$ event <<redo>>
#$ win <Control-y> #$ win <Control-y>
...@@ -339,12 +339,12 @@ class CommandSequence(Command): ...@@ -339,12 +339,12 @@ class CommandSequence(Command):
def _undo_delegator(parent): # htest # def _undo_delegator(parent): # htest #
import re import re
import tkinter as tk from tkinter import Toplevel, Text, Button
from idlelib.percolator import Percolator from idlelib.percolator import Percolator
undowin = tk.Toplevel() undowin = Toplevel(parent)
undowin.title("Test UndoDelegator") undowin.title("Test UndoDelegator")
width, height, x, y = list(map(int, re.split('[x+]', parent.geometry()))) 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 = Text(undowin, height=10)
text.pack() text.pack()
...@@ -362,7 +362,7 @@ def _undo_delegator(parent): # htest # ...@@ -362,7 +362,7 @@ def _undo_delegator(parent): # htest #
if __name__ == "__main__": if __name__ == "__main__":
import unittest import unittest
unittest.main('idlelib.idle_test.test_undodelegator', verbosity=2, unittest.main('idlelib.idle_test.test_undo', verbosity=2,
exit=False) exit=False)
from idlelib.idle_test.htest import run from idlelib.idle_test.htest import run
run(_undo_delegator) run(_undo_delegator)
...@@ -6,6 +6,7 @@ import_module('threading') # imported by PyShell, imports _thread ...@@ -6,6 +6,7 @@ import_module('threading') # imported by PyShell, imports _thread
tk = import_module('tkinter') # imports _tkinter tk = import_module('tkinter') # imports _tkinter
if tk.TkVersion < 8.5: if tk.TkVersion < 8.5:
raise unittest.SkipTest("IDLE requires tk 8.5 or later.") raise unittest.SkipTest("IDLE requires tk 8.5 or later.")
tk.NoDefaultRoot()
idletest = import_module('idlelib.idle_test') idletest = import_module('idlelib.idle_test')
# Without test_main present, regrtest.runtest_inner (line1219) calls # Without test_main present, regrtest.runtest_inner (line1219) calls
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment