summaryrefslogtreecommitdiff
path: root/Lib/tkinter
diff options
context:
space:
mode:
authorSerhiy Storchaka <storchaka@gmail.com>2016-06-26 17:42:23 +0300
committerSerhiy Storchaka <storchaka@gmail.com>2016-06-26 17:42:23 +0300
commitf102181dc7b496de26eb04fb17cfd2aa7645bf06 (patch)
tree205f89c89a9e6842093702245afa34b5c16103b5 /Lib/tkinter
parentd2f6bfa5a5192120cee08eab488203ecf4c9bc12 (diff)
downloadcpython-f102181dc7b496de26eb04fb17cfd2aa7645bf06.tar.gz
Issue #22115: Fixed tracing Tkinter variables:
* tracing in the "u" mode now works * trace_vdelete() with wrong mode no longer break tracing * trace_vinfo() now always returns a list of pairs of strings
Diffstat (limited to 'Lib/tkinter')
-rw-r--r--Lib/tkinter/__init__.py19
-rw-r--r--Lib/tkinter/test/test_tkinter/test_variables.py51
2 files changed, 62 insertions, 8 deletions
diff --git a/Lib/tkinter/__init__.py b/Lib/tkinter/__init__.py
index aa646dc8ed..55bfb7f414 100644
--- a/Lib/tkinter/__init__.py
+++ b/Lib/tkinter/__init__.py
@@ -271,7 +271,7 @@ class Variable:
Return the name of the callback.
"""
- f = CallWrapper(callback, None, self).__call__
+ f = CallWrapper(callback, None, self._root).__call__
cbname = repr(id(f))
try:
callback = callback.__func__
@@ -295,14 +295,19 @@ class Variable:
CBNAME is the name of the callback returned from trace_variable or trace.
"""
self._tk.call("trace", "vdelete", self._name, mode, cbname)
- self._tk.deletecommand(cbname)
- try:
- self._tclCommands.remove(cbname)
- except ValueError:
- pass
+ cbname = self._tk.splitlist(cbname)[0]
+ for m, ca in self.trace_vinfo():
+ if self._tk.splitlist(ca)[0] == cbname:
+ break
+ else:
+ self._tk.deletecommand(cbname)
+ try:
+ self._tclCommands.remove(cbname)
+ except ValueError:
+ pass
def trace_vinfo(self):
"""Return all trace callback information."""
- return [self._tk.split(x) for x in self._tk.splitlist(
+ return [self._tk.splitlist(x) for x in self._tk.splitlist(
self._tk.call("trace", "vinfo", self._name))]
def __eq__(self, other):
"""Comparison for equality (==).
diff --git a/Lib/tkinter/test/test_tkinter/test_variables.py b/Lib/tkinter/test/test_tkinter/test_variables.py
index abdce96998..1f74453cea 100644
--- a/Lib/tkinter/test/test_tkinter/test_variables.py
+++ b/Lib/tkinter/test/test_tkinter/test_variables.py
@@ -1,5 +1,5 @@
import unittest
-
+import gc
from tkinter import (Variable, StringVar, IntVar, DoubleVar, BooleanVar, Tcl,
TclError)
@@ -87,6 +87,55 @@ class TestVariable(TestBase):
v.set("value")
self.assertTrue(v.side_effect)
+ def test_trace(self):
+ v = Variable(self.root)
+ vname = str(v)
+ trace = []
+ def read_tracer(*args):
+ trace.append(('read',) + args)
+ def write_tracer(*args):
+ trace.append(('write',) + args)
+ cb1 = v.trace_variable('r', read_tracer)
+ cb2 = v.trace_variable('wu', write_tracer)
+ self.assertEqual(sorted(v.trace_vinfo()), [('r', cb1), ('wu', cb2)])
+ self.assertEqual(trace, [])
+
+ v.set('spam')
+ self.assertEqual(trace, [('write', vname, '', 'w')])
+
+ trace = []
+ v.get()
+ self.assertEqual(trace, [('read', vname, '', 'r')])
+
+ trace = []
+ info = sorted(v.trace_vinfo())
+ v.trace_vdelete('w', cb1) # Wrong mode
+ self.assertEqual(sorted(v.trace_vinfo()), info)
+ with self.assertRaises(TclError):
+ v.trace_vdelete('r', 'spam') # Wrong command name
+ self.assertEqual(sorted(v.trace_vinfo()), info)
+ v.trace_vdelete('r', (cb1, 43)) # Wrong arguments
+ self.assertEqual(sorted(v.trace_vinfo()), info)
+ v.get()
+ self.assertEqual(trace, [('read', vname, '', 'r')])
+
+ trace = []
+ v.trace_vdelete('r', cb1)
+ self.assertEqual(v.trace_vinfo(), [('wu', cb2)])
+ v.get()
+ self.assertEqual(trace, [])
+
+ trace = []
+ del write_tracer
+ gc.collect()
+ v.set('eggs')
+ self.assertEqual(trace, [('write', vname, '', 'w')])
+
+ trace = []
+ del v
+ gc.collect()
+ self.assertEqual(trace, [('write', vname, '', 'u')])
+
class TestStringVar(TestBase):