cls.root = Tk()
cls.root.withdraw()
cls.editwin = EditorWindow(root=cls.root)
- cls.io = iomenu.IOBinding(cls.editwin)
+ cls.io = cls.editwin.io
@classmethod
def tearDownClass(cls):
- cls.io.close()
cls.editwin._close()
del cls.editwin
cls.root.update_idletasks()
self.assertNotIn(funcid, script)
self.assertNotIn(funcid2, script)
self.assertIn(funcid3, script)
+ self.assertCommandNotExist(funcid)
+ self.assertCommandNotExist(funcid2)
self.assertCommandExist(funcid3)
def test_bind_class(self):
unbind_class('Test', event)
self.assertEqual(bind_class('Test', event), '')
self.assertEqual(bind_class('Test'), ())
- self.assertCommandExist(funcid)
- self.assertCommandExist(funcid2)
+ self.assertCommandNotExist(funcid)
+ self.assertCommandNotExist(funcid2)
unbind_class('Test', event) # idempotent
self.assertNotIn(funcid, script)
self.assertNotIn(funcid2, script)
self.assertIn(funcid3, script)
- self.assertCommandExist(funcid)
- self.assertCommandExist(funcid2)
+ self.assertCommandNotExist(funcid)
+ self.assertCommandNotExist(funcid2)
self.assertCommandExist(funcid3)
def test_bind_all(self):
unbind_all(event)
self.assertEqual(bind_all(event), '')
self.assertNotIn(event, bind_all())
- self.assertCommandExist(funcid)
- self.assertCommandExist(funcid2)
+ self.assertCommandNotExist(funcid)
+ self.assertCommandNotExist(funcid2)
unbind_all(event) # idempotent
self.assertNotIn(funcid, script)
self.assertNotIn(funcid2, script)
self.assertIn(funcid3, script)
- self.assertCommandExist(funcid)
- self.assertCommandExist(funcid2)
+ self.assertCommandNotExist(funcid)
+ self.assertCommandNotExist(funcid2)
self.assertCommandExist(funcid3)
def _test_tag_bind(self, w):
else:
self.tk.call('bindtags', self._w, tagList)
- def _bind(self, what, sequence, func, add, needcleanup=1):
+ def _delete_bind_commands(self, *what):
+ lines = self.tk.call(what).split('\n')
+ p = re.compile(r'if \{"\[([^ ]+) .*\]" == "break"\} break')
+ for line in lines:
+ m = p.fullmatch(line)
+ if m:
+ funcid = m[1]
+ try:
+ self.deletecommand(funcid)
+ except TclError:
+ pass
+
+ def _bind(self, what, sequence, func, add):
"""Internal function."""
if isinstance(func, str):
self.tk.call(what + (sequence, func))
elif func:
- funcid = self._register(func, self._substitute,
- needcleanup)
+ if not add:
+ self._delete_bind_commands(*what, sequence)
+ funcid = self._register(func, self._substitute, needcleanup=True)
cmd = ('%sif {"[%s %s]" == "break"} break\n'
%
(add and '+' or '',
def _unbind(self, what, funcid=None):
if funcid is None:
+ self._delete_bind_commands(*what)
self.tk.call(*what, '')
else:
lines = self.tk.call(what).split('\n')
An additional boolean parameter ADD specifies whether FUNC will
be called additionally to the other bound function or whether
it will replace the previous function. See bind for the return value."""
- return self._root()._bind(('bind', 'all'), sequence, func, add, True)
+ return self._root()._bind(('bind', 'all'), sequence, func, add)
def unbind_all(self, sequence):
"""Unbind for all widgets for event SEQUENCE all functions."""
whether it will replace the previous function. See bind for
the return value."""
- return self._root()._bind(('bind', className), sequence, func, add, True)
+ return self._root()._bind(('bind', className), sequence, func, add)
def unbind_class(self, className, sequence):
"""Unbind for all widgets with bindtag CLASSNAME for event SEQUENCE
--- /dev/null
+Fix a reference leak in :mod:`tkinter`: the Tcl commands created for event
+callbacks are now deleted when a binding is replaced or unbound.