diff options
author | Miss Islington (bot) <31488909+miss-islington@users.noreply.github.com> | 2018-03-04 04:00:33 -0800 |
---|---|---|
committer | GitHub <noreply@github.com> | 2018-03-04 04:00:33 -0800 |
commit | a5303dd9c263b337f02dda0038f2f5a10208140c (patch) | |
tree | 43ac9881f69afee94913323411e485fdcbcf6a55 /Lib/tkinter | |
parent | 0902a2d6b2d1d9dbde36aeaaccf1788ceaa97143 (diff) | |
download | cpython-git-a5303dd9c263b337f02dda0038f2f5a10208140c.tar.gz |
bpo-32857: Raise error when tkinter after_cancel() is called with None. (GH-5701)
(cherry picked from commit 74382a3f175ac285cc924a73fd758e8dc3cc41bb)
Co-authored-by: Cheryl Sabella <cheryl.sabella@gmail.com>
Diffstat (limited to 'Lib/tkinter')
-rw-r--r-- | Lib/tkinter/__init__.py | 9 | ||||
-rw-r--r-- | Lib/tkinter/test/test_tkinter/test_misc.py | 108 |
2 files changed, 114 insertions, 3 deletions
diff --git a/Lib/tkinter/__init__.py b/Lib/tkinter/__init__.py index deea791831..53bad3fa95 100644 --- a/Lib/tkinter/__init__.py +++ b/Lib/tkinter/__init__.py @@ -739,6 +739,7 @@ class Misc: if not func: # I'd rather use time.sleep(ms*0.001) self.tk.call('after', ms) + return None else: def callit(): try: @@ -762,11 +763,13 @@ class Misc: """Cancel scheduling of function identified with ID. Identifier returned by after or after_idle must be - given as first parameter.""" + given as first parameter. + """ + if not id: + raise ValueError('id must be a valid identifier returned from ' + 'after or after_idle') try: data = self.tk.call('after', 'info', id) - # In Tk 8.3, splitlist returns: (script, type) - # In Tk 8.4, splitlist may return (script, type) or (script,) script = self.tk.splitlist(data)[0] self.deletecommand(script) except TclError: diff --git a/Lib/tkinter/test/test_tkinter/test_misc.py b/Lib/tkinter/test/test_tkinter/test_misc.py index 9dc1e37547..1d1a3c29f6 100644 --- a/Lib/tkinter/test/test_tkinter/test_misc.py +++ b/Lib/tkinter/test/test_tkinter/test_misc.py @@ -48,6 +48,114 @@ class MiscTest(AbstractTkTest, unittest.TestCase): '^must specify a background color$', root.tk_setPalette, highlightColor='blue') + def test_after(self): + root = self.root + + def callback(start=0, step=1): + nonlocal count + count = start + step + + # Without function, sleeps for ms. + self.assertIsNone(root.after(1)) + + # Set up with callback with no args. + count = 0 + timer1 = root.after(0, callback) + self.assertIn(timer1, root.tk.call('after', 'info')) + (script, _) = root.tk.splitlist(root.tk.call('after', 'info', timer1)) + root.update() # Process all pending events. + self.assertEqual(count, 1) + with self.assertRaises(tkinter.TclError): + root.tk.call(script) + + # Set up with callback with args. + count = 0 + timer1 = root.after(0, callback, 42, 11) + root.update() # Process all pending events. + self.assertEqual(count, 53) + + # Cancel before called. + timer1 = root.after(1000, callback) + self.assertIn(timer1, root.tk.call('after', 'info')) + (script, _) = root.tk.splitlist(root.tk.call('after', 'info', timer1)) + root.after_cancel(timer1) # Cancel this event. + self.assertEqual(count, 53) + with self.assertRaises(tkinter.TclError): + root.tk.call(script) + + def test_after_idle(self): + root = self.root + + def callback(start=0, step=1): + nonlocal count + count = start + step + + # Set up with callback with no args. + count = 0 + idle1 = root.after_idle(callback) + self.assertIn(idle1, root.tk.call('after', 'info')) + (script, _) = root.tk.splitlist(root.tk.call('after', 'info', idle1)) + root.update_idletasks() # Process all pending events. + self.assertEqual(count, 1) + with self.assertRaises(tkinter.TclError): + root.tk.call(script) + + # Set up with callback with args. + count = 0 + idle1 = root.after_idle(callback, 42, 11) + root.update_idletasks() # Process all pending events. + self.assertEqual(count, 53) + + # Cancel before called. + idle1 = root.after_idle(callback) + self.assertIn(idle1, root.tk.call('after', 'info')) + (script, _) = root.tk.splitlist(root.tk.call('after', 'info', idle1)) + root.after_cancel(idle1) # Cancel this event. + self.assertEqual(count, 53) + with self.assertRaises(tkinter.TclError): + root.tk.call(script) + + def test_after_cancel(self): + root = self.root + + def callback(): + nonlocal count + count += 1 + + timer1 = root.after(5000, callback) + idle1 = root.after_idle(callback) + + # No value for id raises a ValueError. + with self.assertRaises(ValueError): + root.after_cancel(None) + + # Cancel timer event. + count = 0 + (script, _) = root.tk.splitlist(root.tk.call('after', 'info', timer1)) + root.tk.call(script) + self.assertEqual(count, 1) + root.after_cancel(timer1) + with self.assertRaises(tkinter.TclError): + root.tk.call(script) + self.assertEqual(count, 1) + with self.assertRaises(tkinter.TclError): + root.tk.call('after', 'info', timer1) + + # Cancel same event - nothing happens. + root.after_cancel(timer1) + + # Cancel idle event. + count = 0 + (script, _) = root.tk.splitlist(root.tk.call('after', 'info', idle1)) + root.tk.call(script) + self.assertEqual(count, 1) + root.after_cancel(idle1) + with self.assertRaises(tkinter.TclError): + root.tk.call(script) + self.assertEqual(count, 1) + with self.assertRaises(tkinter.TclError): + root.tk.call('after', 'info', idle1) + tests_gui = (MiscTest, ) |