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