mirror of
https://github.com/python/cpython.git
synced 2025-07-23 11:15:24 +00:00
Issue #22629: Revise idle_test.htest, mostly docstring. Start revision of
htests to add # htest # marker for coveragepy and stop tcl errors.
This commit is contained in:
parent
9a6f8e1866
commit
cd567365c9
8 changed files with 110 additions and 80 deletions
|
@ -133,37 +133,27 @@ class CallTip:
|
||||||
|
|
||||||
|
|
||||||
def _calltip_window(parent): # htest #
|
def _calltip_window(parent): # htest #
|
||||||
import re
|
from tkinter import Toplevel, Text, LEFT, BOTH
|
||||||
from tkinter import Tk, Text, LEFT, BOTH
|
|
||||||
|
|
||||||
root = Tk()
|
top = Toplevel(parent)
|
||||||
root.title("Test calltips")
|
top.title("Test calltips")
|
||||||
width, height, x, y = list(map(int, re.split('[x+]', parent.geometry())))
|
top.geometry("200x100+%d+%d" % (parent.winfo_rootx() + 200,
|
||||||
root.geometry("+%d+%d"%(x, y + 150))
|
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 calltip_show(event):
|
||||||
def __init__(self):
|
calltip.showtip("(s=Hello world)", "insert", "end")
|
||||||
text = self.text = Text(root)
|
def calltip_hide(event):
|
||||||
text.pack(side=LEFT, fill=BOTH, expand=1)
|
calltip.hidetip()
|
||||||
text.insert("insert", "string.split")
|
text.event_add("<<calltip-show>>", "(")
|
||||||
root.update()
|
text.event_add("<<calltip-hide>>", ")")
|
||||||
self.calltip = CallTip(text)
|
text.bind("<<calltip-show>>", calltip_show)
|
||||||
|
text.bind("<<calltip-hide>>", calltip_hide)
|
||||||
text.event_add("<<calltip-show>>", "(")
|
text.focus_set()
|
||||||
text.event_add("<<calltip-hide>>", ")")
|
|
||||||
text.bind("<<calltip-show>>", self.calltip_show)
|
|
||||||
text.bind("<<calltip-hide>>", 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()
|
|
||||||
|
|
||||||
if __name__=='__main__':
|
if __name__=='__main__':
|
||||||
from idlelib.idle_test.htest import run
|
from idlelib.idle_test.htest import run
|
||||||
|
|
|
@ -19,6 +19,9 @@ from idlelib.WindowList import ListedToplevel
|
||||||
from idlelib.TreeWidget import TreeNode, TreeItem, ScrolledCanvas
|
from idlelib.TreeWidget import TreeNode, TreeItem, ScrolledCanvas
|
||||||
from idlelib.configHandler import idleConf
|
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:
|
class ClassBrowser:
|
||||||
|
|
||||||
def __init__(self, flist, name, path, _htest=False):
|
def __init__(self, flist, name, path, _htest=False):
|
||||||
|
@ -27,6 +30,9 @@ class ClassBrowser:
|
||||||
"""
|
"""
|
||||||
_htest - bool, change box when location running htest.
|
_htest - bool, change box when location running htest.
|
||||||
"""
|
"""
|
||||||
|
global file_open
|
||||||
|
if not _htest:
|
||||||
|
file_open = PyShell.flist.open
|
||||||
self.name = name
|
self.name = name
|
||||||
self.file = os.path.join(path[0], self.name + ".py")
|
self.file = os.path.join(path[0], self.name + ".py")
|
||||||
self._htest = _htest
|
self._htest = _htest
|
||||||
|
@ -170,7 +176,7 @@ class ClassBrowserTreeItem(TreeItem):
|
||||||
def OnDoubleClick(self):
|
def OnDoubleClick(self):
|
||||||
if not os.path.exists(self.file):
|
if not os.path.exists(self.file):
|
||||||
return
|
return
|
||||||
edit = PyShell.flist.open(self.file)
|
edit = file_open(self.file)
|
||||||
if hasattr(self.cl, 'lineno'):
|
if hasattr(self.cl, 'lineno'):
|
||||||
lineno = self.cl.lineno
|
lineno = self.cl.lineno
|
||||||
edit.gotoline(lineno)
|
edit.gotoline(lineno)
|
||||||
|
@ -206,7 +212,7 @@ class MethodBrowserTreeItem(TreeItem):
|
||||||
def OnDoubleClick(self):
|
def OnDoubleClick(self):
|
||||||
if not os.path.exists(self.file):
|
if not os.path.exists(self.file):
|
||||||
return
|
return
|
||||||
edit = PyShell.flist.open(self.file)
|
edit = file_open(self.file)
|
||||||
edit.gotoline(self.cl.methods[self.name])
|
edit.gotoline(self.cl.methods[self.name])
|
||||||
|
|
||||||
def _class_browser(parent): #Wrapper for htest
|
def _class_browser(parent): #Wrapper for htest
|
||||||
|
@ -221,8 +227,9 @@ def _class_browser(parent): #Wrapper for htest
|
||||||
dir, file = os.path.split(file)
|
dir, file = os.path.split(file)
|
||||||
name = os.path.splitext(file)[0]
|
name = os.path.splitext(file)[0]
|
||||||
flist = PyShell.PyShellFileList(parent)
|
flist = PyShell.PyShellFileList(parent)
|
||||||
|
global file_open
|
||||||
|
file_open = flist.open
|
||||||
ClassBrowser(flist, name, [dir], _htest=True)
|
ClassBrowser(flist, name, [dir], _htest=True)
|
||||||
parent.mainloop()
|
|
||||||
|
|
||||||
if __name__ == "__main__":
|
if __name__ == "__main__":
|
||||||
from idlelib.idle_test.htest import run
|
from idlelib.idle_test.htest import run
|
||||||
|
|
|
@ -2,7 +2,6 @@ import time
|
||||||
import re
|
import re
|
||||||
import keyword
|
import keyword
|
||||||
import builtins
|
import builtins
|
||||||
from tkinter import *
|
|
||||||
from idlelib.Delegator import Delegator
|
from idlelib.Delegator import Delegator
|
||||||
from idlelib.configHandler import idleConf
|
from idlelib.configHandler import idleConf
|
||||||
|
|
||||||
|
@ -234,20 +233,23 @@ class ColorDelegator(Delegator):
|
||||||
for tag in self.tagdefs:
|
for tag in self.tagdefs:
|
||||||
self.tag_remove(tag, "1.0", "end")
|
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
|
from idlelib.Percolator import Percolator
|
||||||
root = Tk()
|
|
||||||
root.title("Test ColorDelegator")
|
top = Toplevel(parent)
|
||||||
width, height, x, y = list(map(int, re.split('[x+]', parent.geometry())))
|
top.title("Test ColorDelegator")
|
||||||
root.geometry("+%d+%d"%(x, y + 150))
|
top.geometry("200x100+%d+%d" % (parent.winfo_rootx() + 200,
|
||||||
source = "if somename: x = 'abc' # comment\nprint"
|
parent.winfo_rooty() + 150))
|
||||||
text = Text(root, background="white")
|
source = "if somename: x = 'abc' # comment\nprint\n"
|
||||||
text.insert("insert", source)
|
text = Text(top, background="white")
|
||||||
text.pack(expand=1, fill="both")
|
text.pack(expand=1, fill="both")
|
||||||
|
text.insert("insert", source)
|
||||||
|
text.focus_set()
|
||||||
|
|
||||||
p = Percolator(text)
|
p = Percolator(text)
|
||||||
d = ColorDelegator()
|
d = ColorDelegator()
|
||||||
p.insertfilter(d)
|
p.insertfilter(d)
|
||||||
root.mainloop()
|
|
||||||
|
|
||||||
if __name__ == "__main__":
|
if __name__ == "__main__":
|
||||||
from idlelib.idle_test.htest import run
|
from idlelib.idle_test.htest import run
|
||||||
|
|
|
@ -1711,7 +1711,8 @@ def fixwordbreaks(root):
|
||||||
tk.call('set', 'tcl_nonwordchars', '[^a-zA-Z0-9_]')
|
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
|
root = parent
|
||||||
fixwordbreaks(root)
|
fixwordbreaks(root)
|
||||||
if sys.argv[1:]:
|
if sys.argv[1:]:
|
||||||
|
@ -1721,7 +1722,8 @@ def _editor_window(parent):
|
||||||
macosxSupport.setupApp(root, None)
|
macosxSupport.setupApp(root, None)
|
||||||
edit = EditorWindow(root=root, filename=filename)
|
edit = EditorWindow(root=root, filename=filename)
|
||||||
edit.text.bind("<<close-all-windows>>", edit.close_event)
|
edit.text.bind("<<close-all-windows>>", edit.close_event)
|
||||||
parent.mainloop()
|
# Does not stop error, neither does following
|
||||||
|
# edit.text.bind("<<close-window>>", edit.close_event)
|
||||||
|
|
||||||
if __name__ == '__main__':
|
if __name__ == '__main__':
|
||||||
from idlelib.idle_test.htest import run
|
from idlelib.idle_test.htest import run
|
||||||
|
|
|
@ -131,7 +131,7 @@ class GrepDialog(SearchDialogBase):
|
||||||
self.top.withdraw()
|
self.top.withdraw()
|
||||||
|
|
||||||
|
|
||||||
def _grep_dialog(parent): # for htest
|
def _grep_dialog(parent): # htest #
|
||||||
from idlelib.PyShell import PyShellFileList
|
from idlelib.PyShell import PyShellFileList
|
||||||
root = Tk()
|
root = Tk()
|
||||||
root.title("Test GrepDialog")
|
root.title("Test GrepDialog")
|
||||||
|
|
|
@ -24,7 +24,7 @@ from idlelib import macosxSupport
|
||||||
|
|
||||||
class ConfigDialog(Toplevel):
|
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
|
_htest - bool, change box location when running htest
|
||||||
_utest - bool, don't wait_window when running unittest
|
_utest - bool, don't wait_window when running unittest
|
||||||
|
@ -36,7 +36,7 @@ class ConfigDialog(Toplevel):
|
||||||
self.wm_withdraw()
|
self.wm_withdraw()
|
||||||
|
|
||||||
self.configure(borderwidth=5)
|
self.configure(borderwidth=5)
|
||||||
self.title('IDLE Preferences')
|
self.title(title or 'IDLE Preferences')
|
||||||
self.geometry(
|
self.geometry(
|
||||||
"+%d+%d" % (parent.winfo_rootx() + 20,
|
"+%d+%d" % (parent.winfo_rootx() + 20,
|
||||||
parent.winfo_rooty() + (30 if not _htest else 150)))
|
parent.winfo_rooty() + (30 if not _htest else 150)))
|
||||||
|
|
|
@ -2,17 +2,15 @@
|
||||||
OptionMenu widget modified to allow dynamic menu reconfiguration
|
OptionMenu widget modified to allow dynamic menu reconfiguration
|
||||||
and setting of highlightthickness
|
and setting of highlightthickness
|
||||||
"""
|
"""
|
||||||
from tkinter import OptionMenu, _setit, Tk, StringVar, Button
|
|
||||||
|
|
||||||
import copy
|
import copy
|
||||||
import re
|
from tkinter import OptionMenu, _setit, StringVar, Button
|
||||||
|
|
||||||
class DynOptionMenu(OptionMenu):
|
class DynOptionMenu(OptionMenu):
|
||||||
"""
|
"""
|
||||||
unlike OptionMenu, our kwargs can include highlightthickness
|
unlike OptionMenu, our kwargs can include highlightthickness
|
||||||
"""
|
"""
|
||||||
def __init__(self, master, variable, value, *values, **kwargs):
|
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)
|
kwargsCopy=copy.copy(kwargs)
|
||||||
if 'highlightthickness' in list(kwargs.keys()):
|
if 'highlightthickness' in list(kwargs.keys()):
|
||||||
del(kwargs['highlightthickness'])
|
del(kwargs['highlightthickness'])
|
||||||
|
@ -35,22 +33,24 @@ class DynOptionMenu(OptionMenu):
|
||||||
if value:
|
if value:
|
||||||
self.variable.set(value)
|
self.variable.set(value)
|
||||||
|
|
||||||
def _dyn_option_menu(parent):
|
def _dyn_option_menu(parent): # htest #
|
||||||
root = Tk()
|
from tkinter import Toplevel
|
||||||
root.title("Tets dynamic option menu")
|
|
||||||
var = StringVar(root)
|
top = Toplevel()
|
||||||
width, height, x, y = list(map(int, re.split('[x+]', parent.geometry())))
|
top.title("Tets dynamic option menu")
|
||||||
root.geometry("+%d+%d"%(x, y + 150))
|
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
|
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()
|
dyn.pack()
|
||||||
|
|
||||||
def update():
|
def update():
|
||||||
dyn.SetMenu(["new1","new2","new3","new4"],value="new option set")
|
dyn.SetMenu(["new1","new2","new3","new4"], value="new option set")
|
||||||
|
button = Button(top, text="Change option set", command=update)
|
||||||
button = Button(root, text="Change option set", command=update)
|
|
||||||
button.pack()
|
button.pack()
|
||||||
root.mainloop()
|
|
||||||
|
|
||||||
if __name__ == '__main__':
|
if __name__ == '__main__':
|
||||||
from idlelib.idle_test.htest import run
|
from idlelib.idle_test.htest import run
|
||||||
|
|
|
@ -1,11 +1,24 @@
|
||||||
'''Run human tests of Idle's window, dialog, and popup widgets.
|
'''Run human tests of Idle's window, dialog, and popup widgets.
|
||||||
|
|
||||||
run(*tests)
|
run(*tests)
|
||||||
Run each callable in tests after finding the matching test spec in this file.
|
Create a master Tk window. Within that, run each callable in tests
|
||||||
If there are none, run an htest for each spec dict in this file after finding
|
after finding the matching test spec in this file. If tests is empty,
|
||||||
the matching callable in the module named in the spec.
|
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 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 '_'.
|
||||||
|
|
||||||
|
|
||||||
In a tested module, let X be a global name bound to a widget callable.
|
|
||||||
End the module with
|
End the module with
|
||||||
|
|
||||||
if __name__ == '__main__':
|
if __name__ == '__main__':
|
||||||
|
@ -13,13 +26,25 @@ if __name__ == '__main__':
|
||||||
from idlelib.idle_test.htest import run
|
from idlelib.idle_test.htest import run
|
||||||
run(X)
|
run(X)
|
||||||
|
|
||||||
The X object must have a .__name__ attribute and a 'parent' parameter.
|
To have wrapper functions and test invocation code ignored by coveragepy
|
||||||
X will often be a widget class, but a callable instance with .__name__
|
reports, put '# htest #' on the def statement header line.
|
||||||
or a wrapper function also work. The name of wrapper functions, like
|
|
||||||
'_editor_window', should start with '_'.
|
|
||||||
|
|
||||||
This file must contain a matching instance of the following template,
|
def _wrapper(parent): # htest #
|
||||||
with X.__name__ prepended, as in '_editor_window_spec ...'.
|
|
||||||
|
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 = {
|
_spec = {
|
||||||
'file': '',
|
'file': '',
|
||||||
|
@ -27,18 +52,19 @@ _spec = {
|
||||||
'msg': ""
|
'msg': ""
|
||||||
}
|
}
|
||||||
|
|
||||||
file (no .py): used in run() to import the file and get X.
|
file (no .py): run() imports file.py.
|
||||||
kwds: passed to X (**kwds), after 'parent' is added, to initialize X.
|
kwds: augmented with {'parent':root} and passed to X as **kwds.
|
||||||
title: an example; used for some widgets, delete if not.
|
title: an example kwd; some widgets need this, delete if not.
|
||||||
msg: displayed in a master window. Hints as to how the user might
|
msg: master window hints about testing the widget.
|
||||||
test the widget. Close the window to skip or end the test.
|
|
||||||
|
|
||||||
Modules not being tested at the moment:
|
|
||||||
|
Modules and classes not being tested at the moment:
|
||||||
PyShell.PyShellEditorWindow
|
PyShell.PyShellEditorWindow
|
||||||
Debugger.Debugger
|
Debugger.Debugger
|
||||||
AutoCompleteWindow.AutoCompleteWindow
|
AutoCompleteWindow.AutoCompleteWindow
|
||||||
OutputWindow.OutputWindow (indirectly being tested with grep test)
|
OutputWindow.OutputWindow (indirectly being tested with grep test)
|
||||||
'''
|
'''
|
||||||
|
|
||||||
from importlib import import_module
|
from importlib import import_module
|
||||||
from idlelib.macosxSupport import _initializeTkVariantTests
|
from idlelib.macosxSupport import _initializeTkVariantTests
|
||||||
import tkinter as tk
|
import tkinter as tk
|
||||||
|
@ -79,7 +105,7 @@ _color_delegator_spec = {
|
||||||
|
|
||||||
ConfigDialog_spec = {
|
ConfigDialog_spec = {
|
||||||
'file': 'configDialog',
|
'file': 'configDialog',
|
||||||
'kwds': {'title': 'Settings',
|
'kwds': {'title': 'ConfigDialogTest',
|
||||||
'_htest': True,},
|
'_htest': True,},
|
||||||
'msg': "IDLE preferences dialog.\n"
|
'msg': "IDLE preferences dialog.\n"
|
||||||
"In the 'Fonts/Tabs' tab, changing font face, should update the "
|
"In the 'Fonts/Tabs' tab, changing font face, should update the "
|
||||||
|
@ -92,6 +118,7 @@ ConfigDialog_spec = {
|
||||||
"changes made have persisted."
|
"changes made have persisted."
|
||||||
}
|
}
|
||||||
|
|
||||||
|
# TODO Improve message
|
||||||
_dyn_option_menu_spec = {
|
_dyn_option_menu_spec = {
|
||||||
'file': 'dynOptionMenuWidget',
|
'file': 'dynOptionMenuWidget',
|
||||||
'kwds': {},
|
'kwds': {},
|
||||||
|
@ -100,10 +127,12 @@ _dyn_option_menu_spec = {
|
||||||
"Select one of the many options in the 'new option set'."
|
"Select one of the many options in the 'new option set'."
|
||||||
}
|
}
|
||||||
|
|
||||||
|
# TODO edit wrapper
|
||||||
_editor_window_spec = {
|
_editor_window_spec = {
|
||||||
'file': 'EditorWindow',
|
'file': 'EditorWindow',
|
||||||
'kwds': {},
|
'kwds': {},
|
||||||
'msg': "Test editor functions of interest."
|
'msg': "Test editor functions of interest.\n"
|
||||||
|
"Best to close editor first."
|
||||||
}
|
}
|
||||||
|
|
||||||
GetCfgSectionNameDialog_spec = {
|
GetCfgSectionNameDialog_spec = {
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue