1import functools 2import unittest 3import tkinter 4from test import support 5from tkinter.test.support import AbstractTkTest, AbstractDefaultRootTest 6 7support.requires('gui') 8 9class MiscTest(AbstractTkTest, unittest.TestCase): 10 11 def test_all(self): 12 self.assertIn("Widget", tkinter.__all__) 13 # Check that variables from tkinter.constants are also in tkinter.__all__ 14 self.assertIn("CASCADE", tkinter.__all__) 15 self.assertIsNotNone(tkinter.CASCADE) 16 # Check that sys, re, and constants are not in tkinter.__all__ 17 self.assertNotIn("re", tkinter.__all__) 18 self.assertNotIn("sys", tkinter.__all__) 19 self.assertNotIn("constants", tkinter.__all__) 20 # Check that an underscored functions is not in tkinter.__all__ 21 self.assertNotIn("_tkerror", tkinter.__all__) 22 # Check that wantobjects is not in tkinter.__all__ 23 self.assertNotIn("wantobjects", tkinter.__all__) 24 25 def test_repr(self): 26 t = tkinter.Toplevel(self.root, name='top') 27 f = tkinter.Frame(t, name='child') 28 self.assertEqual(repr(f), '<tkinter.Frame object .top.child>') 29 30 def test_generated_names(self): 31 t = tkinter.Toplevel(self.root) 32 f = tkinter.Frame(t) 33 f2 = tkinter.Frame(t) 34 b = tkinter.Button(f2) 35 for name in str(b).split('.'): 36 self.assertFalse(name.isidentifier(), msg=repr(name)) 37 38 def test_tk_setPalette(self): 39 root = self.root 40 root.tk_setPalette('black') 41 self.assertEqual(root['background'], 'black') 42 root.tk_setPalette('white') 43 self.assertEqual(root['background'], 'white') 44 self.assertRaisesRegex(tkinter.TclError, 45 '^unknown color name "spam"$', 46 root.tk_setPalette, 'spam') 47 48 root.tk_setPalette(background='black') 49 self.assertEqual(root['background'], 'black') 50 root.tk_setPalette(background='blue', highlightColor='yellow') 51 self.assertEqual(root['background'], 'blue') 52 self.assertEqual(root['highlightcolor'], 'yellow') 53 root.tk_setPalette(background='yellow', highlightColor='blue') 54 self.assertEqual(root['background'], 'yellow') 55 self.assertEqual(root['highlightcolor'], 'blue') 56 self.assertRaisesRegex(tkinter.TclError, 57 '^unknown color name "spam"$', 58 root.tk_setPalette, background='spam') 59 self.assertRaisesRegex(tkinter.TclError, 60 '^must specify a background color$', 61 root.tk_setPalette, spam='white') 62 self.assertRaisesRegex(tkinter.TclError, 63 '^must specify a background color$', 64 root.tk_setPalette, highlightColor='blue') 65 66 def test_after(self): 67 root = self.root 68 69 def callback(start=0, step=1): 70 nonlocal count 71 count = start + step 72 73 # Without function, sleeps for ms. 74 self.assertIsNone(root.after(1)) 75 76 # Set up with callback with no args. 77 count = 0 78 timer1 = root.after(0, callback) 79 self.assertIn(timer1, root.tk.call('after', 'info')) 80 (script, _) = root.tk.splitlist(root.tk.call('after', 'info', timer1)) 81 root.update() # Process all pending events. 82 self.assertEqual(count, 1) 83 with self.assertRaises(tkinter.TclError): 84 root.tk.call(script) 85 86 # Set up with callback with args. 87 count = 0 88 timer1 = root.after(0, callback, 42, 11) 89 root.update() # Process all pending events. 90 self.assertEqual(count, 53) 91 92 # Cancel before called. 93 timer1 = root.after(1000, callback) 94 self.assertIn(timer1, root.tk.call('after', 'info')) 95 (script, _) = root.tk.splitlist(root.tk.call('after', 'info', timer1)) 96 root.after_cancel(timer1) # Cancel this event. 97 self.assertEqual(count, 53) 98 with self.assertRaises(tkinter.TclError): 99 root.tk.call(script) 100 101 # Call with a callable class 102 count = 0 103 timer1 = root.after(0, functools.partial(callback, 42, 11)) 104 root.update() # Process all pending events. 105 self.assertEqual(count, 53) 106 107 def test_after_idle(self): 108 root = self.root 109 110 def callback(start=0, step=1): 111 nonlocal count 112 count = start + step 113 114 # Set up with callback with no args. 115 count = 0 116 idle1 = root.after_idle(callback) 117 self.assertIn(idle1, root.tk.call('after', 'info')) 118 (script, _) = root.tk.splitlist(root.tk.call('after', 'info', idle1)) 119 root.update_idletasks() # Process all pending events. 120 self.assertEqual(count, 1) 121 with self.assertRaises(tkinter.TclError): 122 root.tk.call(script) 123 124 # Set up with callback with args. 125 count = 0 126 idle1 = root.after_idle(callback, 42, 11) 127 root.update_idletasks() # Process all pending events. 128 self.assertEqual(count, 53) 129 130 # Cancel before called. 131 idle1 = root.after_idle(callback) 132 self.assertIn(idle1, root.tk.call('after', 'info')) 133 (script, _) = root.tk.splitlist(root.tk.call('after', 'info', idle1)) 134 root.after_cancel(idle1) # Cancel this event. 135 self.assertEqual(count, 53) 136 with self.assertRaises(tkinter.TclError): 137 root.tk.call(script) 138 139 def test_after_cancel(self): 140 root = self.root 141 142 def callback(): 143 nonlocal count 144 count += 1 145 146 timer1 = root.after(5000, callback) 147 idle1 = root.after_idle(callback) 148 149 # No value for id raises a ValueError. 150 with self.assertRaises(ValueError): 151 root.after_cancel(None) 152 153 # Cancel timer event. 154 count = 0 155 (script, _) = root.tk.splitlist(root.tk.call('after', 'info', timer1)) 156 root.tk.call(script) 157 self.assertEqual(count, 1) 158 root.after_cancel(timer1) 159 with self.assertRaises(tkinter.TclError): 160 root.tk.call(script) 161 self.assertEqual(count, 1) 162 with self.assertRaises(tkinter.TclError): 163 root.tk.call('after', 'info', timer1) 164 165 # Cancel same event - nothing happens. 166 root.after_cancel(timer1) 167 168 # Cancel idle event. 169 count = 0 170 (script, _) = root.tk.splitlist(root.tk.call('after', 'info', idle1)) 171 root.tk.call(script) 172 self.assertEqual(count, 1) 173 root.after_cancel(idle1) 174 with self.assertRaises(tkinter.TclError): 175 root.tk.call(script) 176 self.assertEqual(count, 1) 177 with self.assertRaises(tkinter.TclError): 178 root.tk.call('after', 'info', idle1) 179 180 def test_clipboard(self): 181 root = self.root 182 root.clipboard_clear() 183 root.clipboard_append('Ùñî') 184 self.assertEqual(root.clipboard_get(), 'Ùñî') 185 root.clipboard_append('çōđě') 186 self.assertEqual(root.clipboard_get(), 'Ùñîçōđě') 187 root.clipboard_clear() 188 with self.assertRaises(tkinter.TclError): 189 root.clipboard_get() 190 191 def test_clipboard_astral(self): 192 root = self.root 193 root.clipboard_clear() 194 root.clipboard_append('') 195 self.assertEqual(root.clipboard_get(), '') 196 root.clipboard_append('') 197 self.assertEqual(root.clipboard_get(), '') 198 root.clipboard_clear() 199 with self.assertRaises(tkinter.TclError): 200 root.clipboard_get() 201 202 def test_winfo_rgb(self): 203 204 def assertApprox(col1, col2): 205 # A small amount of flexibility is required (bpo-45496) 206 # 33 is ~0.05% of 65535, which is a reasonable margin 207 for col1_channel, col2_channel in zip(col1, col2): 208 self.assertAlmostEqual(col1_channel, col2_channel, delta=33) 209 210 root = self.root 211 rgb = root.winfo_rgb 212 213 # Color name. 214 self.assertEqual(rgb('red'), (65535, 0, 0)) 215 self.assertEqual(rgb('dark slate blue'), (18504, 15677, 35723)) 216 # #RGB - extends each 4-bit hex value to be 16-bit. 217 self.assertEqual(rgb('#F0F'), (0xFFFF, 0x0000, 0xFFFF)) 218 # #RRGGBB - extends each 8-bit hex value to be 16-bit. 219 assertApprox(rgb('#4a3c8c'), (0x4a4a, 0x3c3c, 0x8c8c)) 220 # #RRRRGGGGBBBB 221 assertApprox(rgb('#dede14143939'), (0xdede, 0x1414, 0x3939)) 222 # Invalid string. 223 with self.assertRaises(tkinter.TclError): 224 rgb('#123456789a') 225 # RGB triplet is invalid input. 226 with self.assertRaises(tkinter.TclError): 227 rgb((111, 78, 55)) 228 229 def test_event_repr_defaults(self): 230 e = tkinter.Event() 231 e.serial = 12345 232 e.num = '??' 233 e.height = '??' 234 e.keycode = '??' 235 e.state = 0 236 e.time = 123456789 237 e.width = '??' 238 e.x = '??' 239 e.y = '??' 240 e.char = '' 241 e.keysym = '??' 242 e.keysym_num = '??' 243 e.type = '100' 244 e.widget = '??' 245 e.x_root = '??' 246 e.y_root = '??' 247 e.delta = 0 248 self.assertEqual(repr(e), '<100 event>') 249 250 def test_event_repr(self): 251 e = tkinter.Event() 252 e.serial = 12345 253 e.num = 3 254 e.focus = True 255 e.height = 200 256 e.keycode = 65 257 e.state = 0x30405 258 e.time = 123456789 259 e.width = 300 260 e.x = 10 261 e.y = 20 262 e.char = 'A' 263 e.send_event = True 264 e.keysym = 'Key-A' 265 e.keysym_num = ord('A') 266 e.type = tkinter.EventType.Configure 267 e.widget = '.text' 268 e.x_root = 1010 269 e.y_root = 1020 270 e.delta = -1 271 self.assertEqual(repr(e), 272 "<Configure event send_event=True" 273 " state=Shift|Control|Button3|0x30000" 274 " keysym=Key-A keycode=65 char='A'" 275 " num=3 delta=-1 focus=True" 276 " x=10 y=20 width=300 height=200>") 277 278 def test_getboolean(self): 279 for v in 'true', 'yes', 'on', '1', 't', 'y', 1, True: 280 self.assertIs(self.root.getboolean(v), True) 281 for v in 'false', 'no', 'off', '0', 'f', 'n', 0, False: 282 self.assertIs(self.root.getboolean(v), False) 283 self.assertRaises(ValueError, self.root.getboolean, 'yea') 284 self.assertRaises(ValueError, self.root.getboolean, '') 285 self.assertRaises(TypeError, self.root.getboolean, None) 286 self.assertRaises(TypeError, self.root.getboolean, ()) 287 288 def test_mainloop(self): 289 log = [] 290 def callback(): 291 log.append(1) 292 self.root.after(100, self.root.quit) 293 self.root.after(100, callback) 294 self.root.mainloop(1) 295 self.assertEqual(log, []) 296 self.root.mainloop(0) 297 self.assertEqual(log, [1]) 298 self.assertTrue(self.root.winfo_exists()) 299 300 301class DefaultRootTest(AbstractDefaultRootTest, unittest.TestCase): 302 303 def test_default_root(self): 304 self.assertIs(tkinter._support_default_root, True) 305 self.assertIsNone(tkinter._default_root) 306 root = tkinter.Tk() 307 root2 = tkinter.Tk() 308 root3 = tkinter.Tk() 309 self.assertIs(tkinter._default_root, root) 310 root2.destroy() 311 self.assertIs(tkinter._default_root, root) 312 root.destroy() 313 self.assertIsNone(tkinter._default_root) 314 root3.destroy() 315 self.assertIsNone(tkinter._default_root) 316 317 def test_no_default_root(self): 318 self.assertIs(tkinter._support_default_root, True) 319 self.assertIsNone(tkinter._default_root) 320 root = tkinter.Tk() 321 self.assertIs(tkinter._default_root, root) 322 tkinter.NoDefaultRoot() 323 self.assertIs(tkinter._support_default_root, False) 324 self.assertFalse(hasattr(tkinter, '_default_root')) 325 # repeated call is no-op 326 tkinter.NoDefaultRoot() 327 self.assertIs(tkinter._support_default_root, False) 328 self.assertFalse(hasattr(tkinter, '_default_root')) 329 root.destroy() 330 self.assertIs(tkinter._support_default_root, False) 331 self.assertFalse(hasattr(tkinter, '_default_root')) 332 root = tkinter.Tk() 333 self.assertIs(tkinter._support_default_root, False) 334 self.assertFalse(hasattr(tkinter, '_default_root')) 335 root.destroy() 336 337 def test_getboolean(self): 338 self.assertRaises(RuntimeError, tkinter.getboolean, '1') 339 root = tkinter.Tk() 340 self.assertIs(tkinter.getboolean('1'), True) 341 self.assertRaises(ValueError, tkinter.getboolean, 'yea') 342 root.destroy() 343 tkinter.NoDefaultRoot() 344 self.assertRaises(RuntimeError, tkinter.getboolean, '1') 345 346 def test_mainloop(self): 347 self.assertRaises(RuntimeError, tkinter.mainloop) 348 root = tkinter.Tk() 349 root.after_idle(root.quit) 350 tkinter.mainloop() 351 root.destroy() 352 tkinter.NoDefaultRoot() 353 self.assertRaises(RuntimeError, tkinter.mainloop) 354 355 356if __name__ == "__main__": 357 unittest.main() 358