blob: db982dac8d6533f87ae25a1f0206e2e8eab24062 [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
R. David Murraya21e4ca2009-03-31 23:16:50 +00009
10# Skip this test if the _tkinter module wasn't built.
Hai Shi06a40d72020-06-25 20:15:40 +080011_tkinter = import_helper.import_module('_tkinter')
R. David Murraya21e4ca2009-03-31 23:16:50 +000012
Zachary Ware7dc9dea2015-05-22 11:36:53 -050013import tkinter
Guilherme Polofa8fba92009-02-07 02:33:47 +000014from tkinter import Tcl
David Aschere2b4b322004-02-18 05:59:53 +000015from _tkinter import TclError
16
Serhiy Storchaka5cfc79d2014-02-07 10:06:39 +020017try:
18 from _testcapi import INT_MAX, PY_SSIZE_T_MAX
19except ImportError:
20 INT_MAX = PY_SSIZE_T_MAX = sys.maxsize
21
Serhiy Storchaka462c3572015-04-22 08:36:03 +030022tcl_version = tuple(map(int, _tkinter.TCL_VERSION.split('.')))
Serhiy Storchakadfa689b2013-09-08 20:29:37 +030023
Serhiy Storchaka92af06b2014-02-02 23:04:24 +020024_tk_patchlevel = None
25def get_tk_patchlevel():
26 global _tk_patchlevel
27 if _tk_patchlevel is None:
28 tcl = Tcl()
Serhiy Storchaka462c3572015-04-22 08:36:03 +030029 patchlevel = tcl.call('info', 'patchlevel')
30 m = re.fullmatch(r'(\d+)\.(\d+)([ab.])(\d+)', patchlevel)
31 major, minor, releaselevel, serial = m.groups()
32 major, minor, serial = int(major), int(minor), int(serial)
33 releaselevel = {'a': 'alpha', 'b': 'beta', '.': 'final'}[releaselevel]
34 if releaselevel == 'final':
35 _tk_patchlevel = major, minor, serial, releaselevel, 0
36 else:
37 _tk_patchlevel = major, minor, 0, releaselevel, serial
Serhiy Storchaka92af06b2014-02-02 23:04:24 +020038 return _tk_patchlevel
39
Benjamin Petersonc4bbc8d2009-01-30 03:39:35 +000040
41class TkinterTest(unittest.TestCase):
42
43 def testFlattenLen(self):
44 # flatten(<object with no length>)
45 self.assertRaises(TypeError, _tkinter._flatten, True)
46
47
David Aschere2b4b322004-02-18 05:59:53 +000048class TclTest(unittest.TestCase):
49
50 def setUp(self):
51 self.interp = Tcl()
Serhiy Storchakacc4290b2013-12-25 17:29:01 +020052 self.wantobjects = self.interp.tk.wantobjects()
David Aschere2b4b322004-02-18 05:59:53 +000053
54 def testEval(self):
55 tcl = self.interp
56 tcl.eval('set a 1')
57 self.assertEqual(tcl.eval('set a'),'1')
58
Serhiy Storchaka1317e142014-02-03 21:24:07 +020059 def test_eval_null_in_result(self):
60 tcl = self.interp
61 self.assertEqual(tcl.eval('set a "a\\0b"'), 'a\x00b')
62
David Aschere2b4b322004-02-18 05:59:53 +000063 def testEvalException(self):
64 tcl = self.interp
65 self.assertRaises(TclError,tcl.eval,'set a')
66
67 def testEvalException2(self):
68 tcl = self.interp
69 self.assertRaises(TclError,tcl.eval,'this is wrong')
70
71 def testCall(self):
72 tcl = self.interp
73 tcl.call('set','a','1')
74 self.assertEqual(tcl.call('set','a'),'1')
75
76 def testCallException(self):
77 tcl = self.interp
78 self.assertRaises(TclError,tcl.call,'set','a')
79
80 def testCallException2(self):
81 tcl = self.interp
82 self.assertRaises(TclError,tcl.call,'this','is','wrong')
83
84 def testSetVar(self):
85 tcl = self.interp
86 tcl.setvar('a','1')
87 self.assertEqual(tcl.eval('set a'),'1')
88
89 def testSetVarArray(self):
90 tcl = self.interp
91 tcl.setvar('a(1)','1')
92 self.assertEqual(tcl.eval('set a(1)'),'1')
93
94 def testGetVar(self):
95 tcl = self.interp
96 tcl.eval('set a 1')
97 self.assertEqual(tcl.getvar('a'),'1')
98
99 def testGetVarArray(self):
100 tcl = self.interp
101 tcl.eval('set a(1) 1')
102 self.assertEqual(tcl.getvar('a(1)'),'1')
103
104 def testGetVarException(self):
105 tcl = self.interp
106 self.assertRaises(TclError,tcl.getvar,'a')
107
108 def testGetVarArrayException(self):
109 tcl = self.interp
110 self.assertRaises(TclError,tcl.getvar,'a(1)')
111
112 def testUnsetVar(self):
113 tcl = self.interp
114 tcl.setvar('a',1)
115 self.assertEqual(tcl.eval('info exists a'),'1')
116 tcl.unsetvar('a')
117 self.assertEqual(tcl.eval('info exists a'),'0')
118
119 def testUnsetVarArray(self):
120 tcl = self.interp
121 tcl.setvar('a(1)',1)
122 tcl.setvar('a(2)',2)
123 self.assertEqual(tcl.eval('info exists a(1)'),'1')
124 self.assertEqual(tcl.eval('info exists a(2)'),'1')
125 tcl.unsetvar('a(1)')
126 self.assertEqual(tcl.eval('info exists a(1)'),'0')
127 self.assertEqual(tcl.eval('info exists a(2)'),'1')
128
129 def testUnsetVarException(self):
130 tcl = self.interp
131 self.assertRaises(TclError,tcl.unsetvar,'a')
Tim Peters27f88362004-07-08 04:22:35 +0000132
Serhiy Storchakaea134da2015-04-02 18:46:50 +0300133 def get_integers(self):
Serhiy Storchaka4c7dc482015-04-02 18:49:14 +0300134 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 +0300135 # bignum was added in Tcl 8.5, but its support is able only since 8.5.8
136 if (get_tk_patchlevel() >= (8, 6, 0, 'final') or
137 (8, 5, 8) <= get_tk_patchlevel() < (8, 6)):
Serhiy Storchakaea134da2015-04-02 18:46:50 +0300138 integers += (2**63, -2**63-1, 2**1000, -2**1000)
139 return integers
140
Serhiy Storchaka9f1f4f42014-05-30 14:07:38 +0300141 def test_getint(self):
142 tcl = self.interp.tk
Serhiy Storchakaea134da2015-04-02 18:46:50 +0300143 for i in self.get_integers():
144 self.assertEqual(tcl.getint(' %d ' % i), i)
Serhiy Storchaka2379d542015-04-02 20:07:09 +0300145 if tcl_version >= (8, 5):
146 self.assertEqual(tcl.getint(' %#o ' % i), i)
147 self.assertEqual(tcl.getint((' %#o ' % i).replace('o', '')), i)
Serhiy Storchakaea134da2015-04-02 18:46:50 +0300148 self.assertEqual(tcl.getint(' %#x ' % i), i)
149 if tcl_version < (8, 5): # bignum was added in Tcl 8.5
150 self.assertRaises(TclError, tcl.getint, str(2**1000))
Serhiy Storchaka9f1f4f42014-05-30 14:07:38 +0300151 self.assertEqual(tcl.getint(42), 42)
152 self.assertRaises(TypeError, tcl.getint)
153 self.assertRaises(TypeError, tcl.getint, '42', '10')
154 self.assertRaises(TypeError, tcl.getint, b'42')
155 self.assertRaises(TypeError, tcl.getint, 42.0)
156 self.assertRaises(TclError, tcl.getint, 'a')
157 self.assertRaises((TypeError, ValueError, TclError),
158 tcl.getint, '42\0')
159 self.assertRaises((UnicodeEncodeError, ValueError, TclError),
160 tcl.getint, '42\ud800')
161
162 def test_getdouble(self):
163 tcl = self.interp.tk
164 self.assertEqual(tcl.getdouble(' 42 '), 42.0)
165 self.assertEqual(tcl.getdouble(' 42.5 '), 42.5)
166 self.assertEqual(tcl.getdouble(42.5), 42.5)
Serhiy Storchaka645058d2015-05-06 14:00:04 +0300167 self.assertEqual(tcl.getdouble(42), 42.0)
Serhiy Storchaka9f1f4f42014-05-30 14:07:38 +0300168 self.assertRaises(TypeError, tcl.getdouble)
169 self.assertRaises(TypeError, tcl.getdouble, '42.5', '10')
170 self.assertRaises(TypeError, tcl.getdouble, b'42.5')
Serhiy Storchaka9f1f4f42014-05-30 14:07:38 +0300171 self.assertRaises(TclError, tcl.getdouble, 'a')
172 self.assertRaises((TypeError, ValueError, TclError),
173 tcl.getdouble, '42.5\0')
174 self.assertRaises((UnicodeEncodeError, ValueError, TclError),
175 tcl.getdouble, '42.5\ud800')
176
177 def test_getboolean(self):
178 tcl = self.interp.tk
179 self.assertIs(tcl.getboolean('on'), True)
180 self.assertIs(tcl.getboolean('1'), True)
Serhiy Storchaka9a6e2012015-04-04 12:43:01 +0300181 self.assertIs(tcl.getboolean(42), True)
182 self.assertIs(tcl.getboolean(0), False)
Serhiy Storchaka9f1f4f42014-05-30 14:07:38 +0300183 self.assertRaises(TypeError, tcl.getboolean)
184 self.assertRaises(TypeError, tcl.getboolean, 'on', '1')
185 self.assertRaises(TypeError, tcl.getboolean, b'on')
186 self.assertRaises(TypeError, tcl.getboolean, 1.0)
187 self.assertRaises(TclError, tcl.getboolean, 'a')
188 self.assertRaises((TypeError, ValueError, TclError),
189 tcl.getboolean, 'on\0')
190 self.assertRaises((UnicodeEncodeError, ValueError, TclError),
191 tcl.getboolean, 'on\ud800')
192
David Aschere2b4b322004-02-18 05:59:53 +0000193 def testEvalFile(self):
194 tcl = self.interp
Serhiy Storchaka1317e142014-02-03 21:24:07 +0200195 with open(support.TESTFN, 'w') as f:
196 self.addCleanup(support.unlink, support.TESTFN)
197 f.write("""set a 1
198 set b 2
199 set c [ expr $a + $b ]
200 """)
201 tcl.evalfile(support.TESTFN)
David Aschere2b4b322004-02-18 05:59:53 +0000202 self.assertEqual(tcl.eval('set a'),'1')
203 self.assertEqual(tcl.eval('set b'),'2')
204 self.assertEqual(tcl.eval('set c'),'3')
205
Serhiy Storchaka1317e142014-02-03 21:24:07 +0200206 def test_evalfile_null_in_result(self):
207 tcl = self.interp
208 with open(support.TESTFN, 'w') as f:
209 self.addCleanup(support.unlink, support.TESTFN)
210 f.write("""
211 set a "a\0b"
212 set b "a\\0b"
213 """)
214 tcl.evalfile(support.TESTFN)
215 self.assertEqual(tcl.eval('set a'), 'a\x00b')
216 self.assertEqual(tcl.eval('set b'), 'a\x00b')
217
David Aschere2b4b322004-02-18 05:59:53 +0000218 def testEvalFileException(self):
219 tcl = self.interp
220 filename = "doesnotexists"
221 try:
222 os.remove(filename)
Guido van Rossumb940e112007-01-10 16:19:56 +0000223 except Exception as e:
David Aschere2b4b322004-02-18 05:59:53 +0000224 pass
225 self.assertRaises(TclError,tcl.evalfile,filename)
226
David Aschere2b4b322004-02-18 05:59:53 +0000227 def testPackageRequireException(self):
228 tcl = self.interp
229 self.assertRaises(TclError,tcl.eval,'package require DNE')
230
Hirokazu Yamamotodda7fdf2010-09-23 15:28:35 +0000231 @unittest.skipUnless(sys.platform == 'win32', 'Requires Windows')
Martin v. Löwis2d5157e2010-06-04 19:50:26 +0000232 def testLoadWithUNC(self):
Martin v. Löwis2d5157e2010-06-04 19:50:26 +0000233 # Build a UNC path from the regular path.
234 # Something like
235 # \\%COMPUTERNAME%\c$\python27\python.exe
236
237 fullname = os.path.abspath(sys.executable)
238 if fullname[1] != ':':
Hirokazu Yamamotodda7fdf2010-09-23 15:28:35 +0000239 raise unittest.SkipTest('Absolute path should have drive part')
Martin v. Löwis2d5157e2010-06-04 19:50:26 +0000240 unc_name = r'\\%s\%s$\%s' % (os.environ['COMPUTERNAME'],
241 fullname[0],
242 fullname[3:])
Hirokazu Yamamotodda7fdf2010-09-23 15:28:35 +0000243 if not os.path.exists(unc_name):
244 raise unittest.SkipTest('Cannot connect to UNC Path')
Martin v. Löwis2d5157e2010-06-04 19:50:26 +0000245
Georg Brandlec5ae3b2010-07-31 19:17:11 +0000246 with support.EnvironmentVarGuard() as env:
Martin v. Löwis2d5157e2010-06-04 19:50:26 +0000247 env.unset("TCL_LIBRARY")
Zachary Ware83fd0a82015-10-12 23:27:58 -0500248 stdout = subprocess.check_output(
249 [unc_name, '-c', 'import tkinter; print(tkinter)'])
Martin v. Löwis2d5157e2010-06-04 19:50:26 +0000250
Zachary Ware83fd0a82015-10-12 23:27:58 -0500251 self.assertIn(b'tkinter', stdout)
Martin v. Löwis2d5157e2010-06-04 19:50:26 +0000252
Serhiy Storchakafc055252014-02-03 20:41:34 +0200253 def test_exprstring(self):
254 tcl = self.interp
255 tcl.call('set', 'a', 3)
256 tcl.call('set', 'b', 6)
257 def check(expr, expected):
258 result = tcl.exprstring(expr)
259 self.assertEqual(result, expected)
260 self.assertIsInstance(result, str)
261
262 self.assertRaises(TypeError, tcl.exprstring)
263 self.assertRaises(TypeError, tcl.exprstring, '8.2', '+6')
264 self.assertRaises(TypeError, tcl.exprstring, b'8.2 + 6')
265 self.assertRaises(TclError, tcl.exprstring, 'spam')
266 check('', '0')
267 check('8.2 + 6', '14.2')
Serhiy Storchakafc055252014-02-03 20:41:34 +0200268 check('3.1 + $a', '6.1')
269 check('2 + "$a.$b"', '5.6')
270 check('4*[llength "6 2"]', '8')
271 check('{word one} < "word $a"', '0')
272 check('4*2 < 7', '0')
273 check('hypot($a, 4)', '5.0')
274 check('5 / 4', '1')
275 check('5 / 4.0', '1.25')
276 check('5 / ( [string length "abcd"] + 0.0 )', '1.25')
277 check('20.0/5.0', '4.0')
278 check('"0x03" > "2"', '1')
279 check('[string length "a\xbd\u20ac"]', '3')
280 check(r'[string length "a\xbd\u20ac"]', '3')
281 check('"abc"', 'abc')
282 check('"a\xbd\u20ac"', 'a\xbd\u20ac')
283 check(r'"a\xbd\u20ac"', 'a\xbd\u20ac')
Serhiy Storchaka1317e142014-02-03 21:24:07 +0200284 check(r'"a\0b"', 'a\x00b')
Serhiy Storchakaea134da2015-04-02 18:46:50 +0300285 if tcl_version >= (8, 5): # bignum was added in Tcl 8.5
Serhiy Storchaka160f8922014-02-03 22:31:09 +0200286 check('2**64', str(2**64))
Serhiy Storchakafc055252014-02-03 20:41:34 +0200287
288 def test_exprdouble(self):
289 tcl = self.interp
290 tcl.call('set', 'a', 3)
291 tcl.call('set', 'b', 6)
292 def check(expr, expected):
293 result = tcl.exprdouble(expr)
294 self.assertEqual(result, expected)
295 self.assertIsInstance(result, float)
296
297 self.assertRaises(TypeError, tcl.exprdouble)
298 self.assertRaises(TypeError, tcl.exprdouble, '8.2', '+6')
299 self.assertRaises(TypeError, tcl.exprdouble, b'8.2 + 6')
300 self.assertRaises(TclError, tcl.exprdouble, 'spam')
301 check('', 0.0)
302 check('8.2 + 6', 14.2)
Serhiy Storchakafc055252014-02-03 20:41:34 +0200303 check('3.1 + $a', 6.1)
304 check('2 + "$a.$b"', 5.6)
305 check('4*[llength "6 2"]', 8.0)
306 check('{word one} < "word $a"', 0.0)
307 check('4*2 < 7', 0.0)
308 check('hypot($a, 4)', 5.0)
309 check('5 / 4', 1.0)
310 check('5 / 4.0', 1.25)
311 check('5 / ( [string length "abcd"] + 0.0 )', 1.25)
312 check('20.0/5.0', 4.0)
313 check('"0x03" > "2"', 1.0)
314 check('[string length "a\xbd\u20ac"]', 3.0)
315 check(r'[string length "a\xbd\u20ac"]', 3.0)
316 self.assertRaises(TclError, tcl.exprdouble, '"abc"')
Serhiy Storchakaea134da2015-04-02 18:46:50 +0300317 if tcl_version >= (8, 5): # bignum was added in Tcl 8.5
Serhiy Storchaka160f8922014-02-03 22:31:09 +0200318 check('2**64', float(2**64))
Serhiy Storchakafc055252014-02-03 20:41:34 +0200319
320 def test_exprlong(self):
321 tcl = self.interp
322 tcl.call('set', 'a', 3)
323 tcl.call('set', 'b', 6)
324 def check(expr, expected):
325 result = tcl.exprlong(expr)
326 self.assertEqual(result, expected)
327 self.assertIsInstance(result, int)
328
329 self.assertRaises(TypeError, tcl.exprlong)
330 self.assertRaises(TypeError, tcl.exprlong, '8.2', '+6')
331 self.assertRaises(TypeError, tcl.exprlong, b'8.2 + 6')
332 self.assertRaises(TclError, tcl.exprlong, 'spam')
333 check('', 0)
334 check('8.2 + 6', 14)
Serhiy Storchakafc055252014-02-03 20:41:34 +0200335 check('3.1 + $a', 6)
336 check('2 + "$a.$b"', 5)
337 check('4*[llength "6 2"]', 8)
338 check('{word one} < "word $a"', 0)
339 check('4*2 < 7', 0)
340 check('hypot($a, 4)', 5)
341 check('5 / 4', 1)
342 check('5 / 4.0', 1)
343 check('5 / ( [string length "abcd"] + 0.0 )', 1)
344 check('20.0/5.0', 4)
345 check('"0x03" > "2"', 1)
346 check('[string length "a\xbd\u20ac"]', 3)
347 check(r'[string length "a\xbd\u20ac"]', 3)
348 self.assertRaises(TclError, tcl.exprlong, '"abc"')
Serhiy Storchakaea134da2015-04-02 18:46:50 +0300349 if tcl_version >= (8, 5): # bignum was added in Tcl 8.5
Serhiy Storchaka160f8922014-02-03 22:31:09 +0200350 self.assertRaises(TclError, tcl.exprlong, '2**64')
Serhiy Storchakafc055252014-02-03 20:41:34 +0200351
352 def test_exprboolean(self):
353 tcl = self.interp
354 tcl.call('set', 'a', 3)
355 tcl.call('set', 'b', 6)
356 def check(expr, expected):
357 result = tcl.exprboolean(expr)
358 self.assertEqual(result, expected)
359 self.assertIsInstance(result, int)
360 self.assertNotIsInstance(result, bool)
361
362 self.assertRaises(TypeError, tcl.exprboolean)
363 self.assertRaises(TypeError, tcl.exprboolean, '8.2', '+6')
364 self.assertRaises(TypeError, tcl.exprboolean, b'8.2 + 6')
365 self.assertRaises(TclError, tcl.exprboolean, 'spam')
366 check('', False)
367 for value in ('0', 'false', 'no', 'off'):
368 check(value, False)
369 check('"%s"' % value, False)
370 check('{%s}' % value, False)
371 for value in ('1', 'true', 'yes', 'on'):
372 check(value, True)
373 check('"%s"' % value, True)
374 check('{%s}' % value, True)
375 check('8.2 + 6', True)
Serhiy Storchakafc055252014-02-03 20:41:34 +0200376 check('3.1 + $a', True)
377 check('2 + "$a.$b"', True)
378 check('4*[llength "6 2"]', True)
379 check('{word one} < "word $a"', False)
380 check('4*2 < 7', False)
381 check('hypot($a, 4)', True)
382 check('5 / 4', True)
383 check('5 / 4.0', True)
384 check('5 / ( [string length "abcd"] + 0.0 )', True)
385 check('20.0/5.0', True)
386 check('"0x03" > "2"', True)
387 check('[string length "a\xbd\u20ac"]', True)
388 check(r'[string length "a\xbd\u20ac"]', True)
389 self.assertRaises(TclError, tcl.exprboolean, '"abc"')
Serhiy Storchakaea134da2015-04-02 18:46:50 +0300390 if tcl_version >= (8, 5): # bignum was added in Tcl 8.5
Serhiy Storchaka160f8922014-02-03 22:31:09 +0200391 check('2**64', True)
Serhiy Storchakafc055252014-02-03 20:41:34 +0200392
Serhiy Storchakaa5a4bd72015-04-02 19:57:52 +0300393 @unittest.skipUnless(tcl_version >= (8, 5), 'requires Tcl version >= 8.5')
Serhiy Storchakaf7de3dd2015-04-02 10:35:57 +0300394 def test_booleans(self):
395 tcl = self.interp
396 def check(expr, expected):
397 result = tcl.call('expr', expr)
Serhiy Storchaka9171fe52015-04-02 11:46:07 +0300398 if tcl.wantobjects():
399 self.assertEqual(result, expected)
400 self.assertIsInstance(result, int)
401 else:
402 self.assertIn(result, (expr, str(int(expected))))
403 self.assertIsInstance(result, str)
Serhiy Storchakaf7de3dd2015-04-02 10:35:57 +0300404 check('true', True)
405 check('yes', True)
406 check('on', True)
407 check('false', False)
408 check('no', False)
409 check('off', False)
410 check('1 < 2', True)
411 check('1 > 2', False)
412
Serhiy Storchakaea134da2015-04-02 18:46:50 +0300413 def test_expr_bignum(self):
414 tcl = self.interp
415 for i in self.get_integers():
416 result = tcl.call('expr', str(i))
417 if self.wantobjects:
418 self.assertEqual(result, i)
419 self.assertIsInstance(result, int)
420 else:
421 self.assertEqual(result, str(i))
422 self.assertIsInstance(result, str)
423 if tcl_version < (8, 5): # bignum was added in Tcl 8.5
Serhiy Storchaka2379d542015-04-02 20:07:09 +0300424 self.assertRaises(TclError, tcl.call, 'expr', str(2**1000))
Serhiy Storchakaea134da2015-04-02 18:46:50 +0300425
Serhiy Storchakadf4bb462013-02-07 15:40:03 +0200426 def test_passing_values(self):
427 def passValue(value):
428 return self.interp.call('set', '_', value)
429
Serhiy Storchakacc4290b2013-12-25 17:29:01 +0200430 self.assertEqual(passValue(True), True if self.wantobjects else '1')
431 self.assertEqual(passValue(False), False if self.wantobjects else '0')
Serhiy Storchakadf4bb462013-02-07 15:40:03 +0200432 self.assertEqual(passValue('string'), 'string')
433 self.assertEqual(passValue('string\u20ac'), 'string\u20ac')
Serhiy Storchaka06cb94b2019-10-04 13:09:52 +0300434 self.assertEqual(passValue('string\U0001f4bb'), 'string\U0001f4bb')
Serhiy Storchaka1317e142014-02-03 21:24:07 +0200435 self.assertEqual(passValue('str\x00ing'), 'str\x00ing')
436 self.assertEqual(passValue('str\x00ing\xbd'), 'str\x00ing\xbd')
437 self.assertEqual(passValue('str\x00ing\u20ac'), 'str\x00ing\u20ac')
Serhiy Storchaka06cb94b2019-10-04 13:09:52 +0300438 self.assertEqual(passValue('str\x00ing\U0001f4bb'),
439 'str\x00ing\U0001f4bb')
Serhiy Storchaka74596a82014-07-30 18:33:13 +0300440 self.assertEqual(passValue(b'str\x00ing'),
441 b'str\x00ing' if self.wantobjects else 'str\x00ing')
442 self.assertEqual(passValue(b'str\xc0\x80ing'),
443 b'str\xc0\x80ing' if self.wantobjects else 'str\xc0\x80ing')
444 self.assertEqual(passValue(b'str\xbding'),
445 b'str\xbding' if self.wantobjects else 'str\xbding')
Serhiy Storchakaea134da2015-04-02 18:46:50 +0300446 for i in self.get_integers():
Serhiy Storchakacc4290b2013-12-25 17:29:01 +0200447 self.assertEqual(passValue(i), i if self.wantobjects else str(i))
Serhiy Storchakaea134da2015-04-02 18:46:50 +0300448 if tcl_version < (8, 5): # bignum was added in Tcl 8.5
449 self.assertEqual(passValue(2**1000), str(2**1000))
Serhiy Storchakadf4bb462013-02-07 15:40:03 +0200450 for f in (0.0, 1.0, -1.0, 1/3,
451 sys.float_info.min, sys.float_info.max,
452 -sys.float_info.min, -sys.float_info.max):
Serhiy Storchakacc4290b2013-12-25 17:29:01 +0200453 if self.wantobjects:
Serhiy Storchakadf4bb462013-02-07 15:40:03 +0200454 self.assertEqual(passValue(f), f)
Serhiy Storchakacc4290b2013-12-25 17:29:01 +0200455 else:
456 self.assertEqual(float(passValue(f)), f)
457 if self.wantobjects:
458 f = passValue(float('nan'))
459 self.assertNotEqual(f, f)
460 self.assertEqual(passValue(float('inf')), float('inf'))
461 self.assertEqual(passValue(-float('inf')), -float('inf'))
462 else:
Serhiy Storchakacc4290b2013-12-25 17:29:01 +0200463 self.assertEqual(float(passValue(float('inf'))), float('inf'))
464 self.assertEqual(float(passValue(-float('inf'))), -float('inf'))
Serhiy Storchaka6f1435c2014-07-07 14:57:08 +0300465 # XXX NaN representation can be not parsable by float()
Serhiy Storchakacc4290b2013-12-25 17:29:01 +0200466 self.assertEqual(passValue((1, '2', (3.4,))),
467 (1, '2', (3.4,)) if self.wantobjects else '1 2 3.4')
Serhiy Storchaka2b00c492014-05-21 17:12:21 +0300468 self.assertEqual(passValue(['a', ['b', 'c']]),
469 ('a', ('b', 'c')) if self.wantobjects else 'a {b c}')
Martin v. Löwis2d5157e2010-06-04 19:50:26 +0000470
Serhiy Storchaka4b730162014-01-23 09:44:05 +0200471 def test_user_command(self):
472 result = None
473 def testfunc(arg):
474 nonlocal result
475 result = arg
476 return arg
477 self.interp.createcommand('testfunc', testfunc)
Antoine Pitrou220cc212014-02-23 19:39:06 +0100478 self.addCleanup(self.interp.tk.deletecommand, 'testfunc')
Serhiy Storchakad6ec3092014-08-18 17:47:29 +0300479 def check(value, expected=None, *, eq=self.assertEqual):
480 if expected is None:
481 expected = value
482 nonlocal result
483 result = None
Serhiy Storchakabdf0cb52014-01-23 16:48:44 +0200484 r = self.interp.call('testfunc', value)
485 self.assertIsInstance(result, str)
486 eq(result, expected)
487 self.assertIsInstance(r, str)
488 eq(r, expected)
489 def float_eq(actual, expected):
Serhiy Storchakabdf0cb52014-01-23 16:48:44 +0200490 self.assertAlmostEqual(float(actual), expected,
491 delta=abs(expected) * 1e-10)
Serhiy Storchaka4b730162014-01-23 09:44:05 +0200492
493 check(True, '1')
494 check(False, '0')
Serhiy Storchakad6ec3092014-08-18 17:47:29 +0300495 check('string')
496 check('string\xbd')
497 check('string\u20ac')
Serhiy Storchaka06cb94b2019-10-04 13:09:52 +0300498 check('string\U0001f4bb')
Serhiy Storchakaabf68ce2014-09-11 10:57:13 +0300499 check('')
Serhiy Storchaka1317e142014-02-03 21:24:07 +0200500 check(b'string', 'string')
Serhiy Storchaka74596a82014-07-30 18:33:13 +0300501 check(b'string\xe2\x82\xac', 'string\xe2\x82\xac')
502 check(b'string\xbd', 'string\xbd')
Serhiy Storchakaabf68ce2014-09-11 10:57:13 +0300503 check(b'', '')
Serhiy Storchakad6ec3092014-08-18 17:47:29 +0300504 check('str\x00ing')
505 check('str\x00ing\xbd')
506 check('str\x00ing\u20ac')
Serhiy Storchaka74596a82014-07-30 18:33:13 +0300507 check(b'str\x00ing', 'str\x00ing')
508 check(b'str\xc0\x80ing', 'str\xc0\x80ing')
509 check(b'str\xc0\x80ing\xe2\x82\xac', 'str\xc0\x80ing\xe2\x82\xac')
Serhiy Storchakaea134da2015-04-02 18:46:50 +0300510 for i in self.get_integers():
Serhiy Storchaka4b730162014-01-23 09:44:05 +0200511 check(i, str(i))
Serhiy Storchakaea134da2015-04-02 18:46:50 +0300512 if tcl_version < (8, 5): # bignum was added in Tcl 8.5
513 check(2**1000, str(2**1000))
Serhiy Storchakabdf0cb52014-01-23 16:48:44 +0200514 for f in (0.0, 1.0, -1.0):
515 check(f, repr(f))
516 for f in (1/3.0, sys.float_info.min, sys.float_info.max,
Serhiy Storchaka4b730162014-01-23 09:44:05 +0200517 -sys.float_info.min, -sys.float_info.max):
Serhiy Storchakad6ec3092014-08-18 17:47:29 +0300518 check(f, eq=float_eq)
519 check(float('inf'), eq=float_eq)
520 check(-float('inf'), eq=float_eq)
Serhiy Storchaka6f1435c2014-07-07 14:57:08 +0300521 # XXX NaN representation can be not parsable by float()
Serhiy Storchaka4b730162014-01-23 09:44:05 +0200522 check((), '')
523 check((1, (2,), (3, 4), '5 6', ()), '1 2 {3 4} {5 6} {}')
Serhiy Storchaka2b00c492014-05-21 17:12:21 +0300524 check([1, [2,], [3, 4], '5 6', []], '1 2 {3 4} {5 6} {}')
Serhiy Storchaka4b730162014-01-23 09:44:05 +0200525
Serhiy Storchaka275d5fd2013-07-11 20:34:47 +0300526 def test_splitlist(self):
527 splitlist = self.interp.tk.splitlist
528 call = self.interp.tk.call
529 self.assertRaises(TypeError, splitlist)
530 self.assertRaises(TypeError, splitlist, 'a', 'b')
531 self.assertRaises(TypeError, splitlist, 2)
532 testcases = [
533 ('2', ('2',)),
534 ('', ()),
535 ('{}', ('',)),
536 ('""', ('',)),
537 ('a\n b\t\r c\n ', ('a', 'b', 'c')),
538 (b'a\n b\t\r c\n ', ('a', 'b', 'c')),
539 ('a \u20ac', ('a', '\u20ac')),
Serhiy Storchaka06cb94b2019-10-04 13:09:52 +0300540 ('a \U0001f4bb', ('a', '\U0001f4bb')),
Serhiy Storchaka275d5fd2013-07-11 20:34:47 +0300541 (b'a \xe2\x82\xac', ('a', '\u20ac')),
Serhiy Storchaka1317e142014-02-03 21:24:07 +0200542 (b'a\xc0\x80b c\xc0\x80d', ('a\x00b', 'c\x00d')),
Serhiy Storchaka275d5fd2013-07-11 20:34:47 +0300543 ('a {b c}', ('a', 'b c')),
544 (r'a b\ c', ('a', 'b c')),
545 (('a', 'b c'), ('a', 'b c')),
546 ('a 2', ('a', '2')),
547 (('a', 2), ('a', 2)),
548 ('a 3.4', ('a', '3.4')),
549 (('a', 3.4), ('a', 3.4)),
550 ((), ()),
Serhiy Storchaka2b00c492014-05-21 17:12:21 +0300551 ([], ()),
552 (['a', ['b', 'c']], ('a', ['b', 'c'])),
Serhiy Storchakacc4290b2013-12-25 17:29:01 +0200553 (call('list', 1, '2', (3.4,)),
554 (1, '2', (3.4,)) if self.wantobjects else
555 ('1', '2', '3.4')),
Serhiy Storchaka275d5fd2013-07-11 20:34:47 +0300556 ]
Victor Stinnerece38d92014-09-04 09:53:16 +0200557 tk_patchlevel = get_tk_patchlevel()
Serhiy Storchakadfa689b2013-09-08 20:29:37 +0300558 if tcl_version >= (8, 5):
Victor Stinnerece38d92014-09-04 09:53:16 +0200559 if not self.wantobjects or tk_patchlevel < (8, 5, 5):
Serhiy Storchaka92af06b2014-02-02 23:04:24 +0200560 # Before 8.5.5 dicts were converted to lists through string
Serhiy Storchaka74596a82014-07-30 18:33:13 +0300561 expected = ('12', '\u20ac', '\xe2\x82\xac', '3.4')
Serhiy Storchaka92af06b2014-02-02 23:04:24 +0200562 else:
Serhiy Storchaka74596a82014-07-30 18:33:13 +0300563 expected = (12, '\u20ac', b'\xe2\x82\xac', (3.4,))
Serhiy Storchakadfa689b2013-09-08 20:29:37 +0300564 testcases += [
Serhiy Storchaka92af06b2014-02-02 23:04:24 +0200565 (call('dict', 'create', 12, '\u20ac', b'\xe2\x82\xac', (3.4,)),
566 expected),
Serhiy Storchakadfa689b2013-09-08 20:29:37 +0300567 ]
Victor Stinnerece38d92014-09-04 09:53:16 +0200568 dbg_info = ('want objects? %s, Tcl version: %s, Tk patchlevel: %s'
569 % (self.wantobjects, tcl_version, tk_patchlevel))
Serhiy Storchaka275d5fd2013-07-11 20:34:47 +0300570 for arg, res in testcases:
Victor Stinnerece38d92014-09-04 09:53:16 +0200571 self.assertEqual(splitlist(arg), res,
572 'arg=%a, %s' % (arg, dbg_info))
Serhiy Storchaka275d5fd2013-07-11 20:34:47 +0300573 self.assertRaises(TclError, splitlist, '{')
574
575 def test_split(self):
576 split = self.interp.tk.split
577 call = self.interp.tk.call
Serhiy Storchakad05b0002019-10-08 14:31:35 +0300578 with warnings.catch_warnings():
579 warnings.filterwarnings('ignore', r'\bsplit\b.*\bsplitlist\b',
580 DeprecationWarning)
581 self.assertRaises(TypeError, split)
582 self.assertRaises(TypeError, split, 'a', 'b')
583 self.assertRaises(TypeError, split, 2)
Serhiy Storchaka275d5fd2013-07-11 20:34:47 +0300584 testcases = [
585 ('2', '2'),
586 ('', ''),
587 ('{}', ''),
588 ('""', ''),
589 ('{', '{'),
590 ('a\n b\t\r c\n ', ('a', 'b', 'c')),
591 (b'a\n b\t\r c\n ', ('a', 'b', 'c')),
592 ('a \u20ac', ('a', '\u20ac')),
593 (b'a \xe2\x82\xac', ('a', '\u20ac')),
Serhiy Storchaka1317e142014-02-03 21:24:07 +0200594 (b'a\xc0\x80b', 'a\x00b'),
595 (b'a\xc0\x80b c\xc0\x80d', ('a\x00b', 'c\x00d')),
596 (b'{a\xc0\x80b c\xc0\x80d', '{a\x00b c\x00d'),
Serhiy Storchaka275d5fd2013-07-11 20:34:47 +0300597 ('a {b c}', ('a', ('b', 'c'))),
598 (r'a b\ c', ('a', ('b', 'c'))),
599 (('a', b'b c'), ('a', ('b', 'c'))),
600 (('a', 'b c'), ('a', ('b', 'c'))),
601 ('a 2', ('a', '2')),
602 (('a', 2), ('a', 2)),
603 ('a 3.4', ('a', '3.4')),
604 (('a', 3.4), ('a', 3.4)),
605 (('a', (2, 3.4)), ('a', (2, 3.4))),
606 ((), ()),
Serhiy Storchaka2b00c492014-05-21 17:12:21 +0300607 ([], ()),
608 (['a', 'b c'], ('a', ('b', 'c'))),
609 (['a', ['b', 'c']], ('a', ('b', 'c'))),
Serhiy Storchakacc4290b2013-12-25 17:29:01 +0200610 (call('list', 1, '2', (3.4,)),
611 (1, '2', (3.4,)) if self.wantobjects else
612 ('1', '2', '3.4')),
Serhiy Storchaka275d5fd2013-07-11 20:34:47 +0300613 ]
Serhiy Storchakadfa689b2013-09-08 20:29:37 +0300614 if tcl_version >= (8, 5):
Serhiy Storchaka92af06b2014-02-02 23:04:24 +0200615 if not self.wantobjects or get_tk_patchlevel() < (8, 5, 5):
616 # Before 8.5.5 dicts were converted to lists through string
Serhiy Storchaka74596a82014-07-30 18:33:13 +0300617 expected = ('12', '\u20ac', '\xe2\x82\xac', '3.4')
Serhiy Storchaka92af06b2014-02-02 23:04:24 +0200618 else:
Serhiy Storchaka74596a82014-07-30 18:33:13 +0300619 expected = (12, '\u20ac', b'\xe2\x82\xac', (3.4,))
Serhiy Storchakadfa689b2013-09-08 20:29:37 +0300620 testcases += [
621 (call('dict', 'create', 12, '\u20ac', b'\xe2\x82\xac', (3.4,)),
Serhiy Storchaka92af06b2014-02-02 23:04:24 +0200622 expected),
Serhiy Storchakadfa689b2013-09-08 20:29:37 +0300623 ]
Serhiy Storchaka275d5fd2013-07-11 20:34:47 +0300624 for arg, res in testcases:
Serhiy Storchakad05b0002019-10-08 14:31:35 +0300625 with self.assertWarns(DeprecationWarning):
626 self.assertEqual(split(arg), res, msg=arg)
Serhiy Storchaka275d5fd2013-07-11 20:34:47 +0300627
Serhiy Storchaka8f0a1d02014-09-06 22:47:58 +0300628 def test_splitdict(self):
629 splitdict = tkinter._splitdict
630 tcl = self.interp.tk
631
632 arg = '-a {1 2 3} -something foo status {}'
633 self.assertEqual(splitdict(tcl, arg, False),
634 {'-a': '1 2 3', '-something': 'foo', 'status': ''})
635 self.assertEqual(splitdict(tcl, arg),
636 {'a': '1 2 3', 'something': 'foo', 'status': ''})
637
638 arg = ('-a', (1, 2, 3), '-something', 'foo', 'status', '{}')
639 self.assertEqual(splitdict(tcl, arg, False),
640 {'-a': (1, 2, 3), '-something': 'foo', 'status': '{}'})
641 self.assertEqual(splitdict(tcl, arg),
642 {'a': (1, 2, 3), 'something': 'foo', 'status': '{}'})
643
644 self.assertRaises(RuntimeError, splitdict, tcl, '-a b -c ')
645 self.assertRaises(RuntimeError, splitdict, tcl, ('-a', 'b', '-c'))
646
647 arg = tcl.call('list',
648 '-a', (1, 2, 3), '-something', 'foo', 'status', ())
649 self.assertEqual(splitdict(tcl, arg),
650 {'a': (1, 2, 3) if self.wantobjects else '1 2 3',
651 'something': 'foo', 'status': ''})
652
653 if tcl_version >= (8, 5):
654 arg = tcl.call('dict', 'create',
655 '-a', (1, 2, 3), '-something', 'foo', 'status', ())
656 if not self.wantobjects or get_tk_patchlevel() < (8, 5, 5):
657 # Before 8.5.5 dicts were converted to lists through string
658 expected = {'a': '1 2 3', 'something': 'foo', 'status': ''}
659 else:
660 expected = {'a': (1, 2, 3), 'something': 'foo', 'status': ''}
661 self.assertEqual(splitdict(tcl, arg), expected)
662
Serhiy Storchaka5bb5bbf2018-06-30 09:20:28 +0300663 def test_join(self):
664 join = tkinter._join
665 tcl = self.interp.tk
666 def unpack(s):
667 return tcl.call('lindex', s, 0)
668 def check(value):
669 self.assertEqual(unpack(join([value])), value)
670 self.assertEqual(unpack(join([value, 0])), value)
671 self.assertEqual(unpack(unpack(join([[value]]))), value)
672 self.assertEqual(unpack(unpack(join([[value, 0]]))), value)
673 self.assertEqual(unpack(unpack(join([[value], 0]))), value)
674 self.assertEqual(unpack(unpack(join([[value, 0], 0]))), value)
675 check('')
676 check('spam')
677 check('sp am')
678 check('sp\tam')
679 check('sp\nam')
680 check(' \t\n')
681 check('{spam}')
682 check('{sp am}')
683 check('"spam"')
684 check('"sp am"')
685 check('{"spam"}')
686 check('"{spam}"')
687 check('sp\\am')
688 check('"sp\\am"')
689 check('"{}" "{}"')
690 check('"\\')
691 check('"{')
692 check('"}')
693 check('\n\\')
694 check('\n{')
695 check('\n}')
696 check('\\\n')
697 check('{\n')
698 check('}\n')
699
Serhiy Storchakae3f1b092016-05-08 20:46:22 +0300700 def test_new_tcl_obj(self):
701 self.assertRaises(TypeError, _tkinter.Tcl_Obj)
Neal Norwitz63dfece2004-02-19 02:37:29 +0000702
Serhiy Storchaka9e6b9752013-08-21 21:38:21 +0300703class BigmemTclTest(unittest.TestCase):
704
705 def setUp(self):
706 self.interp = Tcl()
707
Serhiy Storchaka5cfc79d2014-02-07 10:06:39 +0200708 @support.cpython_only
709 @unittest.skipUnless(INT_MAX < PY_SSIZE_T_MAX, "needs UINT_MAX < SIZE_MAX")
710 @support.bigmemtest(size=INT_MAX + 1, memuse=5, dry_run=False)
Serhiy Storchaka79851d72014-05-30 14:24:03 +0300711 def test_huge_string_call(self, size):
Serhiy Storchaka9e6b9752013-08-21 21:38:21 +0300712 value = ' ' * size
Serhiy Storchaka27c623c2017-10-03 22:39:55 +0300713 self.assertRaises(OverflowError, self.interp.call, 'string', 'index', value, 0)
Serhiy Storchaka9e6b9752013-08-21 21:38:21 +0300714
Serhiy Storchaka79851d72014-05-30 14:24:03 +0300715 @support.cpython_only
716 @unittest.skipUnless(INT_MAX < PY_SSIZE_T_MAX, "needs UINT_MAX < SIZE_MAX")
Serhiy Storchaka27c623c2017-10-03 22:39:55 +0300717 @support.bigmemtest(size=INT_MAX + 1, memuse=2, dry_run=False)
Serhiy Storchaka79851d72014-05-30 14:24:03 +0300718 def test_huge_string_builtins(self, size):
Serhiy Storchaka27c623c2017-10-03 22:39:55 +0300719 tk = self.interp.tk
Serhiy Storchaka79851d72014-05-30 14:24:03 +0300720 value = '1' + ' ' * size
Serhiy Storchaka27c623c2017-10-03 22:39:55 +0300721 self.assertRaises(OverflowError, tk.getint, value)
722 self.assertRaises(OverflowError, tk.getdouble, value)
723 self.assertRaises(OverflowError, tk.getboolean, value)
724 self.assertRaises(OverflowError, tk.eval, value)
725 self.assertRaises(OverflowError, tk.evalfile, value)
726 self.assertRaises(OverflowError, tk.record, value)
727 self.assertRaises(OverflowError, tk.adderrorinfo, value)
728 self.assertRaises(OverflowError, tk.setvar, value, 'x', 'a')
729 self.assertRaises(OverflowError, tk.setvar, 'x', value, 'a')
730 self.assertRaises(OverflowError, tk.unsetvar, value)
731 self.assertRaises(OverflowError, tk.unsetvar, 'x', value)
732 self.assertRaises(OverflowError, tk.adderrorinfo, value)
733 self.assertRaises(OverflowError, tk.exprstring, value)
734 self.assertRaises(OverflowError, tk.exprlong, value)
735 self.assertRaises(OverflowError, tk.exprboolean, value)
736 self.assertRaises(OverflowError, tk.splitlist, value)
737 self.assertRaises(OverflowError, tk.split, value)
738 self.assertRaises(OverflowError, tk.createcommand, value, max)
739 self.assertRaises(OverflowError, tk.deletecommand, value)
740
741 @support.cpython_only
742 @unittest.skipUnless(INT_MAX < PY_SSIZE_T_MAX, "needs UINT_MAX < SIZE_MAX")
743 @support.bigmemtest(size=INT_MAX + 1, memuse=6, dry_run=False)
744 def test_huge_string_builtins2(self, size):
745 # These commands require larger memory for possible error messages
746 tk = self.interp.tk
747 value = '1' + ' ' * size
748 self.assertRaises(OverflowError, tk.evalfile, value)
749 self.assertRaises(OverflowError, tk.unsetvar, value)
750 self.assertRaises(OverflowError, tk.unsetvar, 'x', value)
Serhiy Storchaka79851d72014-05-30 14:24:03 +0300751
Serhiy Storchaka9e6b9752013-08-21 21:38:21 +0300752
Serhiy Storchaka8db18232013-11-20 17:43:49 +0200753def setUpModule():
754 if support.verbose:
755 tcl = Tcl()
756 print('patchlevel =', tcl.call('info', 'patchlevel'))
757
758
Neal Norwitz63dfece2004-02-19 02:37:29 +0000759def test_main():
Serhiy Storchaka9e6b9752013-08-21 21:38:21 +0300760 support.run_unittest(TclTest, TkinterTest, BigmemTclTest)
Neal Norwitz63dfece2004-02-19 02:37:29 +0000761
David Aschere2b4b322004-02-18 05:59:53 +0000762if __name__ == "__main__":
Neal Norwitz63dfece2004-02-19 02:37:29 +0000763 test_main()