• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1import functools
2import re
3import tkinter
4import unittest
5
6class AbstractTkTest:
7
8    @classmethod
9    def setUpClass(cls):
10        cls._old_support_default_root = tkinter._support_default_root
11        destroy_default_root()
12        tkinter.NoDefaultRoot()
13        cls.root = tkinter.Tk()
14        cls.wantobjects = cls.root.wantobjects()
15        # De-maximize main window.
16        # Some window managers can maximize new windows.
17        cls.root.wm_state('normal')
18        try:
19            cls.root.wm_attributes('-zoomed', False)
20        except tkinter.TclError:
21            pass
22
23    @classmethod
24    def tearDownClass(cls):
25        cls.root.update_idletasks()
26        cls.root.destroy()
27        del cls.root
28        tkinter._default_root = None
29        tkinter._support_default_root = cls._old_support_default_root
30
31    def setUp(self):
32        self.root.deiconify()
33
34    def tearDown(self):
35        for w in self.root.winfo_children():
36            w.destroy()
37        self.root.withdraw()
38
39
40class AbstractDefaultRootTest:
41
42    def setUp(self):
43        self._old_support_default_root = tkinter._support_default_root
44        destroy_default_root()
45        tkinter._support_default_root = True
46        self.wantobjects = tkinter.wantobjects
47
48    def tearDown(self):
49        destroy_default_root()
50        tkinter._default_root = None
51        tkinter._support_default_root = self._old_support_default_root
52
53    def _test_widget(self, constructor):
54        # no master passing
55        x = constructor()
56        self.assertIsNotNone(tkinter._default_root)
57        self.assertIs(x.master, tkinter._default_root)
58        self.assertIs(x.tk, tkinter._default_root.tk)
59        x.destroy()
60        destroy_default_root()
61        tkinter.NoDefaultRoot()
62        self.assertRaises(RuntimeError, constructor)
63        self.assertFalse(hasattr(tkinter, '_default_root'))
64
65
66def destroy_default_root():
67    if getattr(tkinter, '_default_root', None):
68        tkinter._default_root.update_idletasks()
69        tkinter._default_root.destroy()
70        tkinter._default_root = None
71
72def simulate_mouse_click(widget, x, y):
73    """Generate proper events to click at the x, y position (tries to act
74    like an X server)."""
75    widget.event_generate('<Enter>', x=0, y=0)
76    widget.event_generate('<Motion>', x=x, y=y)
77    widget.event_generate('<ButtonPress-1>', x=x, y=y)
78    widget.event_generate('<ButtonRelease-1>', x=x, y=y)
79
80
81import _tkinter
82tcl_version = tuple(map(int, _tkinter.TCL_VERSION.split('.')))
83
84def requires_tcl(*version):
85    if len(version) <= 2:
86        return unittest.skipUnless(tcl_version >= version,
87            'requires Tcl version >= ' + '.'.join(map(str, version)))
88
89    def deco(test):
90        @functools.wraps(test)
91        def newtest(self):
92            if get_tk_patchlevel() < version:
93                self.skipTest('requires Tcl version >= ' +
94                                '.'.join(map(str, version)))
95            test(self)
96        return newtest
97    return deco
98
99_tk_patchlevel = None
100def get_tk_patchlevel():
101    global _tk_patchlevel
102    if _tk_patchlevel is None:
103        tcl = tkinter.Tcl()
104        patchlevel = tcl.call('info', 'patchlevel')
105        m = re.fullmatch(r'(\d+)\.(\d+)([ab.])(\d+)', patchlevel)
106        major, minor, releaselevel, serial = m.groups()
107        major, minor, serial = int(major), int(minor), int(serial)
108        releaselevel = {'a': 'alpha', 'b': 'beta', '.': 'final'}[releaselevel]
109        if releaselevel == 'final':
110            _tk_patchlevel = major, minor, serial, releaselevel, 0
111        else:
112            _tk_patchlevel = major, minor, 0, releaselevel, serial
113    return _tk_patchlevel
114
115units = {
116    'c': 72 / 2.54,     # centimeters
117    'i': 72,            # inches
118    'm': 72 / 25.4,     # millimeters
119    'p': 1,             # points
120}
121
122def pixels_conv(value):
123    return float(value[:-1]) * units[value[-1:]]
124
125def tcl_obj_eq(actual, expected):
126    if actual == expected:
127        return True
128    if isinstance(actual, _tkinter.Tcl_Obj):
129        if isinstance(expected, str):
130            return str(actual) == expected
131    if isinstance(actual, tuple):
132        if isinstance(expected, tuple):
133            return (len(actual) == len(expected) and
134                    all(tcl_obj_eq(act, exp)
135                        for act, exp in zip(actual, expected)))
136    return False
137
138def widget_eq(actual, expected):
139    if actual == expected:
140        return True
141    if isinstance(actual, (str, tkinter.Widget)):
142        if isinstance(expected, (str, tkinter.Widget)):
143            return str(actual) == str(expected)
144    return False
145