blob: cd2a30e533ae032a50cd3f3ceb6e54abdda88b72 [file] [log] [blame]
David Aschere2b4b322004-02-18 05:59:53 +00001import unittest
Serhiy Storchaka462c3572015-04-22 08:36:03 +03002import re
Zachary Ware83fd0a82015-10-12 23:27:58 -05003import subprocess
Hirokazu Yamamotodda7fdf2010-09-23 15:28:35 +00004import sys
David Aschere2b4b322004-02-18 05:59:53 +00005import os
Serhiy Storchakad05b0002019-10-08 14:31:35 +03006import warnings
Benjamin Petersonee8712c2008-05-20 21:35:26 +00007from test import support
Hai Shi06a40d72020-06-25 20:15:40 +08008from test.support import import_helper
Hai Shi79bb2c92020-08-06 19:51:29 +08009from test.support import os_helper
R. David Murraya21e4ca2009-03-31 23:16:50 +000010
11# Skip this test if the _tkinter module wasn't built.
Hai Shi06a40d72020-06-25 20:15:40 +080012_tkinter = import_helper.import_module('_tkinter')
R. David Murraya21e4ca2009-03-31 23:16:50 +000013
Zachary Ware7dc9dea2015-05-22 11:36:53 -050014import tkinter
Guilherme Polofa8fba92009-02-07 02:33:47 +000015from tkinter import Tcl
David Aschere2b4b322004-02-18 05:59:53 +000016from _tkinter import TclError
17
Serhiy Storchaka5cfc79d2014-02-07 10:06:39 +020018try:
19 from _testcapi import INT_MAX, PY_SSIZE_T_MAX
20except ImportError:
21 INT_MAX = PY_SSIZE_T_MAX = sys.maxsize
22
Serhiy Storchaka462c3572015-04-22 08:36:03 +030023tcl_version = tuple(map(int, _tkinter.TCL_VERSION.split('.')))
Serhiy Storchakadfa689b2013-09-08 20:29:37 +030024
Serhiy Storchaka92af06b2014-02-02 23:04:24 +020025_tk_patchlevel = None
26def get_tk_patchlevel():
27 global _tk_patchlevel
28 if _tk_patchlevel is None:
29 tcl = Tcl()
Serhiy Storchaka462c3572015-04-22 08:36:03 +030030 patchlevel = tcl.call('info', 'patchlevel')
31 m = re.fullmatch(r'(\d+)\.(\d+)([ab.])(\d+)', patchlevel)
32 major, minor, releaselevel, serial = m.groups()
33 major, minor, serial = int(major), int(minor), int(serial)
34 releaselevel = {'a': 'alpha', 'b': 'beta', '.': 'final'}[releaselevel]
35 if releaselevel == 'final':
36 _tk_patchlevel = major, minor, serial, releaselevel, 0
37 else:
38 _tk_patchlevel = major, minor, 0, releaselevel, serial
Serhiy Storchaka92af06b2014-02-02 23:04:24 +020039 return _tk_patchlevel
40
Benjamin Petersonc4bbc8d2009-01-30 03:39:35 +000041
42class TkinterTest(unittest.TestCase):
43
44 def testFlattenLen(self):
45 # flatten(<object with no length>)
46 self.assertRaises(TypeError, _tkinter._flatten, True)
47
48
David Aschere2b4b322004-02-18 05:59:53 +000049class TclTest(unittest.TestCase):
50
51 def setUp(self):
52 self.interp = Tcl()
Serhiy Storchakacc4290b2013-12-25 17:29:01 +020053 self.wantobjects = self.interp.tk.wantobjects()
David Aschere2b4b322004-02-18 05:59:53 +000054
55 def testEval(self):
56 tcl = self.interp
57 tcl.eval('set a 1')
58 self.assertEqual(tcl.eval('set a'),'1')
59
Serhiy Storchaka1317e142014-02-03 21:24:07 +020060 def test_eval_null_in_result(self):
61 tcl = self.interp
62 self.assertEqual(tcl.eval('set a "a\\0b"'), 'a\x00b')
63
David Aschere2b4b322004-02-18 05:59:53 +000064 def testEvalException(self):
65 tcl = self.interp
66 self.assertRaises(TclError,tcl.eval,'set a')
67
68 def testEvalException2(self):
69 tcl = self.interp
70 self.assertRaises(TclError,tcl.eval,'this is wrong')
71
72 def testCall(self):
73 tcl = self.interp
74 tcl.call('set','a','1')
75 self.assertEqual(tcl.call('set','a'),'1')
76
77 def testCallException(self):
78 tcl = self.interp
79 self.assertRaises(TclError,tcl.call,'set','a')
80
81 def testCallException2(self):
82 tcl = self.interp
83 self.assertRaises(TclError,tcl.call,'this','is','wrong')
84
85 def testSetVar(self):
86 tcl = self.interp
87 tcl.setvar('a','1')
88 self.assertEqual(tcl.eval('set a'),'1')
89
90 def testSetVarArray(self):
91 tcl = self.interp
92 tcl.setvar('a(1)','1')
93 self.assertEqual(tcl.eval('set a(1)'),'1')
94
95 def testGetVar(self):
96 tcl = self.interp
97 tcl.eval('set a 1')
98 self.assertEqual(tcl.getvar('a'),'1')
99
100 def testGetVarArray(self):
101 tcl = self.interp
102 tcl.eval('set a(1) 1')
103 self.assertEqual(tcl.getvar('a(1)'),'1')
104
105 def testGetVarException(self):
106 tcl = self.interp
107 self.assertRaises(TclError,tcl.getvar,'a')
108
109 def testGetVarArrayException(self):
110 tcl = self.interp
111 self.assertRaises(TclError,tcl.getvar,'a(1)')
112
113 def testUnsetVar(self):
114 tcl = self.interp
115 tcl.setvar('a',1)
116 self.assertEqual(tcl.eval('info exists a'),'1')
117 tcl.unsetvar('a')
118 self.assertEqual(tcl.eval('info exists a'),'0')
119
120 def testUnsetVarArray(self):
121 tcl = self.interp
122 tcl.setvar('a(1)',1)
123 tcl.setvar('a(2)',2)
124 self.assertEqual(tcl.eval('info exists a(1)'),'1')
125 self.assertEqual(tcl.eval('info exists a(2)'),'1')
126 tcl.unsetvar('a(1)')
127 self.assertEqual(tcl.eval('info exists a(1)'),'0')
128 self.assertEqual(tcl.eval('info exists a(2)'),'1')
129
130 def testUnsetVarException(self):
131 tcl = self.interp
132 self.assertRaises(TclError,tcl.unsetvar,'a')
Tim Peters27f88362004-07-08 04:22:35 +0000133
Serhiy Storchakaea134da2015-04-02 18:46:50 +0300134 def get_integers(self):
Serhiy Storchaka4c7dc482015-04-02 18:49:14 +0300135 integers = (0, 1, -1, 2**31-1, -2**31, 2**31, -2**31-1, 2**63-1, -2**63)
Serhiy Storchaka3af7a382015-04-22 10:53:08 +0300136 # bignum was added in Tcl 8.5, but its support is able only since 8.5.8
137 if (get_tk_patchlevel() >= (8, 6, 0, 'final') or
138 (8, 5, 8) <= get_tk_patchlevel() < (8, 6)):
Serhiy Storchakaea134da2015-04-02 18:46:50 +0300139 integers += (2**63, -2**63-1, 2**1000, -2**1000)
140 return integers
141
Serhiy Storchaka9f1f4f42014-05-30 14:07:38 +0300142 def test_getint(self):
143 tcl = self.interp.tk
Serhiy Storchakaea134da2015-04-02 18:46:50 +0300144 for i in self.get_integers():
145 self.assertEqual(tcl.getint(' %d ' % i), i)
Serhiy Storchaka2379d542015-04-02 20:07:09 +0300146 if tcl_version >= (8, 5):
147 self.assertEqual(tcl.getint(' %#o ' % i), i)
148 self.assertEqual(tcl.getint((' %#o ' % i).replace('o', '')), i)
Serhiy Storchakaea134da2015-04-02 18:46:50 +0300149 self.assertEqual(tcl.getint(' %#x ' % i), i)
150 if tcl_version < (8, 5): # bignum was added in Tcl 8.5
151 self.assertRaises(TclError, tcl.getint, str(2**1000))
Serhiy Storchaka9f1f4f42014-05-30 14:07:38 +0300152 self.assertEqual(tcl.getint(42), 42)
153 self.assertRaises(TypeError, tcl.getint)
154 self.assertRaises(TypeError, tcl.getint, '42', '10')
155 self.assertRaises(TypeError, tcl.getint, b'42')
156 self.assertRaises(TypeError, tcl.getint, 42.0)
157 self.assertRaises(TclError, tcl.getint, 'a')
158 self.assertRaises((TypeError, ValueError, TclError),
159 tcl.getint, '42\0')
160 self.assertRaises((UnicodeEncodeError, ValueError, TclError),
161 tcl.getint, '42\ud800')
162
163 def test_getdouble(self):
164 tcl = self.interp.tk
165 self.assertEqual(tcl.getdouble(' 42 '), 42.0)
166 self.assertEqual(tcl.getdouble(' 42.5 '), 42.5)
167 self.assertEqual(tcl.getdouble(42.5), 42.5)
Serhiy Storchaka645058d2015-05-06 14:00:04 +0300168 self.assertEqual(tcl.getdouble(42), 42.0)
Serhiy Storchaka9f1f4f42014-05-30 14:07:38 +0300169 self.assertRaises(TypeError, tcl.getdouble)
170 self.assertRaises(TypeError, tcl.getdouble, '42.5', '10')
171 self.assertRaises(TypeError, tcl.getdouble, b'42.5')
Serhiy Storchaka9f1f4f42014-05-30 14:07:38 +0300172 self.assertRaises(TclError, tcl.getdouble, 'a')
173 self.assertRaises((TypeError, ValueError, TclError),
174 tcl.getdouble, '42.5\0')
175 self.assertRaises((UnicodeEncodeError, ValueError, TclError),
176 tcl.getdouble, '42.5\ud800')
177
178 def test_getboolean(self):
179 tcl = self.interp.tk
180 self.assertIs(tcl.getboolean('on'), True)
181 self.assertIs(tcl.getboolean('1'), True)
Serhiy Storchaka9a6e2012015-04-04 12:43:01 +0300182 self.assertIs(tcl.getboolean(42), True)
183 self.assertIs(tcl.getboolean(0), False)
Serhiy Storchaka9f1f4f42014-05-30 14:07:38 +0300184 self.assertRaises(TypeError, tcl.getboolean)
185 self.assertRaises(TypeError, tcl.getboolean, 'on', '1')
186 self.assertRaises(TypeError, tcl.getboolean, b'on')
187 self.assertRaises(TypeError, tcl.getboolean, 1.0)
188 self.assertRaises(TclError, tcl.getboolean, 'a')
189 self.assertRaises((TypeError, ValueError, TclError),
190 tcl.getboolean, 'on\0')
191 self.assertRaises((UnicodeEncodeError, ValueError, TclError),
192 tcl.getboolean, 'on\ud800')
193
David Aschere2b4b322004-02-18 05:59:53 +0000194 def testEvalFile(self):
195 tcl = self.interp
Hai Shi79bb2c92020-08-06 19:51:29 +0800196 with open(os_helper.TESTFN, 'w') as f:
197 self.addCleanup(os_helper.unlink, os_helper.TESTFN)
Serhiy Storchaka1317e142014-02-03 21:24:07 +0200198 f.write("""set a 1
199 set b 2
200 set c [ expr $a + $b ]
201 """)
Hai Shi79bb2c92020-08-06 19:51:29 +0800202 tcl.evalfile(os_helper.TESTFN)
David Aschere2b4b322004-02-18 05:59:53 +0000203 self.assertEqual(tcl.eval('set a'),'1')
204 self.assertEqual(tcl.eval('set b'),'2')
205 self.assertEqual(tcl.eval('set c'),'3')
206
Serhiy Storchaka1317e142014-02-03 21:24:07 +0200207 def test_evalfile_null_in_result(self):
208 tcl = self.interp
Hai Shi79bb2c92020-08-06 19:51:29 +0800209 with open(os_helper.TESTFN, 'w') as f:
210 self.addCleanup(os_helper.unlink, os_helper.TESTFN)
Serhiy Storchaka1317e142014-02-03 21:24:07 +0200211 f.write("""
212 set a "a\0b"
213 set b "a\\0b"
214 """)
Hai Shi79bb2c92020-08-06 19:51:29 +0800215 tcl.evalfile(os_helper.TESTFN)
Serhiy Storchaka1317e142014-02-03 21:24:07 +0200216 self.assertEqual(tcl.eval('set a'), 'a\x00b')
217 self.assertEqual(tcl.eval('set b'), 'a\x00b')
218
David Aschere2b4b322004-02-18 05:59:53 +0000219 def testEvalFileException(self):
220 tcl = self.interp
221 filename = "doesnotexists"
222 try:
223 os.remove(filename)
Guido van Rossumb940e112007-01-10 16:19:56 +0000224 except Exception as e:
David Aschere2b4b322004-02-18 05:59:53 +0000225 pass
226 self.assertRaises(TclError,tcl.evalfile,filename)
227
David Aschere2b4b322004-02-18 05:59:53 +0000228 def testPackageRequireException(self):
229 tcl = self.interp
230 self.assertRaises(TclError,tcl.eval,'package require DNE')
231
Hirokazu Yamamotodda7fdf2010-09-23 15:28:35 +0000232 @unittest.skipUnless(sys.platform == 'win32', 'Requires Windows')
Martin v. Löwis2d5157e2010-06-04 19:50:26 +0000233 def testLoadWithUNC(self):
Martin v. Löwis2d5157e2010-06-04 19:50:26 +0000234 # Build a UNC path from the regular path.
235 # Something like
236 # \\%COMPUTERNAME%\c$\python27\python.exe
237
238 fullname = os.path.abspath(sys.executable)
239 if fullname[1] != ':':
Hirokazu Yamamotodda7fdf2010-09-23 15:28:35 +0000240 raise unittest.SkipTest('Absolute path should have drive part')
Martin v. Löwis2d5157e2010-06-04 19:50:26 +0000241 unc_name = r'\\%s\%s$\%s' % (os.environ['COMPUTERNAME'],
242 fullname[0],
243 fullname[3:])
Hirokazu Yamamotodda7fdf2010-09-23 15:28:35 +0000244 if not os.path.exists(unc_name):
245 raise unittest.SkipTest('Cannot connect to UNC Path')
Martin v. Löwis2d5157e2010-06-04 19:50:26 +0000246
Hai Shi79bb2c92020-08-06 19:51:29 +0800247 with os_helper.EnvironmentVarGuard() as env:
Martin v. Löwis2d5157e2010-06-04 19:50:26 +0000248 env.unset("TCL_LIBRARY")
Zachary Ware83fd0a82015-10-12 23:27:58 -0500249 stdout = subprocess.check_output(
250 [unc_name, '-c', 'import tkinter; print(tkinter)'])
Martin v. Löwis2d5157e2010-06-04 19:50:26 +0000251
Zachary Ware83fd0a82015-10-12 23:27:58 -0500252 self.assertIn(b'tkinter', stdout)
Martin v. Löwis2d5157e2010-06-04 19:50:26 +0000253
Serhiy Storchakafc055252014-02-03 20:41:34 +0200254 def test_exprstring(self):
255 tcl = self.interp
256 tcl.call('set', 'a', 3)
257 tcl.call('set', 'b', 6)
258 def check(expr, expected):
259 result = tcl.exprstring(expr)
260 self.assertEqual(result, expected)
261 self.assertIsInstance(result, str)
262
263 self.assertRaises(TypeError, tcl.exprstring)
264 self.assertRaises(TypeError, tcl.exprstring, '8.2', '+6')
265 self.assertRaises(TypeError, tcl.exprstring, b'8.2 + 6')
266 self.assertRaises(TclError, tcl.exprstring, 'spam')
267 check('', '0')
268 check('8.2 + 6', '14.2')
Serhiy Storchakafc055252014-02-03 20:41:34 +0200269 check('3.1 + $a', '6.1')
270 check('2 + "$a.$b"', '5.6')
271 check('4*[llength "6 2"]', '8')
272 check('{word one} < "word $a"', '0')
273 check('4*2 < 7', '0')
274 check('hypot($a, 4)', '5.0')
275 check('5 / 4', '1')
276 check('5 / 4.0', '1.25')
277 check('5 / ( [string length "abcd"] + 0.0 )', '1.25')
278 check('20.0/5.0', '4.0')
279 check('"0x03" > "2"', '1')
280 check('[string length "a\xbd\u20ac"]', '3')
281 check(r'[string length "a\xbd\u20ac"]', '3')
282 check('"abc"', 'abc')
283 check('"a\xbd\u20ac"', 'a\xbd\u20ac')
284 check(r'"a\xbd\u20ac"', 'a\xbd\u20ac')
Serhiy Storchaka1317e142014-02-03 21:24:07 +0200285 check(r'"a\0b"', 'a\x00b')
Serhiy Storchakaea134da2015-04-02 18:46:50 +0300286 if tcl_version >= (8, 5): # bignum was added in Tcl 8.5
Serhiy Storchaka160f8922014-02-03 22:31:09 +0200287 check('2**64', str(2**64))
Serhiy Storchakafc055252014-02-03 20:41:34 +0200288
289 def test_exprdouble(self):
290 tcl = self.interp
291 tcl.call('set', 'a', 3)
292 tcl.call('set', 'b', 6)
293 def check(expr, expected):
294 result = tcl.exprdouble(expr)
295 self.assertEqual(result, expected)
296 self.assertIsInstance(result, float)
297
298 self.assertRaises(TypeError, tcl.exprdouble)
299 self.assertRaises(TypeError, tcl.exprdouble, '8.2', '+6')
300 self.assertRaises(TypeError, tcl.exprdouble, b'8.2 + 6')
301 self.assertRaises(TclError, tcl.exprdouble, 'spam')
302 check('', 0.0)
303 check('8.2 + 6', 14.2)
Serhiy Storchakafc055252014-02-03 20:41:34 +0200304 check('3.1 + $a', 6.1)
305 check('2 + "$a.$b"', 5.6)
306 check('4*[llength "6 2"]', 8.0)
307 check('{word one} < "word $a"', 0.0)
308 check('4*2 < 7', 0.0)
309 check('hypot($a, 4)', 5.0)
310 check('5 / 4', 1.0)
311 check('5 / 4.0', 1.25)
312 check('5 / ( [string length "abcd"] + 0.0 )', 1.25)
313 check('20.0/5.0', 4.0)
314 check('"0x03" > "2"', 1.0)
315 check('[string length "a\xbd\u20ac"]', 3.0)
316 check(r'[string length "a\xbd\u20ac"]', 3.0)
317 self.assertRaises(TclError, tcl.exprdouble, '"abc"')
Serhiy Storchakaea134da2015-04-02 18:46:50 +0300318 if tcl_version >= (8, 5): # bignum was added in Tcl 8.5
Serhiy Storchaka160f8922014-02-03 22:31:09 +0200319 check('2**64', float(2**64))
Serhiy Storchakafc055252014-02-03 20:41:34 +0200320
321 def test_exprlong(self):
322 tcl = self.interp
323 tcl.call('set', 'a', 3)
324 tcl.call('set', 'b', 6)
325 def check(expr, expected):
326 result = tcl.exprlong(expr)
327 self.assertEqual(result, expected)
328 self.assertIsInstance(result, int)
329
330 self.assertRaises(TypeError, tcl.exprlong)
331 self.assertRaises(TypeError, tcl.exprlong, '8.2', '+6')
332 self.assertRaises(TypeError, tcl.exprlong, b'8.2 + 6')
333 self.assertRaises(TclError, tcl.exprlong, 'spam')
334 check('', 0)
335 check('8.2 + 6', 14)
Serhiy Storchakafc055252014-02-03 20:41:34 +0200336 check('3.1 + $a', 6)
337 check('2 + "$a.$b"', 5)
338 check('4*[llength "6 2"]', 8)
339 check('{word one} < "word $a"', 0)
340 check('4*2 < 7', 0)
341 check('hypot($a, 4)', 5)
342 check('5 / 4', 1)
343 check('5 / 4.0', 1)
344 check('5 / ( [string length "abcd"] + 0.0 )', 1)
345 check('20.0/5.0', 4)
346 check('"0x03" > "2"', 1)
347 check('[string length "a\xbd\u20ac"]', 3)
348 check(r'[string length "a\xbd\u20ac"]', 3)
349 self.assertRaises(TclError, tcl.exprlong, '"abc"')
Serhiy Storchakaea134da2015-04-02 18:46:50 +0300350 if tcl_version >= (8, 5): # bignum was added in Tcl 8.5
Serhiy Storchaka160f8922014-02-03 22:31:09 +0200351 self.assertRaises(TclError, tcl.exprlong, '2**64')
Serhiy Storchakafc055252014-02-03 20:41:34 +0200352
353 def test_exprboolean(self):
354 tcl = self.interp
355 tcl.call('set', 'a', 3)
356 tcl.call('set', 'b', 6)
357 def check(expr, expected):
358 result = tcl.exprboolean(expr)
359 self.assertEqual(result, expected)
360 self.assertIsInstance(result, int)
361 self.assertNotIsInstance(result, bool)
362
363 self.assertRaises(TypeError, tcl.exprboolean)
364 self.assertRaises(TypeError, tcl.exprboolean, '8.2', '+6')
365 self.assertRaises(TypeError, tcl.exprboolean, b'8.2 + 6')
366 self.assertRaises(TclError, tcl.exprboolean, 'spam')
367 check('', False)
368 for value in ('0', 'false', 'no', 'off'):
369 check(value, False)
370 check('"%s"' % value, False)
371 check('{%s}' % value, False)
372 for value in ('1', 'true', 'yes', 'on'):
373 check(value, True)
374 check('"%s"' % value, True)
375 check('{%s}' % value, True)
376 check('8.2 + 6', True)
Serhiy Storchakafc055252014-02-03 20:41:34 +0200377 check('3.1 + $a', True)
378 check('2 + "$a.$b"', True)
379 check('4*[llength "6 2"]', True)
380 check('{word one} < "word $a"', False)
381 check('4*2 < 7', False)
382 check('hypot($a, 4)', True)
383 check('5 / 4', True)
384 check('5 / 4.0', True)
385 check('5 / ( [string length "abcd"] + 0.0 )', True)
386 check('20.0/5.0', True)
387 check('"0x03" > "2"', True)
388 check('[string length "a\xbd\u20ac"]', True)
389 check(r'[string length "a\xbd\u20ac"]', True)
390 self.assertRaises(TclError, tcl.exprboolean, '"abc"')
Serhiy Storchakaea134da2015-04-02 18:46:50 +0300391 if tcl_version >= (8, 5): # bignum was added in Tcl 8.5
Serhiy Storchaka160f8922014-02-03 22:31:09 +0200392 check('2**64', True)
Serhiy Storchakafc055252014-02-03 20:41:34 +0200393
Serhiy Storchakaa5a4bd72015-04-02 19:57:52 +0300394 @unittest.skipUnless(tcl_version >= (8, 5), 'requires Tcl version >= 8.5')
Serhiy Storchakaf7de3dd2015-04-02 10:35:57 +0300395 def test_booleans(self):
396 tcl = self.interp
397 def check(expr, expected):
398 result = tcl.call('expr', expr)
Serhiy Storchaka9171fe52015-04-02 11:46:07 +0300399 if tcl.wantobjects():
400 self.assertEqual(result, expected)
401 self.assertIsInstance(result, int)
402 else:
403 self.assertIn(result, (expr, str(int(expected))))
404 self.assertIsInstance(result, str)
Serhiy Storchakaf7de3dd2015-04-02 10:35:57 +0300405 check('true', True)
406 check('yes', True)
407 check('on', True)
408 check('false', False)
409 check('no', False)
410 check('off', False)
411 check('1 < 2', True)
412 check('1 > 2', False)
413
Serhiy Storchakaea134da2015-04-02 18:46:50 +0300414 def test_expr_bignum(self):
415 tcl = self.interp
416 for i in self.get_integers():
417 result = tcl.call('expr', str(i))
418 if self.wantobjects:
419 self.assertEqual(result, i)
420 self.assertIsInstance(result, int)
421 else:
422 self.assertEqual(result, str(i))
423 self.assertIsInstance(result, str)
424 if tcl_version < (8, 5): # bignum was added in Tcl 8.5
Serhiy Storchaka2379d542015-04-02 20:07:09 +0300425 self.assertRaises(TclError, tcl.call, 'expr', str(2**1000))
Serhiy Storchakaea134da2015-04-02 18:46:50 +0300426
Serhiy Storchakadf4bb462013-02-07 15:40:03 +0200427 def test_passing_values(self):
428 def passValue(value):
429 return self.interp.call('set', '_', value)
430
Serhiy Storchakacc4290b2013-12-25 17:29:01 +0200431 self.assertEqual(passValue(True), True if self.wantobjects else '1')
432 self.assertEqual(passValue(False), False if self.wantobjects else '0')
Serhiy Storchakadf4bb462013-02-07 15:40:03 +0200433 self.assertEqual(passValue('string'), 'string')
434 self.assertEqual(passValue('string\u20ac'), 'string\u20ac')
Serhiy Storchaka06cb94b2019-10-04 13:09:52 +0300435 self.assertEqual(passValue('string\U0001f4bb'), 'string\U0001f4bb')
Serhiy Storchaka1317e142014-02-03 21:24:07 +0200436 self.assertEqual(passValue('str\x00ing'), 'str\x00ing')
437 self.assertEqual(passValue('str\x00ing\xbd'), 'str\x00ing\xbd')
438 self.assertEqual(passValue('str\x00ing\u20ac'), 'str\x00ing\u20ac')
Serhiy Storchaka06cb94b2019-10-04 13:09:52 +0300439 self.assertEqual(passValue('str\x00ing\U0001f4bb'),
440 'str\x00ing\U0001f4bb')
Serhiy Storchaka74596a82014-07-30 18:33:13 +0300441 self.assertEqual(passValue(b'str\x00ing'),
442 b'str\x00ing' if self.wantobjects else 'str\x00ing')
443 self.assertEqual(passValue(b'str\xc0\x80ing'),
444 b'str\xc0\x80ing' if self.wantobjects else 'str\xc0\x80ing')
445 self.assertEqual(passValue(b'str\xbding'),
446 b'str\xbding' if self.wantobjects else 'str\xbding')
Serhiy Storchakaea134da2015-04-02 18:46:50 +0300447 for i in self.get_integers():
Serhiy Storchakacc4290b2013-12-25 17:29:01 +0200448 self.assertEqual(passValue(i), i if self.wantobjects else str(i))
Serhiy Storchakaea134da2015-04-02 18:46:50 +0300449 if tcl_version < (8, 5): # bignum was added in Tcl 8.5
450 self.assertEqual(passValue(2**1000), str(2**1000))
Serhiy Storchakadf4bb462013-02-07 15:40:03 +0200451 for f in (0.0, 1.0, -1.0, 1/3,
452 sys.float_info.min, sys.float_info.max,
453 -sys.float_info.min, -sys.float_info.max):
Serhiy Storchakacc4290b2013-12-25 17:29:01 +0200454 if self.wantobjects:
Serhiy Storchakadf4bb462013-02-07 15:40:03 +0200455 self.assertEqual(passValue(f), f)
Serhiy Storchakacc4290b2013-12-25 17:29:01 +0200456 else:
457 self.assertEqual(float(passValue(f)), f)
458 if self.wantobjects:
459 f = passValue(float('nan'))
460 self.assertNotEqual(f, f)
461 self.assertEqual(passValue(float('inf')), float('inf'))
462 self.assertEqual(passValue(-float('inf')), -float('inf'))
463 else:
Serhiy Storchakacc4290b2013-12-25 17:29:01 +0200464 self.assertEqual(float(passValue(float('inf'))), float('inf'))
465 self.assertEqual(float(passValue(-float('inf'))), -float('inf'))
Serhiy Storchaka6f1435c2014-07-07 14:57:08 +0300466 # XXX NaN representation can be not parsable by float()
Serhiy Storchakacc4290b2013-12-25 17:29:01 +0200467 self.assertEqual(passValue((1, '2', (3.4,))),
468 (1, '2', (3.4,)) if self.wantobjects else '1 2 3.4')
Serhiy Storchaka2b00c492014-05-21 17:12:21 +0300469 self.assertEqual(passValue(['a', ['b', 'c']]),
470 ('a', ('b', 'c')) if self.wantobjects else 'a {b c}')
Martin v. Löwis2d5157e2010-06-04 19:50:26 +0000471
Serhiy Storchaka4b730162014-01-23 09:44:05 +0200472 def test_user_command(self):
473 result = None
474 def testfunc(arg):
475 nonlocal result
476 result = arg
477 return arg
478 self.interp.createcommand('testfunc', testfunc)
Antoine Pitrou220cc212014-02-23 19:39:06 +0100479 self.addCleanup(self.interp.tk.deletecommand, 'testfunc')
Serhiy Storchakad6ec3092014-08-18 17:47:29 +0300480 def check(value, expected=None, *, eq=self.assertEqual):
481 if expected is None:
482 expected = value
483 nonlocal result
484 result = None
Serhiy Storchakabdf0cb52014-01-23 16:48:44 +0200485 r = self.interp.call('testfunc', value)
486 self.assertIsInstance(result, str)
487 eq(result, expected)
488 self.assertIsInstance(r, str)
489 eq(r, expected)
490 def float_eq(actual, expected):
Serhiy Storchakabdf0cb52014-01-23 16:48:44 +0200491 self.assertAlmostEqual(float(actual), expected,
492 delta=abs(expected) * 1e-10)
Serhiy Storchaka4b730162014-01-23 09:44:05 +0200493
494 check(True, '1')
495 check(False, '0')
Serhiy Storchakad6ec3092014-08-18 17:47:29 +0300496 check('string')
497 check('string\xbd')
498 check('string\u20ac')
Serhiy Storchaka06cb94b2019-10-04 13:09:52 +0300499 check('string\U0001f4bb')
Serhiy Storchakaabf68ce2014-09-11 10:57:13 +0300500 check('')
Serhiy Storchaka1317e142014-02-03 21:24:07 +0200501 check(b'string', 'string')
Serhiy Storchaka74596a82014-07-30 18:33:13 +0300502 check(b'string\xe2\x82\xac', 'string\xe2\x82\xac')
503 check(b'string\xbd', 'string\xbd')
Serhiy Storchakaabf68ce2014-09-11 10:57:13 +0300504 check(b'', '')
Serhiy Storchakad6ec3092014-08-18 17:47:29 +0300505 check('str\x00ing')
506 check('str\x00ing\xbd')
507 check('str\x00ing\u20ac')
Serhiy Storchaka74596a82014-07-30 18:33:13 +0300508 check(b'str\x00ing', 'str\x00ing')
509 check(b'str\xc0\x80ing', 'str\xc0\x80ing')
510 check(b'str\xc0\x80ing\xe2\x82\xac', 'str\xc0\x80ing\xe2\x82\xac')
Serhiy Storchakaea134da2015-04-02 18:46:50 +0300511 for i in self.get_integers():
Serhiy Storchaka4b730162014-01-23 09:44:05 +0200512 check(i, str(i))
Serhiy Storchakaea134da2015-04-02 18:46:50 +0300513 if tcl_version < (8, 5): # bignum was added in Tcl 8.5
514 check(2**1000, str(2**1000))
Serhiy Storchakabdf0cb52014-01-23 16:48:44 +0200515 for f in (0.0, 1.0, -1.0):
516 check(f, repr(f))
517 for f in (1/3.0, sys.float_info.min, sys.float_info.max,
Serhiy Storchaka4b730162014-01-23 09:44:05 +0200518 -sys.float_info.min, -sys.float_info.max):
Serhiy Storchakad6ec3092014-08-18 17:47:29 +0300519 check(f, eq=float_eq)
520 check(float('inf'), eq=float_eq)
521 check(-float('inf'), eq=float_eq)
Serhiy Storchaka6f1435c2014-07-07 14:57:08 +0300522 # XXX NaN representation can be not parsable by float()
Serhiy Storchaka4b730162014-01-23 09:44:05 +0200523 check((), '')
524 check((1, (2,), (3, 4), '5 6', ()), '1 2 {3 4} {5 6} {}')
Serhiy Storchaka2b00c492014-05-21 17:12:21 +0300525 check([1, [2,], [3, 4], '5 6', []], '1 2 {3 4} {5 6} {}')
Serhiy Storchaka4b730162014-01-23 09:44:05 +0200526
Serhiy Storchaka275d5fd2013-07-11 20:34:47 +0300527 def test_splitlist(self):
528 splitlist = self.interp.tk.splitlist
529 call = self.interp.tk.call
530 self.assertRaises(TypeError, splitlist)
531 self.assertRaises(TypeError, splitlist, 'a', 'b')
532 self.assertRaises(TypeError, splitlist, 2)
533 testcases = [
534 ('2', ('2',)),
535 ('', ()),
536 ('{}', ('',)),
537 ('""', ('',)),
538 ('a\n b\t\r c\n ', ('a', 'b', 'c')),
539 (b'a\n b\t\r c\n ', ('a', 'b', 'c')),
540 ('a \u20ac', ('a', '\u20ac')),
Serhiy Storchaka06cb94b2019-10-04 13:09:52 +0300541 ('a \U0001f4bb', ('a', '\U0001f4bb')),
Serhiy Storchaka275d5fd2013-07-11 20:34:47 +0300542 (b'a \xe2\x82\xac', ('a', '\u20ac')),
Serhiy Storchaka1317e142014-02-03 21:24:07 +0200543 (b'a\xc0\x80b c\xc0\x80d', ('a\x00b', 'c\x00d')),
Serhiy Storchaka275d5fd2013-07-11 20:34:47 +0300544 ('a {b c}', ('a', 'b c')),
545 (r'a b\ c', ('a', 'b c')),
546 (('a', 'b c'), ('a', 'b c')),
547 ('a 2', ('a', '2')),
548 (('a', 2), ('a', 2)),
549 ('a 3.4', ('a', '3.4')),
550 (('a', 3.4), ('a', 3.4)),
551 ((), ()),
Serhiy Storchaka2b00c492014-05-21 17:12:21 +0300552 ([], ()),
553 (['a', ['b', 'c']], ('a', ['b', 'c'])),
Serhiy Storchakacc4290b2013-12-25 17:29:01 +0200554 (call('list', 1, '2', (3.4,)),
555 (1, '2', (3.4,)) if self.wantobjects else
556 ('1', '2', '3.4')),
Serhiy Storchaka275d5fd2013-07-11 20:34:47 +0300557 ]
Victor Stinnerece38d92014-09-04 09:53:16 +0200558 tk_patchlevel = get_tk_patchlevel()
Serhiy Storchakadfa689b2013-09-08 20:29:37 +0300559 if tcl_version >= (8, 5):
Victor Stinnerece38d92014-09-04 09:53:16 +0200560 if not self.wantobjects or tk_patchlevel < (8, 5, 5):
Serhiy Storchaka92af06b2014-02-02 23:04:24 +0200561 # Before 8.5.5 dicts were converted to lists through string
Serhiy Storchaka74596a82014-07-30 18:33:13 +0300562 expected = ('12', '\u20ac', '\xe2\x82\xac', '3.4')
Serhiy Storchaka92af06b2014-02-02 23:04:24 +0200563 else:
Serhiy Storchaka74596a82014-07-30 18:33:13 +0300564 expected = (12, '\u20ac', b'\xe2\x82\xac', (3.4,))
Serhiy Storchakadfa689b2013-09-08 20:29:37 +0300565 testcases += [
Serhiy Storchaka92af06b2014-02-02 23:04:24 +0200566 (call('dict', 'create', 12, '\u20ac', b'\xe2\x82\xac', (3.4,)),
567 expected),
Serhiy Storchakadfa689b2013-09-08 20:29:37 +0300568 ]
Victor Stinnerece38d92014-09-04 09:53:16 +0200569 dbg_info = ('want objects? %s, Tcl version: %s, Tk patchlevel: %s'
570 % (self.wantobjects, tcl_version, tk_patchlevel))
Serhiy Storchaka275d5fd2013-07-11 20:34:47 +0300571 for arg, res in testcases:
Victor Stinnerece38d92014-09-04 09:53:16 +0200572 self.assertEqual(splitlist(arg), res,
573 'arg=%a, %s' % (arg, dbg_info))
Serhiy Storchaka275d5fd2013-07-11 20:34:47 +0300574 self.assertRaises(TclError, splitlist, '{')
575
576 def test_split(self):
577 split = self.interp.tk.split
578 call = self.interp.tk.call
Serhiy Storchakad05b0002019-10-08 14:31:35 +0300579 with warnings.catch_warnings():
580 warnings.filterwarnings('ignore', r'\bsplit\b.*\bsplitlist\b',
581 DeprecationWarning)
582 self.assertRaises(TypeError, split)
583 self.assertRaises(TypeError, split, 'a', 'b')
584 self.assertRaises(TypeError, split, 2)
Serhiy Storchaka275d5fd2013-07-11 20:34:47 +0300585 testcases = [
586 ('2', '2'),
587 ('', ''),
588 ('{}', ''),
589 ('""', ''),
590 ('{', '{'),
591 ('a\n b\t\r c\n ', ('a', 'b', 'c')),
592 (b'a\n b\t\r c\n ', ('a', 'b', 'c')),
593 ('a \u20ac', ('a', '\u20ac')),
594 (b'a \xe2\x82\xac', ('a', '\u20ac')),
Serhiy Storchaka1317e142014-02-03 21:24:07 +0200595 (b'a\xc0\x80b', 'a\x00b'),
596 (b'a\xc0\x80b c\xc0\x80d', ('a\x00b', 'c\x00d')),
597 (b'{a\xc0\x80b c\xc0\x80d', '{a\x00b c\x00d'),
Serhiy Storchaka275d5fd2013-07-11 20:34:47 +0300598 ('a {b c}', ('a', ('b', 'c'))),
599 (r'a b\ c', ('a', ('b', 'c'))),
600 (('a', b'b c'), ('a', ('b', 'c'))),
601 (('a', 'b c'), ('a', ('b', 'c'))),
602 ('a 2', ('a', '2')),
603 (('a', 2), ('a', 2)),
604 ('a 3.4', ('a', '3.4')),
605 (('a', 3.4), ('a', 3.4)),
606 (('a', (2, 3.4)), ('a', (2, 3.4))),
607 ((), ()),
Serhiy Storchaka2b00c492014-05-21 17:12:21 +0300608 ([], ()),
609 (['a', 'b c'], ('a', ('b', 'c'))),
610 (['a', ['b', 'c']], ('a', ('b', 'c'))),
Serhiy Storchakacc4290b2013-12-25 17:29:01 +0200611 (call('list', 1, '2', (3.4,)),
612 (1, '2', (3.4,)) if self.wantobjects else
613 ('1', '2', '3.4')),
Serhiy Storchaka275d5fd2013-07-11 20:34:47 +0300614 ]
Serhiy Storchakadfa689b2013-09-08 20:29:37 +0300615 if tcl_version >= (8, 5):
Serhiy Storchaka92af06b2014-02-02 23:04:24 +0200616 if not self.wantobjects or get_tk_patchlevel() < (8, 5, 5):
617 # Before 8.5.5 dicts were converted to lists through string
Serhiy Storchaka74596a82014-07-30 18:33:13 +0300618 expected = ('12', '\u20ac', '\xe2\x82\xac', '3.4')
Serhiy Storchaka92af06b2014-02-02 23:04:24 +0200619 else:
Serhiy Storchaka74596a82014-07-30 18:33:13 +0300620 expected = (12, '\u20ac', b'\xe2\x82\xac', (3.4,))
Serhiy Storchakadfa689b2013-09-08 20:29:37 +0300621 testcases += [
622 (call('dict', 'create', 12, '\u20ac', b'\xe2\x82\xac', (3.4,)),
Serhiy Storchaka92af06b2014-02-02 23:04:24 +0200623 expected),
Serhiy Storchakadfa689b2013-09-08 20:29:37 +0300624 ]
Serhiy Storchaka275d5fd2013-07-11 20:34:47 +0300625 for arg, res in testcases:
Serhiy Storchakad05b0002019-10-08 14:31:35 +0300626 with self.assertWarns(DeprecationWarning):
627 self.assertEqual(split(arg), res, msg=arg)
Serhiy Storchaka275d5fd2013-07-11 20:34:47 +0300628
Serhiy Storchaka8f0a1d02014-09-06 22:47:58 +0300629 def test_splitdict(self):
630 splitdict = tkinter._splitdict
631 tcl = self.interp.tk
632
633 arg = '-a {1 2 3} -something foo status {}'
634 self.assertEqual(splitdict(tcl, arg, False),
635 {'-a': '1 2 3', '-something': 'foo', 'status': ''})
636 self.assertEqual(splitdict(tcl, arg),
637 {'a': '1 2 3', 'something': 'foo', 'status': ''})
638
639 arg = ('-a', (1, 2, 3), '-something', 'foo', 'status', '{}')
640 self.assertEqual(splitdict(tcl, arg, False),
641 {'-a': (1, 2, 3), '-something': 'foo', 'status': '{}'})
642 self.assertEqual(splitdict(tcl, arg),
643 {'a': (1, 2, 3), 'something': 'foo', 'status': '{}'})
644
645 self.assertRaises(RuntimeError, splitdict, tcl, '-a b -c ')
646 self.assertRaises(RuntimeError, splitdict, tcl, ('-a', 'b', '-c'))
647
648 arg = tcl.call('list',
649 '-a', (1, 2, 3), '-something', 'foo', 'status', ())
650 self.assertEqual(splitdict(tcl, arg),
651 {'a': (1, 2, 3) if self.wantobjects else '1 2 3',
652 'something': 'foo', 'status': ''})
653
654 if tcl_version >= (8, 5):
655 arg = tcl.call('dict', 'create',
656 '-a', (1, 2, 3), '-something', 'foo', 'status', ())
657 if not self.wantobjects or get_tk_patchlevel() < (8, 5, 5):
658 # Before 8.5.5 dicts were converted to lists through string
659 expected = {'a': '1 2 3', 'something': 'foo', 'status': ''}
660 else:
661 expected = {'a': (1, 2, 3), 'something': 'foo', 'status': ''}
662 self.assertEqual(splitdict(tcl, arg), expected)
663
Serhiy Storchaka5bb5bbf2018-06-30 09:20:28 +0300664 def test_join(self):
665 join = tkinter._join
666 tcl = self.interp.tk
667 def unpack(s):
668 return tcl.call('lindex', s, 0)
669 def check(value):
670 self.assertEqual(unpack(join([value])), value)
671 self.assertEqual(unpack(join([value, 0])), value)
672 self.assertEqual(unpack(unpack(join([[value]]))), value)
673 self.assertEqual(unpack(unpack(join([[value, 0]]))), value)
674 self.assertEqual(unpack(unpack(join([[value], 0]))), value)
675 self.assertEqual(unpack(unpack(join([[value, 0], 0]))), value)
676 check('')
677 check('spam')
678 check('sp am')
679 check('sp\tam')
680 check('sp\nam')
681 check(' \t\n')
682 check('{spam}')
683 check('{sp am}')
684 check('"spam"')
685 check('"sp am"')
686 check('{"spam"}')
687 check('"{spam}"')
688 check('sp\\am')
689 check('"sp\\am"')
690 check('"{}" "{}"')
691 check('"\\')
692 check('"{')
693 check('"}')
694 check('\n\\')
695 check('\n{')
696 check('\n}')
697 check('\\\n')
698 check('{\n')
699 check('}\n')
700
Serhiy Storchakae3f1b092016-05-08 20:46:22 +0300701 def test_new_tcl_obj(self):
702 self.assertRaises(TypeError, _tkinter.Tcl_Obj)
Neal Norwitz63dfece2004-02-19 02:37:29 +0000703
Serhiy Storchaka9e6b9752013-08-21 21:38:21 +0300704class BigmemTclTest(unittest.TestCase):
705
706 def setUp(self):
707 self.interp = Tcl()
708
Serhiy Storchaka5cfc79d2014-02-07 10:06:39 +0200709 @support.cpython_only
710 @unittest.skipUnless(INT_MAX < PY_SSIZE_T_MAX, "needs UINT_MAX < SIZE_MAX")
711 @support.bigmemtest(size=INT_MAX + 1, memuse=5, dry_run=False)
Serhiy Storchaka79851d72014-05-30 14:24:03 +0300712 def test_huge_string_call(self, size):
Serhiy Storchaka9e6b9752013-08-21 21:38:21 +0300713 value = ' ' * size
Serhiy Storchaka27c623c2017-10-03 22:39:55 +0300714 self.assertRaises(OverflowError, self.interp.call, 'string', 'index', value, 0)
Serhiy Storchaka9e6b9752013-08-21 21:38:21 +0300715
Serhiy Storchaka79851d72014-05-30 14:24:03 +0300716 @support.cpython_only
717 @unittest.skipUnless(INT_MAX < PY_SSIZE_T_MAX, "needs UINT_MAX < SIZE_MAX")
Serhiy Storchaka27c623c2017-10-03 22:39:55 +0300718 @support.bigmemtest(size=INT_MAX + 1, memuse=2, dry_run=False)
Serhiy Storchaka79851d72014-05-30 14:24:03 +0300719 def test_huge_string_builtins(self, size):
Serhiy Storchaka27c623c2017-10-03 22:39:55 +0300720 tk = self.interp.tk
Serhiy Storchaka79851d72014-05-30 14:24:03 +0300721 value = '1' + ' ' * size
Serhiy Storchaka27c623c2017-10-03 22:39:55 +0300722 self.assertRaises(OverflowError, tk.getint, value)
723 self.assertRaises(OverflowError, tk.getdouble, value)
724 self.assertRaises(OverflowError, tk.getboolean, value)
725 self.assertRaises(OverflowError, tk.eval, value)
726 self.assertRaises(OverflowError, tk.evalfile, value)
727 self.assertRaises(OverflowError, tk.record, value)
728 self.assertRaises(OverflowError, tk.adderrorinfo, value)
729 self.assertRaises(OverflowError, tk.setvar, value, 'x', 'a')
730 self.assertRaises(OverflowError, tk.setvar, 'x', value, 'a')
731 self.assertRaises(OverflowError, tk.unsetvar, value)
732 self.assertRaises(OverflowError, tk.unsetvar, 'x', value)
733 self.assertRaises(OverflowError, tk.adderrorinfo, value)
734 self.assertRaises(OverflowError, tk.exprstring, value)
735 self.assertRaises(OverflowError, tk.exprlong, value)
736 self.assertRaises(OverflowError, tk.exprboolean, value)
737 self.assertRaises(OverflowError, tk.splitlist, value)
738 self.assertRaises(OverflowError, tk.split, value)
739 self.assertRaises(OverflowError, tk.createcommand, value, max)
740 self.assertRaises(OverflowError, tk.deletecommand, value)
741
742 @support.cpython_only
743 @unittest.skipUnless(INT_MAX < PY_SSIZE_T_MAX, "needs UINT_MAX < SIZE_MAX")
744 @support.bigmemtest(size=INT_MAX + 1, memuse=6, dry_run=False)
745 def test_huge_string_builtins2(self, size):
746 # These commands require larger memory for possible error messages
747 tk = self.interp.tk
748 value = '1' + ' ' * size
749 self.assertRaises(OverflowError, tk.evalfile, value)
750 self.assertRaises(OverflowError, tk.unsetvar, value)
751 self.assertRaises(OverflowError, tk.unsetvar, 'x', value)
Serhiy Storchaka79851d72014-05-30 14:24:03 +0300752
Serhiy Storchaka9e6b9752013-08-21 21:38:21 +0300753
Serhiy Storchaka8db18232013-11-20 17:43:49 +0200754def setUpModule():
755 if support.verbose:
756 tcl = Tcl()
757 print('patchlevel =', tcl.call('info', 'patchlevel'))
758
759
Neal Norwitz63dfece2004-02-19 02:37:29 +0000760def test_main():
Serhiy Storchaka9e6b9752013-08-21 21:38:21 +0300761 support.run_unittest(TclTest, TkinterTest, BigmemTclTest)
Neal Norwitz63dfece2004-02-19 02:37:29 +0000762
David Aschere2b4b322004-02-18 05:59:53 +0000763if __name__ == "__main__":
Neal Norwitz63dfece2004-02-19 02:37:29 +0000764 test_main()