python (3.12.0)
1 import unittest
2 from test import support
3
4 import gc
5 import tkinter
6 from tkinter import (Variable, StringVar, IntVar, DoubleVar, BooleanVar, Tcl,
7 TclError)
8 from test.support import ALWAYS_EQ
9 from test.test_tkinter.support import AbstractDefaultRootTest
10
11
12 class ESC[4;38;5;81mVar(ESC[4;38;5;149mVariable):
13
14 _default = "default"
15 side_effect = False
16
17 def set(self, value):
18 self.side_effect = True
19 super().set(value)
20
21
22 class ESC[4;38;5;81mTestBase(ESC[4;38;5;149munittestESC[4;38;5;149m.ESC[4;38;5;149mTestCase):
23
24 def setUp(self):
25 self.root = Tcl()
26
27 def tearDown(self):
28 del self.root
29
30
31 class ESC[4;38;5;81mTestVariable(ESC[4;38;5;149mTestBase):
32
33 def info_exists(self, *args):
34 return self.root.getboolean(self.root.call("info", "exists", *args))
35
36 def test_default(self):
37 v = Variable(self.root)
38 self.assertEqual("", v.get())
39 self.assertRegex(str(v), r"^PY_VAR(\d+)$")
40
41 def test_name_and_value(self):
42 v = Variable(self.root, "sample string", "varname")
43 self.assertEqual("sample string", v.get())
44 self.assertEqual("varname", str(v))
45
46 def test___del__(self):
47 self.assertFalse(self.info_exists("varname"))
48 v = Variable(self.root, "sample string", "varname")
49 self.assertTrue(self.info_exists("varname"))
50 del v
51 support.gc_collect() # For PyPy or other GCs.
52 self.assertFalse(self.info_exists("varname"))
53
54 def test_dont_unset_not_existing(self):
55 self.assertFalse(self.info_exists("varname"))
56 v1 = Variable(self.root, name="name")
57 v2 = Variable(self.root, name="name")
58 del v1
59 support.gc_collect() # For PyPy or other GCs.
60 self.assertFalse(self.info_exists("name"))
61 # shouldn't raise exception
62 del v2
63 support.gc_collect() # For PyPy or other GCs.
64 self.assertFalse(self.info_exists("name"))
65
66 def test_equality(self):
67 # values doesn't matter, only class and name are checked
68 v1 = Variable(self.root, name="abc")
69 v2 = Variable(self.root, name="abc")
70 self.assertIsNot(v1, v2)
71 self.assertEqual(v1, v2)
72
73 v3 = Variable(self.root, name="cba")
74 self.assertNotEqual(v1, v3)
75
76 v4 = StringVar(self.root, name="abc")
77 self.assertEqual(str(v1), str(v4))
78 self.assertNotEqual(v1, v4)
79
80 V = type('Variable', (), {})
81 self.assertNotEqual(v1, V())
82
83 self.assertNotEqual(v1, object())
84 self.assertEqual(v1, ALWAYS_EQ)
85
86 root2 = tkinter.Tk()
87 self.addCleanup(root2.destroy)
88 v5 = Variable(root2, name="abc")
89 self.assertEqual(str(v1), str(v5))
90 self.assertNotEqual(v1, v5)
91
92 def test_invalid_name(self):
93 with self.assertRaises(TypeError):
94 Variable(self.root, name=123)
95
96 def test_null_in_name(self):
97 with self.assertRaises(ValueError):
98 Variable(self.root, name='var\x00name')
99 with self.assertRaises(ValueError):
100 self.root.globalsetvar('var\x00name', "value")
101 with self.assertRaises(ValueError):
102 self.root.globalsetvar(b'var\x00name', "value")
103 with self.assertRaises(ValueError):
104 self.root.setvar('var\x00name', "value")
105 with self.assertRaises(ValueError):
106 self.root.setvar(b'var\x00name', "value")
107
108 def test_initialize(self):
109 v = Var(self.root)
110 self.assertFalse(v.side_effect)
111 v.set("value")
112 self.assertTrue(v.side_effect)
113
114 def test_trace_old(self):
115 # Old interface
116 v = Variable(self.root)
117 vname = str(v)
118 trace = []
119 def read_tracer(*args):
120 trace.append(('read',) + args)
121 def write_tracer(*args):
122 trace.append(('write',) + args)
123 cb1 = v.trace_variable('r', read_tracer)
124 cb2 = v.trace_variable('wu', write_tracer)
125 self.assertEqual(sorted(v.trace_vinfo()), [('r', cb1), ('wu', cb2)])
126 self.assertEqual(trace, [])
127
128 v.set('spam')
129 self.assertEqual(trace, [('write', vname, '', 'w')])
130
131 trace = []
132 v.get()
133 self.assertEqual(trace, [('read', vname, '', 'r')])
134
135 trace = []
136 info = sorted(v.trace_vinfo())
137 v.trace_vdelete('w', cb1) # Wrong mode
138 self.assertEqual(sorted(v.trace_vinfo()), info)
139 with self.assertRaises(TclError):
140 v.trace_vdelete('r', 'spam') # Wrong command name
141 self.assertEqual(sorted(v.trace_vinfo()), info)
142 v.trace_vdelete('r', (cb1, 43)) # Wrong arguments
143 self.assertEqual(sorted(v.trace_vinfo()), info)
144 v.get()
145 self.assertEqual(trace, [('read', vname, '', 'r')])
146
147 trace = []
148 v.trace_vdelete('r', cb1)
149 self.assertEqual(v.trace_vinfo(), [('wu', cb2)])
150 v.get()
151 self.assertEqual(trace, [])
152
153 trace = []
154 del write_tracer
155 gc.collect()
156 v.set('eggs')
157 self.assertEqual(trace, [('write', vname, '', 'w')])
158
159 trace = []
160 del v
161 gc.collect()
162 self.assertEqual(trace, [('write', vname, '', 'u')])
163
164 def test_trace(self):
165 v = Variable(self.root)
166 vname = str(v)
167 trace = []
168 def read_tracer(*args):
169 trace.append(('read',) + args)
170 def write_tracer(*args):
171 trace.append(('write',) + args)
172 tr1 = v.trace_add('read', read_tracer)
173 tr2 = v.trace_add(['write', 'unset'], write_tracer)
174 self.assertEqual(sorted(v.trace_info()), [
175 (('read',), tr1),
176 (('write', 'unset'), tr2)])
177 self.assertEqual(trace, [])
178
179 v.set('spam')
180 self.assertEqual(trace, [('write', vname, '', 'write')])
181
182 trace = []
183 v.get()
184 self.assertEqual(trace, [('read', vname, '', 'read')])
185
186 trace = []
187 info = sorted(v.trace_info())
188 v.trace_remove('write', tr1) # Wrong mode
189 self.assertEqual(sorted(v.trace_info()), info)
190 with self.assertRaises(TclError):
191 v.trace_remove('read', 'spam') # Wrong command name
192 self.assertEqual(sorted(v.trace_info()), info)
193 v.get()
194 self.assertEqual(trace, [('read', vname, '', 'read')])
195
196 trace = []
197 v.trace_remove('read', tr1)
198 self.assertEqual(v.trace_info(), [(('write', 'unset'), tr2)])
199 v.get()
200 self.assertEqual(trace, [])
201
202 trace = []
203 del write_tracer
204 gc.collect()
205 v.set('eggs')
206 self.assertEqual(trace, [('write', vname, '', 'write')])
207
208 trace = []
209 del v
210 gc.collect()
211 self.assertEqual(trace, [('write', vname, '', 'unset')])
212
213
214 class ESC[4;38;5;81mTestStringVar(ESC[4;38;5;149mTestBase):
215
216 def test_default(self):
217 v = StringVar(self.root)
218 self.assertEqual("", v.get())
219
220 def test_get(self):
221 v = StringVar(self.root, "abc", "name")
222 self.assertEqual("abc", v.get())
223 self.root.globalsetvar("name", "value")
224 self.assertEqual("value", v.get())
225
226 def test_get_null(self):
227 v = StringVar(self.root, "abc\x00def", "name")
228 self.assertEqual("abc\x00def", v.get())
229 self.root.globalsetvar("name", "val\x00ue")
230 self.assertEqual("val\x00ue", v.get())
231
232
233 class ESC[4;38;5;81mTestIntVar(ESC[4;38;5;149mTestBase):
234
235 def test_default(self):
236 v = IntVar(self.root)
237 self.assertEqual(0, v.get())
238
239 def test_get(self):
240 v = IntVar(self.root, 123, "name")
241 self.assertEqual(123, v.get())
242 self.root.globalsetvar("name", "345")
243 self.assertEqual(345, v.get())
244 self.root.globalsetvar("name", "876.5")
245 self.assertEqual(876, v.get())
246
247 def test_invalid_value(self):
248 v = IntVar(self.root, name="name")
249 self.root.globalsetvar("name", "value")
250 with self.assertRaises((ValueError, TclError)):
251 v.get()
252
253
254 class ESC[4;38;5;81mTestDoubleVar(ESC[4;38;5;149mTestBase):
255
256 def test_default(self):
257 v = DoubleVar(self.root)
258 self.assertEqual(0.0, v.get())
259
260 def test_get(self):
261 v = DoubleVar(self.root, 1.23, "name")
262 self.assertAlmostEqual(1.23, v.get())
263 self.root.globalsetvar("name", "3.45")
264 self.assertAlmostEqual(3.45, v.get())
265
266 def test_get_from_int(self):
267 v = DoubleVar(self.root, 1.23, "name")
268 self.assertAlmostEqual(1.23, v.get())
269 self.root.globalsetvar("name", "3.45")
270 self.assertAlmostEqual(3.45, v.get())
271 self.root.globalsetvar("name", "456")
272 self.assertAlmostEqual(456, v.get())
273
274 def test_invalid_value(self):
275 v = DoubleVar(self.root, name="name")
276 self.root.globalsetvar("name", "value")
277 with self.assertRaises((ValueError, TclError)):
278 v.get()
279
280
281 class ESC[4;38;5;81mTestBooleanVar(ESC[4;38;5;149mTestBase):
282
283 def test_default(self):
284 v = BooleanVar(self.root)
285 self.assertIs(v.get(), False)
286
287 def test_get(self):
288 v = BooleanVar(self.root, True, "name")
289 self.assertIs(v.get(), True)
290 self.root.globalsetvar("name", "0")
291 self.assertIs(v.get(), False)
292 self.root.globalsetvar("name", 42 if self.root.wantobjects() else 1)
293 self.assertIs(v.get(), True)
294 self.root.globalsetvar("name", 0)
295 self.assertIs(v.get(), False)
296 self.root.globalsetvar("name", "on")
297 self.assertIs(v.get(), True)
298
299 def test_set(self):
300 true = 1 if self.root.wantobjects() else "1"
301 false = 0 if self.root.wantobjects() else "0"
302 v = BooleanVar(self.root, name="name")
303 v.set(True)
304 self.assertEqual(self.root.globalgetvar("name"), true)
305 v.set("0")
306 self.assertEqual(self.root.globalgetvar("name"), false)
307 v.set(42)
308 self.assertEqual(self.root.globalgetvar("name"), true)
309 v.set(0)
310 self.assertEqual(self.root.globalgetvar("name"), false)
311 v.set("on")
312 self.assertEqual(self.root.globalgetvar("name"), true)
313
314 def test_invalid_value_domain(self):
315 false = 0 if self.root.wantobjects() else "0"
316 v = BooleanVar(self.root, name="name")
317 with self.assertRaises(TclError):
318 v.set("value")
319 self.assertEqual(self.root.globalgetvar("name"), false)
320 self.root.globalsetvar("name", "value")
321 with self.assertRaises(ValueError):
322 v.get()
323 self.root.globalsetvar("name", "1.0")
324 with self.assertRaises(ValueError):
325 v.get()
326
327
328 class ESC[4;38;5;81mDefaultRootTest(ESC[4;38;5;149mAbstractDefaultRootTest, ESC[4;38;5;149munittestESC[4;38;5;149m.ESC[4;38;5;149mTestCase):
329
330 def test_variable(self):
331 self.assertRaises(RuntimeError, Variable)
332 root = tkinter.Tk()
333 v = Variable()
334 v.set("value")
335 self.assertEqual(v.get(), "value")
336 root.destroy()
337 tkinter.NoDefaultRoot()
338 self.assertRaises(RuntimeError, Variable)
339
340
341 if __name__ == "__main__":
342 unittest.main()