import unittest import gc from tkinter import (Variable, StringVar, IntVar, DoubleVar, BooleanVar, Tcl, TclError) class Var(Variable): _default = "default" side_effect = False def set(self, value): self.side_effect = True super().set(value) class TestBase(unittest.TestCase): def setUp(self): self.root = Tcl() def tearDown(self): del self.root class TestVariable(TestBase): def info_exists(self, *args): return self.root.getboolean(self.root.call("info", "exists", *args)) def test_default(self): v = Variable(self.root) self.assertEqual("", v.get()) self.assertRegex(str(v), r"^PY_VAR(\d+)$") def test_name_and_value(self): v = Variable(self.root, "sample string", "varname") self.assertEqual("sample string", v.get()) self.assertEqual("varname", str(v)) def test___del__(self): self.assertFalse(self.info_exists("varname")) v = Variable(self.root, "sample string", "varname") self.assertTrue(self.info_exists("varname")) del v self.assertFalse(self.info_exists("varname")) def test_dont_unset_not_existing(self): self.assertFalse(self.info_exists("varname")) v1 = Variable(self.root, name="name") v2 = Variable(self.root, name="name") del v1 self.assertFalse(self.info_exists("name")) # shouldn't raise exception del v2 self.assertFalse(self.info_exists("name")) def test___eq__(self): # values doesn't matter, only class and name are checked v1 = Variable(self.root, name="abc") v2 = Variable(self.root, name="abc") self.assertEqual(v1, v2) v3 = Variable(self.root, name="abc") v4 = StringVar(self.root, name="abc") self.assertNotEqual(v3, v4) def test_invalid_name(self): with self.assertRaises(TypeError): Variable(self.root, name=123) def test_null_in_name(self): with self.assertRaises(ValueError): Variable(self.root, name='var\x00name') with self.assertRaises(ValueError): self.root.globalsetvar('var\x00name', "value") with self.assertRaises(ValueError): self.root.globalsetvar(b'var\x00name', "value") with self.assertRaises(ValueError): self.root.setvar('var\x00name', "value") with self.assertRaises(ValueError): self.root.setvar(b'var\x00name', "value") def test_initialize(self): v = Var(self.root) self.assertFalse(v.side_effect) v.set("value") self.assertTrue(v.side_effect) def test_trace_old(self): # Old interface 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')]) 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) tr1 = v.trace_add('read', read_tracer) tr2 = v.trace_add(['write', 'unset'], write_tracer) self.assertEqual(sorted(v.trace_info()), [ (('read',), tr1), (('write', 'unset'), tr2)]) self.assertEqual(trace, []) v.set('spam') self.assertEqual(trace, [('write', vname, '', 'write')]) trace = [] v.get() self.assertEqual(trace, [('read', vname, '', 'read')]) trace = [] info = sorted(v.trace_info()) v.trace_remove('write', tr1) # Wrong mode self.assertEqual(sorted(v.trace_info()), info) with self.assertRaises(TclError): v.trace_remove('read', 'spam') # Wrong command name self.assertEqual(sorted(v.trace_info()), info) v.get() self.assertEqual(trace, [('read', vname, '', 'read')]) trace = [] v.trace_remove('read', tr1) self.assertEqual(v.trace_info(), [(('write', 'unset'), tr2)]) v.get() self.assertEqual(trace, []) trace = [] del write_tracer gc.collect() v.set('eggs') self.assertEqual(trace, [('write', vname, '', 'write')]) trace = [] del v gc.collect() self.assertEqual(trace, [('write', vname, '', 'unset')]) class TestStringVar(TestBase): def test_default(self): v = StringVar(self.root) self.assertEqual("", v.get()) def test_get(self): v = StringVar(self.root, "abc", "name") self.assertEqual("abc", v.get()) self.root.globalsetvar("name", "value") self.assertEqual("value", v.get()) def test_get_null(self): v = StringVar(self.root, "abc\x00def", "name") self.assertEqual("abc\x00def", v.get()) self.root.globalsetvar("name", "val\x00ue") self.assertEqual("val\x00ue", v.get()) class TestIntVar(TestBase): def test_default(self): v = IntVar(self.root) self.assertEqual(0, v.get()) def test_get(self): v = IntVar(self.root, 123, "name") self.assertEqual(123, v.get()) self.root.globalsetvar("name", "345") self.assertEqual(345, v.get()) self.root.globalsetvar("name", "876.5") self.assertEqual(876, v.get()) def test_invalid_value(self): v = IntVar(self.root, name="name") self.root.globalsetvar("name", "value") with self.assertRaises((ValueError, TclError)): v.get() class TestDoubleVar(TestBase): def test_default(self): v = DoubleVar(self.root) self.assertEqual(0.0, v.get()) def test_get(self): v = DoubleVar(self.root, 1.23, "name") self.assertAlmostEqual(1.23, v.get()) self.root.globalsetvar("name", "3.45") self.assertAlmostEqual(3.45, v.get()) def test_get_from_int(self): v = DoubleVar(self.root, 1.23, "name") self.assertAlmostEqual(1.23, v.get()) self.root.globalsetvar("name", "3.45") self.assertAlmostEqual(3.45, v.get()) self.root.globalsetvar("name", "456") self.assertAlmostEqual(456, v.get()) def test_invalid_value(self): v = DoubleVar(self.root, name="name") self.root.globalsetvar("name", "value") with self.assertRaises((ValueError, TclError)): v.get() class TestBooleanVar(TestBase): def test_default(self): v = BooleanVar(self.root) self.assertIs(v.get(), False) def test_get(self): v = BooleanVar(self.root, True, "name") self.assertIs(v.get(), True) self.root.globalsetvar("name", "0") self.assertIs(v.get(), False) self.root.globalsetvar("name", 42 if self.root.wantobjects() else 1) self.assertIs(v.get(), True) self.root.globalsetvar("name", 0) self.assertIs(v.get(), False) self.root.globalsetvar("name", "on") self.assertIs(v.get(), True) def test_set(self): true = 1 if self.root.wantobjects() else "1" false = 0 if self.root.wantobjects() else "0" v = BooleanVar(self.root, name="name") v.set(True) self.assertEqual(self.root.globalgetvar("name"), true) v.set("0") self.assertEqual(self.root.globalgetvar("name"), false) v.set(42) self.assertEqual(self.root.globalgetvar("name"), true) v.set(0) self.assertEqual(self.root.globalgetvar("name"), false) v.set("on") self.assertEqual(self.root.globalgetvar("name"), true) def test_invalid_value_domain(self): false = 0 if self.root.wantobjects() else "0" v = BooleanVar(self.root, name="name") with self.assertRaises(TclError): v.set("value") self.assertEqual(self.root.globalgetvar("name"), false) self.root.globalsetvar("name", "value") with self.assertRaises(ValueError): v.get() self.root.globalsetvar("name", "1.0") with self.assertRaises(ValueError): v.get() tests_gui = (TestVariable, TestStringVar, TestIntVar, TestDoubleVar, TestBooleanVar) if __name__ == "__main__": from test.support import run_unittest run_unittest(*tests_gui)