You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
{{ message }}
Repository navigation
Tkinter widget.unbind(sequence, funcid) unbind all bindings #75666
I am using python 3.6.2 with tk 8.6.7 in Linux and when I call widget.unbind(<Sequence>, funcid), it unbinds all bindings for <Sequence>, while I would expect it to unbind only funcid. Here is an example reproducing the problem:
Tk do not provide a way of unbinding a specific command. It supports binding a script with replacing an existing binding, appending a script to an existing binding, and destroying an existing binding. Unbinding a specific command can be implemented in Python with a code similar to your example, but more complex due to taking to account different corner cases.
Do you want to write a patch and open a pull request Juliette?
The unbind docstring, "Unbind for this widget for event SEQUENCE the
function identified with FUNCID" implies to me the behavior Juliette expected. The NMT reference unpacks this to two sentences. Reading the code
self.tk.call('bind', self._w, sequence, '')
if funcid:
self.deletecommand(funcid)
the docstring should be something like "Unbind for this widget the event SEQUENCE. If funcid is given, delete the command also" This part of the bind docstring, "Bind will return an identifier to allow deletion of the bound function with unbind without memory leak." implies that the unbind behavior is deliberate.
Serhiy, are you proposing to add a new method that does what some people thought unbind would do?
I don't think a new method is needed. We can make unbind() destroying all bindings if FUNCID is not given (note that registered commands are leaked in this case), and only the specified command if it is specified. We can add a boolean parameter (similar to the one in bind()) for restoring the old behavior if this is needed.
j4321 commented on Sep 18, 2017
j4321mannequin
MannequinAuthor
More actions
I don't mind writing a patch and opening a pull request, however I don't know which corner cases I need to take into account.
def unbind(self, sequence, funcid=None):
"""Unbind for this widget for event SEQUENCE the
function identified with FUNCID."""
bound = ''
if funcid:
self.deletecommand(funcid)
funcs = self.tk.call('bind', self._w, sequence, None).split('\n')
bound = '\n'.join([f for f in funcs if not f.startswith('if {{"[{0}'.format(funcid))])
self.tk.call('bind', self._w, sequence, bound)
Serhiy, if I understand your last message (msg302299), the docstring should read:
Unbind for this widget the event SEQUENCE.
If FUNCID is given, only unbind the function identified with FUNCID
and also delete that command.
The main doc change is to specify what happens when funcid is not given while the code change in the patch is to no longer unbind everything when funcid *is* given.
Serhiy, given that the code did not match the docstring and that we are changing the code to match the clarified docstring, should we consider this a bugfix, and, should we backport it?
I wrote it almost 3 years ago, but there was a little issue with IDLE, so I put it aside and then forgot about it. Turned out, the bug was in IDLE tests. It was hidden by that bug in unbind() and was exposed when it was fixed. The change does not affect IDLE, and I hope it will not break much user code.
Activity
j4321 commentedon Sep 15, 2017
I am using python 3.6.2 with tk 8.6.7 in Linux and when I call widget.unbind(<Sequence>, funcid), it unbinds all bindings for <Sequence>, while I would expect it to unbind only funcid. Here is an example reproducing the problem:
In this example, clicking on one of the buttons unbinds both bindings instead of only one.
j4321 commentedon Sep 15, 2017
I have found a workaround to unbind a single binding (inspired by https://mail.python.org/pipermail/tkinter-discuss/2012-May/003151.html):
serhiy-storchaka commentedon Sep 15, 2017
Tk do not provide a way of unbinding a specific command. It supports binding a script with replacing an existing binding, appending a script to an existing binding, and destroying an existing binding. Unbinding a specific command can be implemented in Python with a code similar to your example, but more complex due to taking to account different corner cases.
Do you want to write a patch and open a pull request Juliette?
terryjreedy commentedon Sep 15, 2017
The unbind docstring, "Unbind for this widget for event SEQUENCE the
function identified with FUNCID" implies to me the behavior Juliette expected. The NMT reference unpacks this to two sentences. Reading the code
self.tk.call('bind', self._w, sequence, '')
if funcid:
self.deletecommand(funcid)
the docstring should be something like "Unbind for this widget the event SEQUENCE. If funcid is given, delete the command also" This part of the bind docstring, "Bind will return an identifier to allow deletion of the bound function with unbind without memory leak." implies that the unbind behavior is deliberate.
Serhiy, are you proposing to add a new method that does what some people thought unbind would do?
serhiy-storchaka commentedon Sep 15, 2017
I don't think a new method is needed. We can make unbind() destroying all bindings if FUNCID is not given (note that registered commands are leaked in this case), and only the specified command if it is specified. We can add a boolean parameter (similar to the one in bind()) for restoring the old behavior if this is needed.
j4321 commentedon Sep 18, 2017
I don't mind writing a patch and opening a pull request, however I don't know which corner cases I need to take into account.
GiovaLomba commentedon Dec 10, 2019
http://docs.python.org/devguide/triaging.html#assigned-to
GiovaLomba commentedon Jan 5, 2020
I propose the below fix:
terryjreedy commentedon Jan 16, 2020
Serhiy, if I understand your last message (msg302299), the docstring should read:
The main doc change is to specify what happens when funcid is not given while the code change in the patch is to no longer unbind everything when funcid *is* given.
terryjreedy commentedon Jan 16, 2020
Serhiy, given that the code did not match the docstring and that we are changing the code to match the clarified docstring, should we consider this a bugfix, and, should we backport it?
29 remaining items
hugovk commentedon Jan 11, 2024
serhiy-storchaka commentedon Jan 11, 2024
pythongh-75666: Tkinter: add tests for binding (pythonGH-111202)
pythongh-75666: Tkinter: "unbind(sequence, funcid)" now only unbinds …
pythongh-75666: Tkinter: add tests for binding (pythonGH-111202)
pythongh-75666: Tkinter: "unbind(sequence, funcid)" now only unbinds …
serhiy-storchaka commentedon Jun 20, 2026
Opened #151808.
I wrote it almost 3 years ago, but there was a little issue with IDLE, so I put it aside and then forgot about it. Turned out, the bug was in IDLE tests. It was hidden by that bug in unbind() and was exposed when it was fixed. The change does not affect IDLE, and I hope it will not break much user code.
gh-75666: Fix a reference leak in tkinter event bindings (GH-151808)
serhiy-storchaka commentedon Jun 23, 2026
Still, it is safer to only backport this fix to 3.15. The leak was always.
[3.15] gh-75666: Fix a reference leak in tkinter event bindings (GH-1…
[3.14]gh-75666: idlelib backport of iomenu change (GH-151958) (#152995)
[3.13] gh-75666: idlelib backport of iomenu change (GH-151958) (GH-15…
pythongh-75666: Fix a reference leak in tkinter event bindings (pytho…