summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--Lib/test/test_tkinter/test_misc.py34
-rw-r--r--Lib/tkinter/__init__.py22
-rw-r--r--Misc/NEWS.d/next/Library/2023-10-25-16-37-13.gh-issue-75666.BpsWut.rst6
3 files changed, 51 insertions, 11 deletions
diff --git a/Lib/test/test_tkinter/test_misc.py b/Lib/test/test_tkinter/test_misc.py
index bac52ae..a84bb02 100644
--- a/Lib/test/test_tkinter/test_misc.py
+++ b/Lib/test/test_tkinter/test_misc.py
@@ -425,26 +425,46 @@ class BindTest(AbstractTkTest, unittest.TestCase):
def test_unbind2(self):
f = self.frame
+ f.wait_visibility()
+ f.focus_force()
+ f.update_idletasks()
event = '<Control-Alt-Key-c>'
self.assertEqual(f.bind(), ())
self.assertEqual(f.bind(event), '')
- def test1(e): pass
- def test2(e): pass
+ def test1(e): events.append('a')
+ def test2(e): events.append('b')
+ def test3(e): events.append('c')
funcid = f.bind(event, test1)
funcid2 = f.bind(event, test2, add=True)
+ funcid3 = f.bind(event, test3, add=True)
+ events = []
+ f.event_generate(event)
+ self.assertEqual(events, ['a', 'b', 'c'])
- f.unbind(event, funcid)
+ f.unbind(event, funcid2)
script = f.bind(event)
- self.assertNotIn(funcid, script)
- self.assertCommandNotExist(funcid)
- self.assertCommandExist(funcid2)
+ self.assertNotIn(funcid2, script)
+ self.assertIn(funcid, script)
+ self.assertIn(funcid3, script)
+ self.assertEqual(f.bind(), (event,))
+ self.assertCommandNotExist(funcid2)
+ self.assertCommandExist(funcid)
+ self.assertCommandExist(funcid3)
+ events = []
+ f.event_generate(event)
+ self.assertEqual(events, ['a', 'c'])
- f.unbind(event, funcid2)
+ f.unbind(event, funcid)
+ f.unbind(event, funcid3)
self.assertEqual(f.bind(event), '')
self.assertEqual(f.bind(), ())
self.assertCommandNotExist(funcid)
self.assertCommandNotExist(funcid2)
+ self.assertCommandNotExist(funcid3)
+ events = []
+ f.event_generate(event)
+ self.assertEqual(events, [])
# non-idempotent
self.assertRaises(tkinter.TclError, f.unbind, event, funcid2)
diff --git a/Lib/tkinter/__init__.py b/Lib/tkinter/__init__.py
index cb3e5f1..c47c8c2 100644
--- a/Lib/tkinter/__init__.py
+++ b/Lib/tkinter/__init__.py
@@ -1448,10 +1448,24 @@ class Misc:
return self._bind(('bind', self._w), sequence, func, add)
def unbind(self, sequence, funcid=None):
- """Unbind for this widget for event SEQUENCE the
- function identified with FUNCID."""
- self.tk.call('bind', self._w, sequence, '')
- if funcid:
+ """Unbind for this widget the event SEQUENCE.
+
+ If FUNCID is given, only unbind the function identified with FUNCID
+ and also delete the corresponding Tcl command.
+
+ Otherwise destroy the current binding for SEQUENCE, leaving SEQUENCE
+ unbound.
+ """
+ if funcid is None:
+ self.tk.call('bind', self._w, sequence, '')
+ else:
+ lines = self.tk.call('bind', self._w, sequence).split('\n')
+ prefix = f'if {{"[{funcid} '
+ keep = '\n'.join(line for line in lines
+ if not line.startswith(prefix))
+ if not keep.strip():
+ keep = ''
+ self.tk.call('bind', self._w, sequence, keep)
self.deletecommand(funcid)
def bind_all(self, sequence=None, func=None, add=None):
diff --git a/Misc/NEWS.d/next/Library/2023-10-25-16-37-13.gh-issue-75666.BpsWut.rst b/Misc/NEWS.d/next/Library/2023-10-25-16-37-13.gh-issue-75666.BpsWut.rst
new file mode 100644
index 0000000..d774cc4
--- /dev/null
+++ b/Misc/NEWS.d/next/Library/2023-10-25-16-37-13.gh-issue-75666.BpsWut.rst
@@ -0,0 +1,6 @@
+Fix the behavior of :mod:`tkinter` widget's ``unbind()`` method with two
+arguments. Previously, ``widget.unbind(sequence, funcid)`` destroyed the
+current binding for *sequence*, leaving *sequence* unbound, and deleted the
+*funcid* command. Now it removes only *funcid* from the binding for
+*sequence*, keeping other commands, and deletes the *funcid* command. It
+leaves *sequence* unbound only if *funcid* was the last bound command.