Skip to content

Commit df53191

Browse files
[3.12] gh-75666: Tkinter: add tests for binding (GH-111202) (GH-111255)
(cherry picked from commit 9bb202a) Co-authored-by: Serhiy Storchaka <[email protected]>
1 parent 03c14b0 commit df53191

File tree

1 file changed

+307
-0
lines changed

1 file changed

+307
-0
lines changed

Lib/test/test_tkinter/test_misc.py

Lines changed: 307 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -371,6 +371,309 @@ def test_info_patchlevel(self):
371371
self.assertTrue(str(vi).startswith(f'{vi.major}.{vi.minor}'))
372372

373373

374+
class BindTest(AbstractTkTest, unittest.TestCase):
375+
376+
def setUp(self):
377+
super().setUp()
378+
root = self.root
379+
self.frame = tkinter.Frame(self.root, class_='Test',
380+
width=150, height=100)
381+
self.frame.pack()
382+
383+
def assertCommandExist(self, funcid):
384+
self.assertEqual(_info_commands(self.root, funcid), (funcid,))
385+
386+
def assertCommandNotExist(self, funcid):
387+
self.assertEqual(_info_commands(self.root, funcid), ())
388+
389+
def test_bind(self):
390+
event = '<Control-Alt-Key-a>'
391+
f = self.frame
392+
self.assertEqual(f.bind(), ())
393+
self.assertEqual(f.bind(event), '')
394+
def test1(e): pass
395+
def test2(e): pass
396+
397+
funcid = f.bind(event, test1)
398+
self.assertEqual(f.bind(), (event,))
399+
script = f.bind(event)
400+
self.assertIn(funcid, script)
401+
self.assertCommandExist(funcid)
402+
403+
funcid2 = f.bind(event, test2, add=True)
404+
script = f.bind(event)
405+
self.assertIn(funcid, script)
406+
self.assertIn(funcid2, script)
407+
self.assertCommandExist(funcid)
408+
self.assertCommandExist(funcid2)
409+
410+
def test_unbind(self):
411+
event = '<Control-Alt-Key-b>'
412+
f = self.frame
413+
self.assertEqual(f.bind(), ())
414+
self.assertEqual(f.bind(event), '')
415+
def test1(e): pass
416+
def test2(e): pass
417+
418+
funcid = f.bind(event, test1)
419+
funcid2 = f.bind(event, test2, add=True)
420+
421+
self.assertRaises(TypeError, f.unbind)
422+
f.unbind(event)
423+
self.assertEqual(f.bind(event), '')
424+
self.assertEqual(f.bind(), ())
425+
426+
def test_unbind2(self):
427+
f = self.frame
428+
event = '<Control-Alt-Key-c>'
429+
self.assertEqual(f.bind(), ())
430+
self.assertEqual(f.bind(event), '')
431+
def test1(e): pass
432+
def test2(e): pass
433+
434+
funcid = f.bind(event, test1)
435+
funcid2 = f.bind(event, test2, add=True)
436+
437+
f.unbind(event, funcid)
438+
script = f.bind(event)
439+
self.assertNotIn(funcid, script)
440+
self.assertCommandNotExist(funcid)
441+
self.assertCommandExist(funcid2)
442+
443+
f.unbind(event, funcid2)
444+
self.assertEqual(f.bind(event), '')
445+
self.assertEqual(f.bind(), ())
446+
self.assertCommandNotExist(funcid)
447+
self.assertCommandNotExist(funcid2)
448+
449+
# non-idempotent
450+
self.assertRaises(tkinter.TclError, f.unbind, event, funcid2)
451+
452+
def test_bind_rebind(self):
453+
event = '<Control-Alt-Key-d>'
454+
f = self.frame
455+
self.assertEqual(f.bind(), ())
456+
self.assertEqual(f.bind(event), '')
457+
def test1(e): pass
458+
def test2(e): pass
459+
def test3(e): pass
460+
461+
funcid = f.bind(event, test1)
462+
funcid2 = f.bind(event, test2, add=True)
463+
script = f.bind(event)
464+
self.assertIn(funcid2, script)
465+
self.assertIn(funcid, script)
466+
self.assertCommandExist(funcid)
467+
self.assertCommandExist(funcid2)
468+
469+
funcid3 = f.bind(event, test3)
470+
script = f.bind(event)
471+
self.assertNotIn(funcid, script)
472+
self.assertNotIn(funcid2, script)
473+
self.assertIn(funcid3, script)
474+
self.assertCommandExist(funcid3)
475+
476+
def test_bind_class(self):
477+
event = '<Control-Alt-Key-e>'
478+
bind_class = self.root.bind_class
479+
unbind_class = self.root.unbind_class
480+
self.assertRaises(TypeError, bind_class)
481+
self.assertEqual(bind_class('Test'), ())
482+
self.assertEqual(bind_class('Test', event), '')
483+
self.addCleanup(unbind_class, 'Test', event)
484+
def test1(e): pass
485+
def test2(e): pass
486+
487+
funcid = bind_class('Test', event, test1)
488+
self.assertEqual(bind_class('Test'), (event,))
489+
script = bind_class('Test', event)
490+
self.assertIn(funcid, script)
491+
self.assertCommandExist(funcid)
492+
493+
funcid2 = bind_class('Test', event, test2, add=True)
494+
script = bind_class('Test', event)
495+
self.assertIn(funcid, script)
496+
self.assertIn(funcid2, script)
497+
self.assertCommandExist(funcid)
498+
self.assertCommandExist(funcid2)
499+
500+
def test_unbind_class(self):
501+
event = '<Control-Alt-Key-f>'
502+
bind_class = self.root.bind_class
503+
unbind_class = self.root.unbind_class
504+
self.assertEqual(bind_class('Test'), ())
505+
self.assertEqual(bind_class('Test', event), '')
506+
self.addCleanup(unbind_class, 'Test', event)
507+
def test1(e): pass
508+
def test2(e): pass
509+
510+
funcid = bind_class('Test', event, test1)
511+
funcid2 = bind_class('Test', event, test2, add=True)
512+
513+
self.assertRaises(TypeError, unbind_class)
514+
self.assertRaises(TypeError, unbind_class, 'Test')
515+
unbind_class('Test', event)
516+
self.assertEqual(bind_class('Test', event), '')
517+
self.assertEqual(bind_class('Test'), ())
518+
self.assertCommandExist(funcid)
519+
self.assertCommandExist(funcid2)
520+
521+
unbind_class('Test', event) # idempotent
522+
523+
def test_bind_class_rebind(self):
524+
event = '<Control-Alt-Key-g>'
525+
bind_class = self.root.bind_class
526+
unbind_class = self.root.unbind_class
527+
self.assertEqual(bind_class('Test'), ())
528+
self.assertEqual(bind_class('Test', event), '')
529+
self.addCleanup(unbind_class, 'Test', event)
530+
def test1(e): pass
531+
def test2(e): pass
532+
def test3(e): pass
533+
534+
funcid = bind_class('Test', event, test1)
535+
funcid2 = bind_class('Test', event, test2, add=True)
536+
script = bind_class('Test', event)
537+
self.assertIn(funcid2, script)
538+
self.assertIn(funcid, script)
539+
self.assertCommandExist(funcid)
540+
self.assertCommandExist(funcid2)
541+
542+
funcid3 = bind_class('Test', event, test3)
543+
script = bind_class('Test', event)
544+
self.assertNotIn(funcid, script)
545+
self.assertNotIn(funcid2, script)
546+
self.assertIn(funcid3, script)
547+
self.assertCommandExist(funcid)
548+
self.assertCommandExist(funcid2)
549+
self.assertCommandExist(funcid3)
550+
551+
def test_bind_all(self):
552+
event = '<Control-Alt-Key-h>'
553+
bind_all = self.root.bind_all
554+
unbind_all = self.root.unbind_all
555+
self.assertNotIn(event, bind_all())
556+
self.assertEqual(bind_all(event), '')
557+
self.addCleanup(unbind_all, event)
558+
def test1(e): pass
559+
def test2(e): pass
560+
561+
funcid = bind_all(event, test1)
562+
self.assertIn(event, bind_all())
563+
script = bind_all(event)
564+
self.assertIn(funcid, script)
565+
self.assertCommandExist(funcid)
566+
567+
funcid2 = bind_all(event, test2, add=True)
568+
script = bind_all(event)
569+
self.assertIn(funcid, script)
570+
self.assertIn(funcid2, script)
571+
self.assertCommandExist(funcid)
572+
self.assertCommandExist(funcid2)
573+
574+
def test_unbind_all(self):
575+
event = '<Control-Alt-Key-i>'
576+
bind_all = self.root.bind_all
577+
unbind_all = self.root.unbind_all
578+
self.assertNotIn(event, bind_all())
579+
self.assertEqual(bind_all(event), '')
580+
self.addCleanup(unbind_all, event)
581+
def test1(e): pass
582+
def test2(e): pass
583+
584+
funcid = bind_all(event, test1)
585+
funcid2 = bind_all(event, test2, add=True)
586+
587+
unbind_all(event)
588+
self.assertEqual(bind_all(event), '')
589+
self.assertNotIn(event, bind_all())
590+
self.assertCommandExist(funcid)
591+
self.assertCommandExist(funcid2)
592+
593+
unbind_all(event) # idempotent
594+
595+
def test_bind_all_rebind(self):
596+
event = '<Control-Alt-Key-j>'
597+
bind_all = self.root.bind_all
598+
unbind_all = self.root.unbind_all
599+
self.assertNotIn(event, bind_all())
600+
self.assertEqual(bind_all(event), '')
601+
self.addCleanup(unbind_all, event)
602+
def test1(e): pass
603+
def test2(e): pass
604+
def test3(e): pass
605+
606+
funcid = bind_all(event, test1)
607+
funcid2 = bind_all(event, test2, add=True)
608+
script = bind_all(event)
609+
self.assertIn(funcid2, script)
610+
self.assertIn(funcid, script)
611+
self.assertCommandExist(funcid)
612+
self.assertCommandExist(funcid2)
613+
614+
funcid3 = bind_all(event, test3)
615+
script = bind_all(event)
616+
self.assertNotIn(funcid, script)
617+
self.assertNotIn(funcid2, script)
618+
self.assertIn(funcid3, script)
619+
self.assertCommandExist(funcid)
620+
self.assertCommandExist(funcid2)
621+
self.assertCommandExist(funcid3)
622+
623+
def test_bindtags(self):
624+
f = self.frame
625+
self.assertEqual(self.root.bindtags(), ('.', 'Tk', 'all'))
626+
self.assertEqual(f.bindtags(), (str(f), 'Test', '.', 'all'))
627+
f.bindtags(('a', 'b c'))
628+
self.assertEqual(f.bindtags(), ('a', 'b c'))
629+
630+
def test_bind_events(self):
631+
event = '<Enter>'
632+
root = self.root
633+
t = tkinter.Toplevel(root)
634+
f = tkinter.Frame(t, class_='Test', width=150, height=100)
635+
f.pack()
636+
root.wait_visibility() # needed on Windows
637+
root.update_idletasks()
638+
self.addCleanup(root.unbind_class, 'Test', event)
639+
self.addCleanup(root.unbind_class, 'Toplevel', event)
640+
self.addCleanup(root.unbind_class, 'tag', event)
641+
self.addCleanup(root.unbind_class, 'tag2', event)
642+
self.addCleanup(root.unbind_all, event)
643+
def test(what):
644+
return lambda e: events.append((what, e.widget))
645+
646+
root.bind_all(event, test('all'))
647+
root.bind_class('Test', event, test('frame class'))
648+
root.bind_class('Toplevel', event, test('toplevel class'))
649+
root.bind_class('tag', event, test('tag'))
650+
root.bind_class('tag2', event, test('tag2'))
651+
f.bind(event, test('frame'))
652+
t.bind(event, test('toplevel'))
653+
654+
events = []
655+
f.event_generate(event)
656+
self.assertEqual(events, [
657+
('frame', f),
658+
('frame class', f),
659+
('toplevel', f),
660+
('all', f),
661+
])
662+
663+
events = []
664+
t.event_generate(event)
665+
self.assertEqual(events, [
666+
('toplevel', t),
667+
('toplevel class', t),
668+
('all', t),
669+
])
670+
671+
f.bindtags(('tag', 'tag3'))
672+
events = []
673+
f.event_generate(event)
674+
self.assertEqual(events, [('tag', f)])
675+
676+
374677
class DefaultRootTest(AbstractDefaultRootTest, unittest.TestCase):
375678

376679
def test_default_root(self):
@@ -426,5 +729,9 @@ def test_mainloop(self):
426729
self.assertRaises(RuntimeError, tkinter.mainloop)
427730

428731

732+
def _info_commands(widget, pattern=None):
733+
return widget.tk.splitlist(widget.tk.call('info', 'commands', pattern))
734+
735+
429736
if __name__ == "__main__":
430737
unittest.main()

0 commit comments

Comments
 (0)