diff -r ffe4f3694c0f Lib/idlelib/CallTipWindow.py --- a/Lib/idlelib/CallTipWindow.py Thu Oct 16 23:12:48 2014 -0400 +++ b/Lib/idlelib/CallTipWindow.py Fri Oct 17 01:30:51 2014 -0400 @@ -133,37 +133,27 @@ def _calltip_window(parent): # htest # - import re - from tkinter import Tk, Text, LEFT, BOTH + from tkinter import Toplevel, Text, LEFT, BOTH - root = Tk() - root.title("Test calltips") - width, height, x, y = list(map(int, re.split('[x+]', parent.geometry()))) - root.geometry("+%d+%d"%(x, y + 150)) + top = Toplevel(parent) + top.title("Test calltips") + top.geometry("200x100+%d+%d" % (parent.winfo_rootx() + 200, + parent.winfo_rooty() + 150)) + text = Text(top) + text.pack(side=LEFT, fill=BOTH, expand=1) + text.insert("insert", "string.split") + top.update() + calltip = CallTip(text) - class MyEditWin: # conceptually an editor_window - def __init__(self): - text = self.text = Text(root) - text.pack(side=LEFT, fill=BOTH, expand=1) - text.insert("insert", "string.split") - root.update() - self.calltip = CallTip(text) - - text.event_add("<>", "(") - text.event_add("<>", ")") - text.bind("<>", self.calltip_show) - text.bind("<>", self.calltip_hide) - - text.focus_set() - root.mainloop() - - def calltip_show(self, event): - self.calltip.showtip("Hello world", "insert", "end") - - def calltip_hide(self, event): - self.calltip.hidetip() - - MyEditWin() + def calltip_show(event): + calltip.showtip("(s=Hello world)", "insert", "end") + def calltip_hide(event): + calltip.hidetip() + text.event_add("<>", "(") + text.event_add("<>", ")") + text.bind("<>", calltip_show) + text.bind("<>", calltip_hide) + text.focus_set() if __name__=='__main__': from idlelib.idle_test.htest import run diff -r ffe4f3694c0f Lib/idlelib/ClassBrowser.py --- a/Lib/idlelib/ClassBrowser.py Thu Oct 16 23:12:48 2014 -0400 +++ b/Lib/idlelib/ClassBrowser.py Fri Oct 17 01:30:51 2014 -0400 @@ -19,6 +19,9 @@ from idlelib.TreeWidget import TreeNode, TreeItem, ScrolledCanvas from idlelib.configHandler import idleConf +file_open = None # Method...Item and Class...Item use this. +# Normally PyShell.flist.open, but there is no PyShell.flist for htest. + class ClassBrowser: def __init__(self, flist, name, path, _htest=False): @@ -27,6 +30,9 @@ """ _htest - bool, change box when location running htest. """ + global file_open + if not _htest: + file_open = PyShell.flist.open self.name = name self.file = os.path.join(path[0], self.name + ".py") self._htest = _htest @@ -170,7 +176,7 @@ def OnDoubleClick(self): if not os.path.exists(self.file): return - edit = PyShell.flist.open(self.file) + edit = file_open(self.file) if hasattr(self.cl, 'lineno'): lineno = self.cl.lineno edit.gotoline(lineno) @@ -206,7 +212,7 @@ def OnDoubleClick(self): if not os.path.exists(self.file): return - edit = PyShell.flist.open(self.file) + edit = file_open(self.file) edit.gotoline(self.cl.methods[self.name]) def _class_browser(parent): #Wrapper for htest @@ -221,8 +227,9 @@ dir, file = os.path.split(file) name = os.path.splitext(file)[0] flist = PyShell.PyShellFileList(parent) + global file_open + file_open = flist.open ClassBrowser(flist, name, [dir], _htest=True) - parent.mainloop() if __name__ == "__main__": from idlelib.idle_test.htest import run diff -r ffe4f3694c0f Lib/idlelib/ColorDelegator.py --- a/Lib/idlelib/ColorDelegator.py Thu Oct 16 23:12:48 2014 -0400 +++ b/Lib/idlelib/ColorDelegator.py Fri Oct 17 01:30:51 2014 -0400 @@ -2,7 +2,6 @@ import re import keyword import builtins -from tkinter import * from idlelib.Delegator import Delegator from idlelib.configHandler import idleConf @@ -234,20 +233,23 @@ for tag in self.tagdefs: self.tag_remove(tag, "1.0", "end") -def _color_delegator(parent): +def _color_delegator(parent): # htest # + from tkinter import Toplevel, Text from idlelib.Percolator import Percolator - root = Tk() - root.title("Test ColorDelegator") - width, height, x, y = list(map(int, re.split('[x+]', parent.geometry()))) - root.geometry("+%d+%d"%(x, y + 150)) - source = "if somename: x = 'abc' # comment\nprint" - text = Text(root, background="white") + + top = Toplevel(parent) + top.title("Test ColorDelegator") + top.geometry("200x100+%d+%d" % (parent.winfo_rootx() + 200, + parent.winfo_rooty() + 150)) + source = "if somename: x = 'abc' # comment\nprint\n" + text = Text(top, background="white") + text.pack(expand=1, fill="both") text.insert("insert", source) - text.pack(expand=1, fill="both") + text.focus_set() + p = Percolator(text) d = ColorDelegator() p.insertfilter(d) - root.mainloop() if __name__ == "__main__": from idlelib.idle_test.htest import run diff -r ffe4f3694c0f Lib/idlelib/EditorWindow.py --- a/Lib/idlelib/EditorWindow.py Thu Oct 16 23:12:48 2014 -0400 +++ b/Lib/idlelib/EditorWindow.py Fri Oct 17 01:30:51 2014 -0400 @@ -1711,7 +1711,8 @@ tk.call('set', 'tcl_nonwordchars', '[^a-zA-Z0-9_]') -def _editor_window(parent): +def _editor_window(parent): # htest # + # error if close master window first - timer event, after script root = parent fixwordbreaks(root) if sys.argv[1:]: @@ -1721,7 +1722,8 @@ macosxSupport.setupApp(root, None) edit = EditorWindow(root=root, filename=filename) edit.text.bind("<>", edit.close_event) - parent.mainloop() + # Does not stop error, neither does following + # edit.text.bind("<>", edit.close_event) if __name__ == '__main__': from idlelib.idle_test.htest import run diff -r ffe4f3694c0f Lib/idlelib/GrepDialog.py --- a/Lib/idlelib/GrepDialog.py Thu Oct 16 23:12:48 2014 -0400 +++ b/Lib/idlelib/GrepDialog.py Fri Oct 17 01:30:51 2014 -0400 @@ -131,7 +131,7 @@ self.top.withdraw() -def _grep_dialog(parent): # for htest +def _grep_dialog(parent): # htest # from idlelib.PyShell import PyShellFileList root = Tk() root.title("Test GrepDialog") diff -r ffe4f3694c0f Lib/idlelib/configDialog.py --- a/Lib/idlelib/configDialog.py Thu Oct 16 23:12:48 2014 -0400 +++ b/Lib/idlelib/configDialog.py Fri Oct 17 01:30:51 2014 -0400 @@ -24,7 +24,7 @@ class ConfigDialog(Toplevel): - def __init__(self, parent, title, _htest=False, _utest=False): + def __init__(self, parent, title='', _htest=False, _utest=False): """ _htest - bool, change box location when running htest _utest - bool, don't wait_window when running unittest @@ -36,7 +36,7 @@ self.wm_withdraw() self.configure(borderwidth=5) - self.title('IDLE Preferences') + self.title(title or 'IDLE Preferences') self.geometry( "+%d+%d" % (parent.winfo_rootx() + 20, parent.winfo_rooty() + (30 if not _htest else 150))) diff -r ffe4f3694c0f Lib/idlelib/dynOptionMenuWidget.py --- a/Lib/idlelib/dynOptionMenuWidget.py Thu Oct 16 23:12:48 2014 -0400 +++ b/Lib/idlelib/dynOptionMenuWidget.py Fri Oct 17 01:30:51 2014 -0400 @@ -2,17 +2,15 @@ OptionMenu widget modified to allow dynamic menu reconfiguration and setting of highlightthickness """ -from tkinter import OptionMenu, _setit, Tk, StringVar, Button - import copy -import re +from tkinter import OptionMenu, _setit, StringVar, Button class DynOptionMenu(OptionMenu): """ unlike OptionMenu, our kwargs can include highlightthickness """ def __init__(self, master, variable, value, *values, **kwargs): - #get a copy of kwargs before OptionMenu.__init__ munges them + # TODO copy value instead of whole dict kwargsCopy=copy.copy(kwargs) if 'highlightthickness' in list(kwargs.keys()): del(kwargs['highlightthickness']) @@ -35,22 +33,24 @@ if value: self.variable.set(value) -def _dyn_option_menu(parent): - root = Tk() - root.title("Tets dynamic option menu") - var = StringVar(root) - width, height, x, y = list(map(int, re.split('[x+]', parent.geometry()))) - root.geometry("+%d+%d"%(x, y + 150)) +def _dyn_option_menu(parent): # htest # + from tkinter import Toplevel + + top = Toplevel() + top.title("Tets dynamic option menu") + top.geometry("200x100+%d+%d" % (parent.winfo_rootx() + 200, + parent.winfo_rooty() + 150)) + top.focus_set() + + var = StringVar(top) var.set("Old option set") #Set the default value - dyn = DynOptionMenu(root,var, "old1","old2","old3","old4") + dyn = DynOptionMenu(top,var, "old1","old2","old3","old4") dyn.pack() def update(): - dyn.SetMenu(["new1","new2","new3","new4"],value="new option set") - - button = Button(root, text="Change option set", command=update) + dyn.SetMenu(["new1","new2","new3","new4"], value="new option set") + button = Button(top, text="Change option set", command=update) button.pack() - root.mainloop() if __name__ == '__main__': from idlelib.idle_test.htest import run diff -r ffe4f3694c0f Lib/idlelib/idle_test/htest.py --- a/Lib/idlelib/idle_test/htest.py Thu Oct 16 23:12:48 2014 -0400 +++ b/Lib/idlelib/idle_test/htest.py Fri Oct 17 01:30:51 2014 -0400 @@ -1,11 +1,24 @@ '''Run human tests of Idle's window, dialog, and popup widgets. run(*tests) -Run each callable in tests after finding the matching test spec in this file. -If there are none, run an htest for each spec dict in this file after finding -the matching callable in the module named in the spec. +Create a master Tk window. Within that, run each callable in tests +after finding the matching test spec in this file. If tests is empty, +run an htest for each spec dict in this file after finding the matching +callable in the module named in the spec. Close the window to skip or +end the test. -In a tested module, let X be a global name bound to a widget callable. +In a tested module, let X be a global name bound to a callable (class +or function) whose .__name__ attrubute is also X (the usual situation). +The first parameter of X must be 'parent'. When called, the parent +argument will be the root window. X must create a child Toplevel +window (or subclass thereof). The Toplevel may be a test widget or +dialog, in which case the callable is the corresonding class. Or the +Toplevel may contain the widget to be tested or set up a context in +which a test widget is invoked. In this latter case, the callable is a +wrapper function that sets up the Toplevel and other objects. Wrapper +function names, such as _editor_window', should start with '_'. + + End the module with if __name__ == '__main__': @@ -13,13 +26,25 @@ from idlelib.idle_test.htest import run run(X) -The X object must have a .__name__ attribute and a 'parent' parameter. -X will often be a widget class, but a callable instance with .__name__ -or a wrapper function also work. The name of wrapper functions, like -'_editor_window', should start with '_'. +To have wrapper functions and test invocation code ignored by coveragepy +reports, put '# htest #' on the def statement header line. -This file must contain a matching instance of the following template, -with X.__name__ prepended, as in '_editor_window_spec ...'. +def _wrapper(parent): # htest # + +Also make sure that the 'if __name__' line matches the above. Then have +make sure that .coveragerc includes the following. + +[report] +exclude_lines = + .*# htest # + if __name__ == .__main__.: + +(The "." instead of "'" is intentional and necessary.) + + +To run any X, this file must contain a matching instance of the +following template, with X.__name__ prepended to '_spec'. +When all tests are run, the prefix is use to get X. _spec = { 'file': '', @@ -27,18 +52,19 @@ 'msg': "" } -file (no .py): used in run() to import the file and get X. -kwds: passed to X (**kwds), after 'parent' is added, to initialize X. -title: an example; used for some widgets, delete if not. -msg: displayed in a master window. Hints as to how the user might - test the widget. Close the window to skip or end the test. +file (no .py): run() imports file.py. +kwds: augmented with {'parent':root} and passed to X as **kwds. +title: an example kwd; some widgets need this, delete if not. +msg: master window hints about testing the widget. -Modules not being tested at the moment: + +Modules and classes not being tested at the moment: PyShell.PyShellEditorWindow Debugger.Debugger AutoCompleteWindow.AutoCompleteWindow OutputWindow.OutputWindow (indirectly being tested with grep test) ''' + from importlib import import_module from idlelib.macosxSupport import _initializeTkVariantTests import tkinter as tk @@ -79,7 +105,7 @@ ConfigDialog_spec = { 'file': 'configDialog', - 'kwds': {'title': 'Settings', + 'kwds': {'title': 'ConfigDialogTest', '_htest': True,}, 'msg': "IDLE preferences dialog.\n" "In the 'Fonts/Tabs' tab, changing font face, should update the " @@ -92,6 +118,7 @@ "changes made have persisted." } +# TODO Improve message _dyn_option_menu_spec = { 'file': 'dynOptionMenuWidget', 'kwds': {}, @@ -100,10 +127,12 @@ "Select one of the many options in the 'new option set'." } +# TODO edit wrapper _editor_window_spec = { 'file': 'EditorWindow', 'kwds': {}, - 'msg': "Test editor functions of interest." + 'msg': "Test editor functions of interest.\n" + "Best to close editor first." } GetCfgSectionNameDialog_spec = {