Merged revisions 69050 via svnmerge from

svn+ssh://pythondev/python/trunk

........
  r69050 | guilherme.polo | 2009-01-28 11:09:03 -0200 (Wed, 28 Jan 2009) | 2 lines

  Added the ttk module. See issue #2983: Ttk support for Tkinter.
........
This commit is contained in:
Guilherme Polo 2009-01-28 14:41:10 +00:00
parent 9844a1ffc3
commit 5f23848574
15 changed files with 5074 additions and 2 deletions

View File

@ -12,8 +12,8 @@ Graphical User Interfaces with Tk
Tk/Tcl has long been an integral part of Python. It provides a robust and
platform independent windowing toolkit, that is available to Python programmers
using the :mod:`tkinter` package, and its extension, the :mod:`tkinter.tix`
module.
using the :mod:`tkinter` package, and its extension, the :mod:`tkinter.tix` and
the :mod:`tkinter.ttk` modules.
The :mod:`tkinter` package is a thin object-oriented layer on top of Tcl/Tk. To
use :mod:`tkinter`, you don't need to write Tcl code, but you will need to
@ -33,6 +33,7 @@ alternatives, see the :ref:`other-gui-packages` section.
.. toctree::
tkinter.rst
tkinter.ttk.rst
tkinter.tix.rst
tkinter.scrolledtext.rst
turtle.rst

1401
Doc/library/tkinter.ttk.rst Normal file

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,14 @@
from test import support
from tkinter.test import runtktests
def test_main(enable_gui=False):
if enable_gui:
if support.use_resources is None:
support.use_resources = ['gui']
elif 'gui' not in support.use_resources:
support.use_resources.append('gui')
support.run_unittest(*runtktests.get_tests(text=False))
if __name__ == '__main__':
test_main(enable_gui=True)

View File

@ -0,0 +1,8 @@
from test import support
from tkinter.test import runtktests
def test_main():
support.run_unittest(*runtktests.get_tests(gui=False))
if __name__ == '__main__':
test_main()

14
Lib/tkinter/test/README Normal file
View File

@ -0,0 +1,14 @@
Writing new tests
=================
Precaution
----------
New tests should always use only one Tk window at once, like all the
current tests do. This means that you have to destroy the current window
before creating another one, and clean up after the test. The motivation
behind this is that some tests may depend on having its window focused
while it is running to work properly, and it may be hard to force focus
on your window across platforms (right now only test_traversal at
test_ttk.test_widgets.NotebookTest depends on this).

View File

View File

@ -0,0 +1,68 @@
"""
Use this module to get and run all tk tests.
tkinter tests should live in a package inside the directory where this file
lives, like test_tkinter.
Extensions also should live in packages following the same rule as above.
"""
import os
import sys
import unittest
import test.support
this_dir_path = os.path.abspath(os.path.dirname(__file__))
def is_package(path):
for name in os.listdir(path):
if name in ('__init__.py', '__init__.pyc', '__init.pyo'):
return True
return False
def get_tests_modules(basepath=this_dir_path, gui=True):
"""This will import and yield modules whose names start with test_
and are inside packages found in the path starting at basepath."""
py_ext = '.py'
for dirpath, dirnames, filenames in os.walk(basepath):
for dirname in list(dirnames):
if dirname[0] == '.':
dirnames.remove(dirname)
if is_package(dirpath) and filenames:
pkg_name = dirpath[len(basepath) + len(os.sep):].replace('/', '.')
filenames = filter(
lambda x: x.startswith('test_') and x.endswith(py_ext),
filenames)
for name in filenames:
try:
yield __import__(
"%s.%s.%s" % (
"tkinter.test",
pkg_name,
name[:-len(py_ext)]),
fromlist=['']
)
except test.support.ResourceDenied:
if gui:
raise
def get_tests(text=True, gui=True):
"""Yield all the tests in the modules found by get_tests_modules.
If nogui is True, only tests that do not require a GUI will be
returned."""
attrs = []
if text:
attrs.append('tests_nogui')
if gui:
attrs.append('tests_gui')
for module in get_tests_modules(gui=gui):
for attr in attrs:
for test in getattr(module, attr, ()):
yield test
if __name__ == "__main__":
test.support.use_resources = ['gui']
test.support.run_unittest(*get_tests())

View File

@ -0,0 +1,25 @@
import tkinter
def get_tk_root():
try:
root = tkinter._default_root
except AttributeError:
# it is possible to disable default root in Tkinter, although
# I haven't seen people doing it (but apparently someone did it
# here).
root = None
if root is None:
# create a new master only if there isn't one already
root = tkinter.Tk()
return root
def simulate_mouse_click(widget, x, y):
"""Generate proper events to click at the x, y position (tries to act
like an X server)."""
widget.event_generate('<Enter>', x=0, y=0)
widget.event_generate('<Motion>', x=x, y=y)
widget.event_generate('<ButtonPress-1>', x=x, y=y)
widget.event_generate('<ButtonRelease-1>', x=x, y=y)

View File

View File

@ -0,0 +1,266 @@
import sys
import unittest
import tkinter
from tkinter import ttk
from test.support import requires, run_unittest
import tkinter.test.support as support
requires('gui')
class LabeledScaleTest(unittest.TestCase):
def test_widget_destroy(self):
# automatically created variable
x = ttk.LabeledScale()
var = x._variable._name
x.destroy()
self.failUnlessRaises(tkinter.TclError, x.tk.globalgetvar, var)
# manually created variable
myvar = tkinter.DoubleVar()
name = myvar._name
x = ttk.LabeledScale(variable=myvar)
x.destroy()
self.failUnlessEqual(x.tk.globalgetvar(name), myvar.get())
del myvar
self.failUnlessRaises(tkinter.TclError, x.tk.globalgetvar, name)
# checking that the tracing callback is properly removed
myvar = tkinter.IntVar()
# LabeledScale will start tracing myvar
x = ttk.LabeledScale(variable=myvar)
x.destroy()
# Unless the tracing callback was removed, creating a new
# LabeledScale with the same var will cause an error now. This
# happens because the variable will be set to (possibly) a new
# value which causes the tracing callback to be called and then
# it tries calling instance attributes not yet defined.
ttk.LabeledScale(variable=myvar)
if hasattr(sys, 'last_type'):
self.failIf(sys.last_type == tkinter.TclError)
def test_initialization(self):
# master passing
x = ttk.LabeledScale()
self.failUnlessEqual(x.master, tkinter._default_root)
x.destroy()
master = tkinter.Frame()
x = ttk.LabeledScale(master)
self.failUnlessEqual(x.master, master)
x.destroy()
# variable initialization/passing
passed_expected = ((2.5, 2), ('0', 0), (0, 0), (10, 10),
(-1, -1), (sys.maxsize + 1, sys.maxsize + 1))
for pair in passed_expected:
x = ttk.LabeledScale(from_=pair[0])
self.failUnlessEqual(x.value, pair[1])
x.destroy()
x = ttk.LabeledScale(from_='2.5')
self.failUnlessRaises(ValueError, x._variable.get)
x.destroy()
x = ttk.LabeledScale(from_=None)
self.failUnlessRaises(ValueError, x._variable.get)
x.destroy()
# variable should have its default value set to the from_ value
myvar = tkinter.DoubleVar(value=20)
x = ttk.LabeledScale(variable=myvar)
self.failUnlessEqual(x.value, 0)
x.destroy()
# check that it is really using a DoubleVar
x = ttk.LabeledScale(variable=myvar, from_=0.5)
self.failUnlessEqual(x.value, 0.5)
self.failUnlessEqual(x._variable._name, myvar._name)
x.destroy()
# widget positionment
def check_positions(scale, scale_pos, label, label_pos):
self.failUnlessEqual(scale.pack_info()['side'], scale_pos)
self.failUnlessEqual(label.place_info()['anchor'], label_pos)
x = ttk.LabeledScale(compound='top')
check_positions(x.scale, 'bottom', x.label, 'n')
x.destroy()
x = ttk.LabeledScale(compound='bottom')
check_positions(x.scale, 'top', x.label, 's')
x.destroy()
x = ttk.LabeledScale(compound='unknown') # invert default positions
check_positions(x.scale, 'top', x.label, 's')
x.destroy()
x = ttk.LabeledScale() # take default positions
check_positions(x.scale, 'bottom', x.label, 'n')
x.destroy()
# extra, and invalid, kwargs
self.failUnlessRaises(tkinter.TclError, ttk.LabeledScale, a='b')
def test_horizontal_range(self):
lscale = ttk.LabeledScale(from_=0, to=10)
lscale.pack()
lscale.wait_visibility()
lscale.update()
linfo_1 = lscale.label.place_info()
prev_xcoord = lscale.scale.coords()[0]
self.failUnlessEqual(prev_xcoord, int(linfo_1['x']))
# change range to: from -5 to 5. This should change the x coord of
# the scale widget, since 0 is at the middle of the new
# range.
lscale.scale.configure(from_=-5, to=5)
# The following update is needed since the test doesn't use mainloop,
# at the same time this shouldn't affect test outcome
lscale.update()
curr_xcoord = lscale.scale.coords()[0]
self.failUnless(prev_xcoord != curr_xcoord)
# the label widget should have been repositioned too
linfo_2 = lscale.label.place_info()
self.failUnlessEqual(lscale.label['text'], 0)
self.failUnlessEqual(curr_xcoord, int(linfo_2['x']))
# change the range back
lscale.scale.configure(from_=0, to=10)
self.failUnless(prev_xcoord != curr_xcoord)
self.failUnlessEqual(prev_xcoord, int(linfo_1['x']))
lscale.destroy()
def test_variable_change(self):
x = ttk.LabeledScale()
x.pack()
x.wait_visibility()
x.update()
curr_xcoord = x.scale.coords()[0]
newval = x.value + 1
x.value = newval
# The following update is needed since the test doesn't use mainloop,
# at the same time this shouldn't affect test outcome
x.update()
self.failUnlessEqual(x.label['text'], newval)
self.failUnless(x.scale.coords()[0] > curr_xcoord)
self.failUnlessEqual(x.scale.coords()[0],
int(x.label.place_info()['x']))
# value outside range
x.value = x.scale['to'] + 1 # no changes shouldn't happen
x.update()
self.failUnlessEqual(x.label['text'], newval)
self.failUnlessEqual(x.scale.coords()[0],
int(x.label.place_info()['x']))
x.destroy()
def test_resize(self):
x = ttk.LabeledScale()
x.pack(expand=True, fill='both')
x.wait_visibility()
x.update()
width, height = x.master.winfo_width(), x.master.winfo_height()
width, height = width * 2, height * 2
x.value = 3
x.update()
x.master.wm_geometry("%dx%d" % (width, height))
self.failUnlessEqual(int(x.label.place_info()['x']),
x.scale.coords()[0])
x.master.wm_geometry("%dx%d" % (width, height))
x.destroy()
class OptionMenuTest(unittest.TestCase):
def setUp(self):
self.root = support.get_tk_root()
self.textvar = tkinter.StringVar(self.root)
def tearDown(self):
del self.textvar
self.root.destroy()
def test_widget_destroy(self):
var = tkinter.StringVar()
optmenu = ttk.OptionMenu(None, var)
name = var._name
optmenu.update_idletasks()
optmenu.destroy()
self.failUnlessEqual(optmenu.tk.globalgetvar(name), var.get())
del var
self.failUnlessRaises(tkinter.TclError, optmenu.tk.globalgetvar, name)
def test_initialization(self):
self.failUnlessRaises(tkinter.TclError,
ttk.OptionMenu, None, self.textvar, invalid='thing')
optmenu = ttk.OptionMenu(None, self.textvar, 'b', 'a', 'b')
self.failUnlessEqual(optmenu._variable.get(), 'b')
self.failUnless(optmenu['menu'])
self.failUnless(optmenu['textvariable'])
optmenu.destroy()
def test_menu(self):
items = ('a', 'b', 'c')
default = 'a'
optmenu = ttk.OptionMenu(None, self.textvar, default, *items)
found_default = False
for i in range(len(items)):
value = optmenu['menu'].entrycget(i, 'value')
self.failUnlessEqual(value, items[i])
if value == default:
found_default = True
self.failUnless(found_default)
optmenu.destroy()
# default shouldn't be in menu if it is not part of values
default = 'd'
optmenu = ttk.OptionMenu(None, self.textvar, default, *items)
curr = None
i = 0
while True:
last, curr = curr, optmenu['menu'].entryconfigure(i, 'value')
if last == curr:
# no more menu entries
break
self.failIf(curr == default)
i += 1
self.failUnlessEqual(i, len(items))
# check that variable is updated correctly
optmenu.pack()
optmenu.wait_visibility()
optmenu['menu'].invoke(0)
self.failUnlessEqual(optmenu._variable.get(), items[0])
# changing to an invalid index shouldn't change the variable
self.failUnlessRaises(tkinter.TclError, optmenu['menu'].invoke, -1)
self.failUnlessEqual(optmenu._variable.get(), items[0])
optmenu.destroy()
# specifying a callback
success = []
def cb_test(item):
self.failUnlessEqual(item, items[1])
success.append(True)
optmenu = ttk.OptionMenu(None, self.textvar, 'a', command=cb_test,
*items)
optmenu['menu'].invoke(1)
if not success:
self.fail("Menu callback not invoked")
optmenu.destroy()
tests_gui = (LabeledScaleTest, OptionMenuTest)
if __name__ == "__main__":
run_unittest(*tests_gui)

View File

@ -0,0 +1,423 @@
# -*- encoding: utf-8 -*-
import unittest
from tkinter import ttk
class MockTclObj(object):
typename = 'test'
def __init__(self, val):
self.val = val
def __str__(self):
return str(self.val)
class MockStateSpec(object):
typename = 'StateSpec'
def __init__(self, *args):
self.val = args
def __str__(self):
return ' '.join(self.val)
class InternalFunctionsTest(unittest.TestCase):
def test_format_optdict(self):
def check_against(fmt_opts, result):
for i in range(0, len(fmt_opts), 2):
self.failUnlessEqual(result.pop(fmt_opts[i]), fmt_opts[i + 1])
if result:
self.fail("result still got elements: %s" % result)
# passing an empty dict should return an empty object (tuple here)
self.failIf(ttk._format_optdict({}))
# check list formatting
check_against(
ttk._format_optdict({'fg': 'blue', 'padding': [1, 2, 3, 4]}),
{'-fg': 'blue', '-padding': '1 2 3 4'})
# check tuple formatting (same as list)
check_against(
ttk._format_optdict({'test': (1, 2, '', 0)}),
{'-test': '1 2 {} 0'})
# check untouched values
check_against(
ttk._format_optdict({'test': {'left': 'as is'}}),
{'-test': {'left': 'as is'}})
# check script formatting and untouched value(s)
check_against(
ttk._format_optdict(
{'test': [1, -1, '', '2m', 0], 'nochange1': 3,
'nochange2': 'abc def'}, script=True),
{'-test': '{1 -1 {} 2m 0}', '-nochange1': 3,
'-nochange2': 'abc def' })
opts = {'αβγ': True, 'á': False}
orig_opts = opts.copy()
# check if giving unicode keys is fine
check_against(ttk._format_optdict(opts), {'-αβγ': True, '': False})
# opts should remain unchanged
self.failUnlessEqual(opts, orig_opts)
# passing values with spaces inside a tuple/list
check_against(
ttk._format_optdict(
{'option': ('one two', 'three')}),
{'-option': '{one two} three'})
# ignore an option
amount_opts = len(ttk._format_optdict(opts, ignore=('á'))) / 2
self.failUnlessEqual(amount_opts, len(opts) - 1)
# ignore non-existing options
amount_opts = len(ttk._format_optdict(opts, ignore=('á', 'b'))) / 2
self.failUnlessEqual(amount_opts, len(opts) - 1)
# ignore every option
self.failIf(ttk._format_optdict(opts, ignore=list(opts.keys())))
def test_format_mapdict(self):
opts = {'a': [('b', 'c', 'val'), ('d', 'otherval'), ('', 'single')]}
result = ttk._format_mapdict(opts)
self.failUnlessEqual(len(result), len(list(opts.keys())) * 2)
self.failUnlessEqual(result, ('-a', '{b c} val d otherval {} single'))
self.failUnlessEqual(ttk._format_mapdict(opts, script=True),
('-a', '{{b c} val d otherval {} single}'))
self.failUnlessEqual(ttk._format_mapdict({2: []}), ('-2', ''))
opts = {'üñíćódè': [('á', 'vãl')]}
result = ttk._format_mapdict(opts)
self.failUnlessEqual(result, ('-üñíćódè', 'á vãl'))
# empty states
valid = {'opt': [('', '', 'hi')]}
self.failUnlessEqual(ttk._format_mapdict(valid), ('-opt', '{ } hi'))
# when passing multiple states, they all must be strings
invalid = {'opt': [(1, 2, 'valid val')]}
self.failUnlessRaises(TypeError, ttk._format_mapdict, invalid)
invalid = {'opt': [([1], '2', 'valid val')]}
self.failUnlessRaises(TypeError, ttk._format_mapdict, invalid)
# but when passing a single state, it can be anything
valid = {'opt': [[1, 'value']]}
self.failUnlessEqual(ttk._format_mapdict(valid), ('-opt', '1 value'))
# special attention to single states which evalute to False
for stateval in (None, 0, False, '', set()): # just some samples
valid = {'opt': [(stateval, 'value')]}
self.failUnlessEqual(ttk._format_mapdict(valid),
('-opt', '{} value'))
# values must be iterable
opts = {'a': None}
self.failUnlessRaises(TypeError, ttk._format_mapdict, opts)
# items in the value must have size >= 2
self.failUnlessRaises(IndexError, ttk._format_mapdict,
{'a': [('invalid', )]})
def test_format_elemcreate(self):
self.failUnless(ttk._format_elemcreate(None), (None, ()))
## Testing type = image
# image type expects at least an image name, so this should raise
# IndexError since it tries to access the index 0 of an empty tuple
self.failUnlessRaises(IndexError, ttk._format_elemcreate, 'image')
# don't format returned values as a tcl script
# minimum acceptable for image type
self.failUnlessEqual(ttk._format_elemcreate('image', False, 'test'),
("test ", ()))
# specifiyng a state spec
self.failUnlessEqual(ttk._format_elemcreate('image', False, 'test',
('', 'a')), ("test {} a", ()))
# state spec with multiple states
self.failUnlessEqual(ttk._format_elemcreate('image', False, 'test',
('a', 'b', 'c')), ("test {a b} c", ()))
# state spec and options
self.failUnlessEqual(ttk._format_elemcreate('image', False, 'test',
('a', 'b'), a='x', b='y'), ("test a b", ("-a", "x", "-b", "y")))
# format returned values as a tcl script
# state spec with multiple states and an option with a multivalue
self.failUnlessEqual(ttk._format_elemcreate('image', True, 'test',
('a', 'b', 'c', 'd'), x=[2, 3]), ("{test {a b c} d}", "-x {2 3}"))
## Testing type = vsapi
# vsapi type expects at least a class name and a part_id, so this
# should raise an ValueError since it tries to get two elements from
# an empty tuple
self.failUnlessRaises(ValueError, ttk._format_elemcreate, 'vsapi')
# don't format returned values as a tcl script
# minimum acceptable for vsapi
self.failUnlessEqual(ttk._format_elemcreate('vsapi', False, 'a', 'b'),
("a b ", ()))
# now with a state spec with multiple states
self.failUnlessEqual(ttk._format_elemcreate('vsapi', False, 'a', 'b',
('a', 'b', 'c')), ("a b {a b} c", ()))
# state spec and option
self.failUnlessEqual(ttk._format_elemcreate('vsapi', False, 'a', 'b',
('a', 'b'), opt='x'), ("a b a b", ("-opt", "x")))
# format returned values as a tcl script
# state spec with a multivalue and an option
self.failUnlessEqual(ttk._format_elemcreate('vsapi', True, 'a', 'b',
('a', 'b', [1, 2]), opt='x'), ("{a b {a b} {1 2}}", "-opt x"))
# Testing type = from
# from type expects at least a type name
self.failUnlessRaises(IndexError, ttk._format_elemcreate, 'from')
self.failUnlessEqual(ttk._format_elemcreate('from', False, 'a'),
('a', ()))
self.failUnlessEqual(ttk._format_elemcreate('from', False, 'a', 'b'),
('a', ('b', )))
self.failUnlessEqual(ttk._format_elemcreate('from', True, 'a', 'b'),
('{a}', 'b'))
def test_format_layoutlist(self):
def sample(indent=0, indent_size=2):
return ttk._format_layoutlist(
[('a', {'other': [1, 2, 3], 'children':
[('b', {'children':
[('c', {'children':
[('d', {'nice': 'opt'})], 'something': (1, 2)
})]
})]
})], indent=indent, indent_size=indent_size)[0]
def sample_expected(indent=0, indent_size=2):
spaces = lambda amount=0: ' ' * (amount + indent)
return (
"%sa -other {1 2 3} -children {\n"
"%sb -children {\n"
"%sc -something {1 2} -children {\n"
"%sd -nice opt\n"
"%s}\n"
"%s}\n"
"%s}" % (spaces(), spaces(indent_size),
spaces(2 * indent_size), spaces(3 * indent_size),
spaces(2 * indent_size), spaces(indent_size), spaces()))
# empty layout
self.failUnlessEqual(ttk._format_layoutlist([])[0], '')
# _format_layoutlist always expects the second item (in every item)
# to act like a dict (except when the value evalutes to False).
self.failUnlessRaises(AttributeError,
ttk._format_layoutlist, [('a', 'b')])
smallest = ttk._format_layoutlist([('a', None)], indent=0)
self.failUnlessEqual(smallest,
ttk._format_layoutlist([('a', '')], indent=0))
self.failUnlessEqual(smallest[0], 'a')
# testing indentation levels
self.failUnlessEqual(sample(), sample_expected())
for i in range(4):
self.failUnlessEqual(sample(i), sample_expected(i))
self.failUnlessEqual(sample(i, i), sample_expected(i, i))
# invalid layout format, different kind of exceptions will be
# raised by internal functions
# plain wrong format
self.failUnlessRaises(ValueError, ttk._format_layoutlist,
['bad', 'format'])
# will try to use iteritems in the 'bad' string
self.failUnlessRaises(AttributeError, ttk._format_layoutlist,
[('name', 'bad')])
# bad children formatting
self.failUnlessRaises(ValueError, ttk._format_layoutlist,
[('name', {'children': {'a': None}})])
def test_script_from_settings(self):
# empty options
self.failIf(ttk._script_from_settings({'name':
{'configure': None, 'map': None, 'element create': None}}))
# empty layout
self.failUnlessEqual(
ttk._script_from_settings({'name': {'layout': None}}),
"ttk::style layout name {\nnull\n}")
configdict = {'αβγ': True, 'á': False}
self.failUnless(
ttk._script_from_settings({'name': {'configure': configdict}}))
mapdict = {'üñíćódè': [('á', 'vãl')]}
self.failUnless(
ttk._script_from_settings({'name': {'map': mapdict}}))
# invalid image element
self.failUnlessRaises(IndexError,
ttk._script_from_settings, {'name': {'element create': ['image']}})
# minimal valid image
self.failUnless(ttk._script_from_settings({'name':
{'element create': ['image', 'name']}}))
image = {'thing': {'element create':
['image', 'name', ('state1', 'state2', 'val')]}}
self.failUnlessEqual(ttk._script_from_settings(image),
"ttk::style element create thing image {name {state1 state2} val} ")
image['thing']['element create'].append({'opt': 30})
self.failUnlessEqual(ttk._script_from_settings(image),
"ttk::style element create thing image {name {state1 state2} val} "
"-opt 30")
image['thing']['element create'][-1]['opt'] = [MockTclObj(3),
MockTclObj('2m')]
self.failUnlessEqual(ttk._script_from_settings(image),
"ttk::style element create thing image {name {state1 state2} val} "
"-opt {3 2m}")
def test_dict_from_tcltuple(self):
fakettuple = ('-a', '{1 2 3}', '-something', 'foo')
self.failUnlessEqual(ttk._dict_from_tcltuple(fakettuple, False),
{'-a': '{1 2 3}', '-something': 'foo'})
self.failUnlessEqual(ttk._dict_from_tcltuple(fakettuple),
{'a': '{1 2 3}', 'something': 'foo'})
# passing a tuple with a single item should return an empty dict,
# since it tries to break the tuple by pairs.
self.failIf(ttk._dict_from_tcltuple(('single', )))
sspec = MockStateSpec('a', 'b')
self.failUnlessEqual(ttk._dict_from_tcltuple(('-a', (sspec, 'val'))),
{'a': [('a', 'b', 'val')]})
self.failUnlessEqual(ttk._dict_from_tcltuple((MockTclObj('-padding'),
[MockTclObj('1'), 2, MockTclObj('3m')])),
{'padding': [1, 2, '3m']})
def test_list_from_statespec(self):
def test_it(sspec, value, res_value, states):
self.failUnlessEqual(ttk._list_from_statespec(
(sspec, value)), [states + (res_value, )])
states_even = tuple('state%d' % i for i in range(6))
statespec = MockStateSpec(*states_even)
test_it(statespec, 'val', 'val', states_even)
test_it(statespec, MockTclObj('val'), 'val', states_even)
states_odd = tuple('state%d' % i for i in range(5))
statespec = MockStateSpec(*states_odd)
test_it(statespec, 'val', 'val', states_odd)
test_it(('a', 'b', 'c'), MockTclObj('val'), 'val', ('a', 'b', 'c'))
def test_list_from_layouttuple(self):
# empty layout tuple
self.failIf(ttk._list_from_layouttuple(()))
# shortest layout tuple
self.failUnlessEqual(ttk._list_from_layouttuple(('name', )),
[('name', {})])
# not so interesting ltuple
sample_ltuple = ('name', '-option', 'value')
self.failUnlessEqual(ttk._list_from_layouttuple(sample_ltuple),
[('name', {'option': 'value'})])
# empty children
self.failUnlessEqual(ttk._list_from_layouttuple(
('something', '-children', ())),
[('something', {'children': []})]
)
# more interesting ltuple
ltuple = (
'name', '-option', 'niceone', '-children', (
('otherone', '-children', (
('child', )), '-otheropt', 'othervalue'
)
)
)
self.failUnlessEqual(ttk._list_from_layouttuple(ltuple),
[('name', {'option': 'niceone', 'children':
[('otherone', {'otheropt': 'othervalue', 'children':
[('child', {})]
})]
})]
)
# bad tuples
self.failUnlessRaises(ValueError, ttk._list_from_layouttuple,
('name', 'no_minus'))
self.failUnlessRaises(ValueError, ttk._list_from_layouttuple,
('name', 'no_minus', 'value'))
self.failUnlessRaises(ValueError, ttk._list_from_layouttuple,
('something', '-children')) # no children
self.failUnlessRaises(ValueError, ttk._list_from_layouttuple,
('something', '-children', 'value')) # invalid children
def test_val_or_dict(self):
def func(opt, val=None):
if val is None:
return "test val"
return (opt, val)
options = {'test': None}
self.failUnlessEqual(ttk._val_or_dict(options, func), "test val")
options = {'test': 3}
self.failUnlessEqual(ttk._val_or_dict(options, func), options)
def test_convert_stringval(self):
tests = (
(0, 0), ('09', 9), ('a', 'a'), ('áÚ', 'áÚ'), ([], '[]'),
(None, 'None')
)
for orig, expected in tests:
self.failUnlessEqual(ttk._convert_stringval(orig), expected)
class TclObjsToPyTest(unittest.TestCase):
def test_unicode(self):
adict = {'opt': 'välúè'}
self.failUnlessEqual(ttk.tclobjs_to_py(adict), {'opt': 'välúè'})
adict['opt'] = MockTclObj(adict['opt'])
self.failUnlessEqual(ttk.tclobjs_to_py(adict), {'opt': 'välúè'})
def test_multivalues(self):
adict = {'opt': [1, 2, 3, 4]}
self.failUnlessEqual(ttk.tclobjs_to_py(adict), {'opt': [1, 2, 3, 4]})
adict['opt'] = [1, 'xm', 3]
self.failUnlessEqual(ttk.tclobjs_to_py(adict), {'opt': [1, 'xm', 3]})
adict['opt'] = (MockStateSpec('a', 'b'), 'válũè')
self.failUnlessEqual(ttk.tclobjs_to_py(adict),
{'opt': [('a', 'b', 'válũè')]})
self.failUnlessEqual(ttk.tclobjs_to_py({'x': ['y z']}),
{'x': ['y z']})
def test_nosplit(self):
self.failUnlessEqual(ttk.tclobjs_to_py({'text': 'some text'}),
{'text': 'some text'})
tests_nogui = (InternalFunctionsTest, TclObjsToPyTest)
if __name__ == "__main__":
from test.support import run_unittest
run_unittest(*tests_nogui)

View File

@ -0,0 +1,99 @@
import unittest
import tkinter
from tkinter import ttk
from test.support import requires, run_unittest
import tkinter.test.support as support
requires('gui')
class StyleTest(unittest.TestCase):
def setUp(self):
self.root = support.get_tk_root()
self.style = ttk.Style(self.root)
def tearDown(self):
# As tests have shown, these tests are likely to deliver
# <<ThemeChanged>> events after the root is destroyed, so
# lets let them happen now.
self.root.update_idletasks()
self.root.destroy()
def test_configure(self):
style = self.style
style.configure('TButton', background='yellow')
self.failUnlessEqual(style.configure('TButton', 'background'),
'yellow')
self.failUnless(isinstance(style.configure('TButton'), dict))
def test_map(self):
style = self.style
style.map('TButton', background=[('active', 'background', 'blue')])
self.failUnlessEqual(style.map('TButton', 'background'),
[('active', 'background', 'blue')])
self.failUnless(isinstance(style.map('TButton'), dict))
def test_lookup(self):
style = self.style
style.configure('TButton', background='yellow')
style.map('TButton', background=[('active', 'background', 'blue')])
self.failUnlessEqual(style.lookup('TButton', 'background'), 'yellow')
self.failUnlessEqual(style.lookup('TButton', 'background',
['active', 'background']), 'blue')
self.failUnlessEqual(style.lookup('TButton', 'optionnotdefined',
default='iknewit'), 'iknewit')
def test_layout(self):
style = self.style
self.failUnlessRaises(tkinter.TclError, style.layout, 'NotALayout')
tv_style = style.layout('Treeview')
# "erase" Treeview layout
style.layout('Treeview', '')
self.failUnlessEqual(style.layout('Treeview'),
[('null', {'sticky': 'nswe'})]
)
# restore layout
style.layout('Treeview', tv_style)
self.failUnlessEqual(style.layout('Treeview'), tv_style)
# should return a list
self.failUnless(isinstance(style.layout('TButton'), list))
# correct layout, but "option" doesn't exist as option
self.failUnlessRaises(tkinter.TclError, style.layout, 'Treeview',
[('name', {'option': 'inexistant'})])
def test_theme_use(self):
self.failUnlessRaises(tkinter.TclError, self.style.theme_use,
'nonexistingname')
curr_theme = self.style.theme_use()
new_theme = None
for theme in self.style.theme_names():
if theme != curr_theme:
new_theme = theme
self.style.theme_use(theme)
break
else:
# just one theme available, can't go on with tests
return
self.failIf(curr_theme == new_theme)
self.failIf(new_theme != self.style.theme_use())
self.style.theme_use(curr_theme)
tests_gui = (StyleTest, )
if __name__ == "__main__":
run_unittest(*tests_gui)

File diff suppressed because it is too large Load Diff

1636
Lib/tkinter/ttk.py Normal file

File diff suppressed because it is too large Load Diff

View File

@ -144,6 +144,8 @@ Core and Builtins
Library
-------
- Added the ttk module. See issue #2983: Ttk support for Tkinter.
- Removed isSequenceType(), isMappingType, and isNumberType() from the
operator module; use the abstract base classes instead. Also removed
the repeat() function; use mul() instead.