mirror of https://github.com/python/cpython
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
This commit is contained in:
parent
e7614dd07d
commit
745a407df8
|
@ -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 (==).
|
||||
|
|
|
@ -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):
|
||||
|
||||
|
|
|
@ -13,6 +13,10 @@ Core and Builtins
|
|||
Library
|
||||
-------
|
||||
|
||||
- Issue #22115: Fixed tracing Tkinter variables: trace_vdelete() with wrong
|
||||
mode no longer break tracing, trace_vinfo() now always returns a list of
|
||||
pairs of strings, tracing in the "u" mode now works.
|
||||
|
||||
- Fix a scoping issue in importlib.util.LazyLoader which triggered an
|
||||
UnboundLocalError when lazy-loading a module that was already put into
|
||||
sys.modules.
|
||||
|
|
Loading…
Reference in New Issue