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