blob: 5be645a32ebc367d0650a59c72f2346cea28bc2e [file] [log] [blame]
David Aschere2b4b322004-02-18 05:59:53 +00001import unittest
Serhiy Storchaka462c3572015-04-22 08:36:03 +03002import re
Hirokazu Yamamotodda7fdf2010-09-23 15:28:35 +00003import sys
David Aschere2b4b322004-02-18 05:59:53 +00004import os
Benjamin Petersonee8712c2008-05-20 21:35:26 +00005from test import support
R. David Murraya21e4ca2009-03-31 23:16:50 +00006
7# Skip this test if the _tkinter module wasn't built.
8_tkinter = support.import_module('_tkinter')
9
Zachary Ware7dc9dea2015-05-22 11:36:53 -050010import tkinter
Guilherme Polofa8fba92009-02-07 02:33:47 +000011from tkinter import Tcl
David Aschere2b4b322004-02-18 05:59:53 +000012from _tkinter import TclError
13
Serhiy Storchaka5cfc79d2014-02-07 10:06:39 +020014try:
15 from _testcapi import INT_MAX, PY_SSIZE_T_MAX
16except ImportError:
17 INT_MAX = PY_SSIZE_T_MAX = sys.maxsize
18
Serhiy Storchaka462c3572015-04-22 08:36:03 +030019tcl_version = tuple(map(int, _tkinter.TCL_VERSION.split('.')))
Serhiy Storchakadfa689b2013-09-08 20:29:37 +030020
Serhiy Storchaka92af06b2014-02-02 23:04:24 +020021_tk_patchlevel = None
22def get_tk_patchlevel():
23 global _tk_patchlevel
24 if _tk_patchlevel is None:
25 tcl = Tcl()
Serhiy Storchaka462c3572015-04-22 08:36:03 +030026 patchlevel = tcl.call('info', 'patchlevel')
27 m = re.fullmatch(r'(\d+)\.(\d+)([ab.])(\d+)', patchlevel)
28 major, minor, releaselevel, serial = m.groups()
29 major, minor, serial = int(major), int(minor), int(serial)
30 releaselevel = {'a': 'alpha', 'b': 'beta', '.': 'final'}[releaselevel]
31 if releaselevel == 'final':
32 _tk_patchlevel = major, minor, serial, releaselevel, 0
33 else:
34 _tk_patchlevel = major, minor, 0, releaselevel, serial
Serhiy Storchaka92af06b2014-02-02 23:04:24 +020035 return _tk_patchlevel
36
Benjamin Petersonc4bbc8d2009-01-30 03:39:35 +000037
38class TkinterTest(unittest.TestCase):
39
40 def testFlattenLen(self):
41 # flatten(<object with no length>)
42 self.assertRaises(TypeError, _tkinter._flatten, True)
43
44
David Aschere2b4b322004-02-18 05:59:53 +000045class TclTest(unittest.TestCase):
46
47 def setUp(self):
48 self.interp = Tcl()
Serhiy Storchakacc4290b2013-12-25 17:29:01 +020049 self.wantobjects = self.interp.tk.wantobjects()
David Aschere2b4b322004-02-18 05:59:53 +000050
51 def testEval(self):
52 tcl = self.interp
53 tcl.eval('set a 1')
54 self.assertEqual(tcl.eval('set a'),'1')
55
Serhiy Storchaka1317e142014-02-03 21:24:07 +020056 def test_eval_null_in_result(self):
57 tcl = self.interp
58 self.assertEqual(tcl.eval('set a "a\\0b"'), 'a\x00b')
59
David Aschere2b4b322004-02-18 05:59:53 +000060 def testEvalException(self):
61 tcl = self.interp
62 self.assertRaises(TclError,tcl.eval,'set a')
63
64 def testEvalException2(self):
65 tcl = self.interp
66 self.assertRaises(TclError,tcl.eval,'this is wrong')
67
68 def testCall(self):
69 tcl = self.interp
70 tcl.call('set','a','1')
71 self.assertEqual(tcl.call('set','a'),'1')
72
73 def testCallException(self):
74 tcl = self.interp
75 self.assertRaises(TclError,tcl.call,'set','a')
76
77 def testCallException2(self):
78 tcl = self.interp
79 self.assertRaises(TclError,tcl.call,'this','is','wrong')
80
81 def testSetVar(self):
82 tcl = self.interp
83 tcl.setvar('a','1')
84 self.assertEqual(tcl.eval('set a'),'1')
85
86 def testSetVarArray(self):
87 tcl = self.interp
88 tcl.setvar('a(1)','1')
89 self.assertEqual(tcl.eval('set a(1)'),'1')
90
91 def testGetVar(self):
92 tcl = self.interp
93 tcl.eval('set a 1')
94 self.assertEqual(tcl.getvar('a'),'1')
95
96 def testGetVarArray(self):
97 tcl = self.interp
98 tcl.eval('set a(1) 1')
99 self.assertEqual(tcl.getvar('a(1)'),'1')
100
101 def testGetVarException(self):
102 tcl = self.interp
103 self.assertRaises(TclError,tcl.getvar,'a')
104
105 def testGetVarArrayException(self):
106 tcl = self.interp
107 self.assertRaises(TclError,tcl.getvar,'a(1)')
108
109 def testUnsetVar(self):
110 tcl = self.interp
111 tcl.setvar('a',1)
112 self.assertEqual(tcl.eval('info exists a'),'1')
113 tcl.unsetvar('a')
114 self.assertEqual(tcl.eval('info exists a'),'0')
115
116 def testUnsetVarArray(self):
117 tcl = self.interp
118 tcl.setvar('a(1)',1)
119 tcl.setvar('a(2)',2)
120 self.assertEqual(tcl.eval('info exists a(1)'),'1')
121 self.assertEqual(tcl.eval('info exists a(2)'),'1')
122 tcl.unsetvar('a(1)')
123 self.assertEqual(tcl.eval('info exists a(1)'),'0')
124 self.assertEqual(tcl.eval('info exists a(2)'),'1')
125
126 def testUnsetVarException(self):
127 tcl = self.interp
128 self.assertRaises(TclError,tcl.unsetvar,'a')
Tim Peters27f88362004-07-08 04:22:35 +0000129
Serhiy Storchakaea134da2015-04-02 18:46:50 +0300130 def get_integers(self):
Serhiy Storchaka4c7dc482015-04-02 18:49:14 +0300131 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 +0300132 # bignum was added in Tcl 8.5, but its support is able only since 8.5.8
133 if (get_tk_patchlevel() >= (8, 6, 0, 'final') or
134 (8, 5, 8) <= get_tk_patchlevel() < (8, 6)):
Serhiy Storchakaea134da2015-04-02 18:46:50 +0300135 integers += (2**63, -2**63-1, 2**1000, -2**1000)
136 return integers
137
Serhiy Storchaka9f1f4f42014-05-30 14:07:38 +0300138 def test_getint(self):
139 tcl = self.interp.tk
Serhiy Storchakaea134da2015-04-02 18:46:50 +0300140 for i in self.get_integers():
141 self.assertEqual(tcl.getint(' %d ' % i), i)
Serhiy Storchaka2379d542015-04-02 20:07:09 +0300142 if tcl_version >= (8, 5):
143 self.assertEqual(tcl.getint(' %#o ' % i), i)
144 self.assertEqual(tcl.getint((' %#o ' % i).replace('o', '')), i)
Serhiy Storchakaea134da2015-04-02 18:46:50 +0300145 self.assertEqual(tcl.getint(' %#x ' % i), i)
146 if tcl_version < (8, 5): # bignum was added in Tcl 8.5
147 self.assertRaises(TclError, tcl.getint, str(2**1000))
Serhiy Storchaka9f1f4f42014-05-30 14:07:38 +0300148 self.assertEqual(tcl.getint(42), 42)
149 self.assertRaises(TypeError, tcl.getint)
150 self.assertRaises(TypeError, tcl.getint, '42', '10')
151 self.assertRaises(TypeError, tcl.getint, b'42')
152 self.assertRaises(TypeError, tcl.getint, 42.0)
153 self.assertRaises(TclError, tcl.getint, 'a')
154 self.assertRaises((TypeError, ValueError, TclError),
155 tcl.getint, '42\0')
156 self.assertRaises((UnicodeEncodeError, ValueError, TclError),
157 tcl.getint, '42\ud800')
158
159 def test_getdouble(self):
160 tcl = self.interp.tk
161 self.assertEqual(tcl.getdouble(' 42 '), 42.0)
162 self.assertEqual(tcl.getdouble(' 42.5 '), 42.5)
163 self.assertEqual(tcl.getdouble(42.5), 42.5)
Serhiy Storchaka645058d2015-05-06 14:00:04 +0300164 self.assertEqual(tcl.getdouble(42), 42.0)
Serhiy Storchaka9f1f4f42014-05-30 14:07:38 +0300165 self.assertRaises(TypeError, tcl.getdouble)
166 self.assertRaises(TypeError, tcl.getdouble, '42.5', '10')
167 self.assertRaises(TypeError, tcl.getdouble, b'42.5')
Serhiy Storchaka9f1f4f42014-05-30 14:07:38 +0300168 self.assertRaises(TclError, tcl.getdouble, 'a')
169 self.assertRaises((TypeError, ValueError, TclError),
170 tcl.getdouble, '42.5\0')
171 self.assertRaises((UnicodeEncodeError, ValueError, TclError),
172 tcl.getdouble, '42.5\ud800')
173
174 def test_getboolean(self):
175 tcl = self.interp.tk
176 self.assertIs(tcl.getboolean('on'), True)
177 self.assertIs(tcl.getboolean('1'), True)
Serhiy Storchaka9a6e2012015-04-04 12:43:01 +0300178 self.assertIs(tcl.getboolean(42), True)
179 self.assertIs(tcl.getboolean(0), False)
Serhiy Storchaka9f1f4f42014-05-30 14:07:38 +0300180 self.assertRaises(TypeError, tcl.getboolean)
181 self.assertRaises(TypeError, tcl.getboolean, 'on', '1')
182 self.assertRaises(TypeError, tcl.getboolean, b'on')
183 self.assertRaises(TypeError, tcl.getboolean, 1.0)
184 self.assertRaises(TclError, tcl.getboolean, 'a')
185 self.assertRaises((TypeError, ValueError, TclError),
186 tcl.getboolean, 'on\0')
187 self.assertRaises((UnicodeEncodeError, ValueError, TclError),
188 tcl.getboolean, 'on\ud800')
189
David Aschere2b4b322004-02-18 05:59:53 +0000190 def testEvalFile(self):
191 tcl = self.interp
Serhiy Storchaka1317e142014-02-03 21:24:07 +0200192 with open(support.TESTFN, 'w') as f:
193 self.addCleanup(support.unlink, support.TESTFN)
194 f.write("""set a 1
195 set b 2
196 set c [ expr $a + $b ]
197 """)
198 tcl.evalfile(support.TESTFN)
David Aschere2b4b322004-02-18 05:59:53 +0000199 self.assertEqual(tcl.eval('set a'),'1')
200 self.assertEqual(tcl.eval('set b'),'2')
201 self.assertEqual(tcl.eval('set c'),'3')
202
Serhiy Storchaka1317e142014-02-03 21:24:07 +0200203 def test_evalfile_null_in_result(self):
204 tcl = self.interp
205 with open(support.TESTFN, 'w') as f:
206 self.addCleanup(support.unlink, support.TESTFN)
207 f.write("""
208 set a "a\0b"
209 set b "a\\0b"
210 """)
211 tcl.evalfile(support.TESTFN)
212 self.assertEqual(tcl.eval('set a'), 'a\x00b')
213 self.assertEqual(tcl.eval('set b'), 'a\x00b')
214
David Aschere2b4b322004-02-18 05:59:53 +0000215 def testEvalFileException(self):
216 tcl = self.interp
217 filename = "doesnotexists"
218 try:
219 os.remove(filename)
Guido van Rossumb940e112007-01-10 16:19:56 +0000220 except Exception as e:
David Aschere2b4b322004-02-18 05:59:53 +0000221 pass
222 self.assertRaises(TclError,tcl.evalfile,filename)
223
David Aschere2b4b322004-02-18 05:59:53 +0000224 def testPackageRequireException(self):
225 tcl = self.interp
226 self.assertRaises(TclError,tcl.eval,'package require DNE')
227
Hirokazu Yamamotodda7fdf2010-09-23 15:28:35 +0000228 @unittest.skipUnless(sys.platform == 'win32', 'Requires Windows')
Martin v. Löwis2d5157e2010-06-04 19:50:26 +0000229 def testLoadWithUNC(self):
Martin v. Löwis2d5157e2010-06-04 19:50:26 +0000230 # Build a UNC path from the regular path.
231 # Something like
232 # \\%COMPUTERNAME%\c$\python27\python.exe
233
234 fullname = os.path.abspath(sys.executable)
235 if fullname[1] != ':':
Hirokazu Yamamotodda7fdf2010-09-23 15:28:35 +0000236 raise unittest.SkipTest('Absolute path should have drive part')
Martin v. Löwis2d5157e2010-06-04 19:50:26 +0000237 unc_name = r'\\%s\%s$\%s' % (os.environ['COMPUTERNAME'],
238 fullname[0],
239 fullname[3:])
Hirokazu Yamamotodda7fdf2010-09-23 15:28:35 +0000240 if not os.path.exists(unc_name):
241 raise unittest.SkipTest('Cannot connect to UNC Path')
Martin v. Löwis2d5157e2010-06-04 19:50:26 +0000242
Georg Brandlec5ae3b2010-07-31 19:17:11 +0000243 with support.EnvironmentVarGuard() as env:
Martin v. Löwis2d5157e2010-06-04 19:50:26 +0000244 env.unset("TCL_LIBRARY")
Hirokazu Yamamotof2dec8d2010-09-18 04:42:41 +0000245 f = os.popen('%s -c "import tkinter; print(tkinter)"' % (unc_name,))
Martin v. Löwis2d5157e2010-06-04 19:50:26 +0000246
Hirokazu Yamamotof2dec8d2010-09-18 04:42:41 +0000247 self.assertIn('tkinter', f.read())
Martin v. Löwis2d5157e2010-06-04 19:50:26 +0000248 # exit code must be zero
249 self.assertEqual(f.close(), None)
250
Serhiy Storchakafc055252014-02-03 20:41:34 +0200251 def test_exprstring(self):
252 tcl = self.interp
253 tcl.call('set', 'a', 3)
254 tcl.call('set', 'b', 6)
255 def check(expr, expected):
256 result = tcl.exprstring(expr)
257 self.assertEqual(result, expected)
258 self.assertIsInstance(result, str)
259
260 self.assertRaises(TypeError, tcl.exprstring)
261 self.assertRaises(TypeError, tcl.exprstring, '8.2', '+6')
262 self.assertRaises(TypeError, tcl.exprstring, b'8.2 + 6')
263 self.assertRaises(TclError, tcl.exprstring, 'spam')
264 check('', '0')
265 check('8.2 + 6', '14.2')
Serhiy Storchakafc055252014-02-03 20:41:34 +0200266 check('3.1 + $a', '6.1')
267 check('2 + "$a.$b"', '5.6')
268 check('4*[llength "6 2"]', '8')
269 check('{word one} < "word $a"', '0')
270 check('4*2 < 7', '0')
271 check('hypot($a, 4)', '5.0')
272 check('5 / 4', '1')
273 check('5 / 4.0', '1.25')
274 check('5 / ( [string length "abcd"] + 0.0 )', '1.25')
275 check('20.0/5.0', '4.0')
276 check('"0x03" > "2"', '1')
277 check('[string length "a\xbd\u20ac"]', '3')
278 check(r'[string length "a\xbd\u20ac"]', '3')
279 check('"abc"', 'abc')
280 check('"a\xbd\u20ac"', 'a\xbd\u20ac')
281 check(r'"a\xbd\u20ac"', 'a\xbd\u20ac')
Serhiy Storchaka1317e142014-02-03 21:24:07 +0200282 check(r'"a\0b"', 'a\x00b')
Serhiy Storchakaea134da2015-04-02 18:46:50 +0300283 if tcl_version >= (8, 5): # bignum was added in Tcl 8.5
Serhiy Storchaka160f8922014-02-03 22:31:09 +0200284 check('2**64', str(2**64))
Serhiy Storchakafc055252014-02-03 20:41:34 +0200285
286 def test_exprdouble(self):
287 tcl = self.interp
288 tcl.call('set', 'a', 3)
289 tcl.call('set', 'b', 6)
290 def check(expr, expected):
291 result = tcl.exprdouble(expr)
292 self.assertEqual(result, expected)
293 self.assertIsInstance(result, float)
294
295 self.assertRaises(TypeError, tcl.exprdouble)
296 self.assertRaises(TypeError, tcl.exprdouble, '8.2', '+6')
297 self.assertRaises(TypeError, tcl.exprdouble, b'8.2 + 6')
298 self.assertRaises(TclError, tcl.exprdouble, 'spam')
299 check('', 0.0)
300 check('8.2 + 6', 14.2)
Serhiy Storchakafc055252014-02-03 20:41:34 +0200301 check('3.1 + $a', 6.1)
302 check('2 + "$a.$b"', 5.6)
303 check('4*[llength "6 2"]', 8.0)
304 check('{word one} < "word $a"', 0.0)
305 check('4*2 < 7', 0.0)
306 check('hypot($a, 4)', 5.0)
307 check('5 / 4', 1.0)
308 check('5 / 4.0', 1.25)
309 check('5 / ( [string length "abcd"] + 0.0 )', 1.25)
310 check('20.0/5.0', 4.0)
311 check('"0x03" > "2"', 1.0)
312 check('[string length "a\xbd\u20ac"]', 3.0)
313 check(r'[string length "a\xbd\u20ac"]', 3.0)
314 self.assertRaises(TclError, tcl.exprdouble, '"abc"')
Serhiy Storchakaea134da2015-04-02 18:46:50 +0300315 if tcl_version >= (8, 5): # bignum was added in Tcl 8.5
Serhiy Storchaka160f8922014-02-03 22:31:09 +0200316 check('2**64', float(2**64))
Serhiy Storchakafc055252014-02-03 20:41:34 +0200317
318 def test_exprlong(self):
319 tcl = self.interp
320 tcl.call('set', 'a', 3)
321 tcl.call('set', 'b', 6)
322 def check(expr, expected):
323 result = tcl.exprlong(expr)
324 self.assertEqual(result, expected)
325 self.assertIsInstance(result, int)
326
327 self.assertRaises(TypeError, tcl.exprlong)
328 self.assertRaises(TypeError, tcl.exprlong, '8.2', '+6')
329 self.assertRaises(TypeError, tcl.exprlong, b'8.2 + 6')
330 self.assertRaises(TclError, tcl.exprlong, 'spam')
331 check('', 0)
332 check('8.2 + 6', 14)
Serhiy Storchakafc055252014-02-03 20:41:34 +0200333 check('3.1 + $a', 6)
334 check('2 + "$a.$b"', 5)
335 check('4*[llength "6 2"]', 8)
336 check('{word one} < "word $a"', 0)
337 check('4*2 < 7', 0)
338 check('hypot($a, 4)', 5)
339 check('5 / 4', 1)
340 check('5 / 4.0', 1)
341 check('5 / ( [string length "abcd"] + 0.0 )', 1)
342 check('20.0/5.0', 4)
343 check('"0x03" > "2"', 1)
344 check('[string length "a\xbd\u20ac"]', 3)
345 check(r'[string length "a\xbd\u20ac"]', 3)
346 self.assertRaises(TclError, tcl.exprlong, '"abc"')
Serhiy Storchakaea134da2015-04-02 18:46:50 +0300347 if tcl_version >= (8, 5): # bignum was added in Tcl 8.5
Serhiy Storchaka160f8922014-02-03 22:31:09 +0200348 self.assertRaises(TclError, tcl.exprlong, '2**64')
Serhiy Storchakafc055252014-02-03 20:41:34 +0200349
350 def test_exprboolean(self):
351 tcl = self.interp
352 tcl.call('set', 'a', 3)
353 tcl.call('set', 'b', 6)
354 def check(expr, expected):
355 result = tcl.exprboolean(expr)
356 self.assertEqual(result, expected)
357 self.assertIsInstance(result, int)
358 self.assertNotIsInstance(result, bool)
359
360 self.assertRaises(TypeError, tcl.exprboolean)
361 self.assertRaises(TypeError, tcl.exprboolean, '8.2', '+6')
362 self.assertRaises(TypeError, tcl.exprboolean, b'8.2 + 6')
363 self.assertRaises(TclError, tcl.exprboolean, 'spam')
364 check('', False)
365 for value in ('0', 'false', 'no', 'off'):
366 check(value, False)
367 check('"%s"' % value, False)
368 check('{%s}' % value, False)
369 for value in ('1', 'true', 'yes', 'on'):
370 check(value, True)
371 check('"%s"' % value, True)
372 check('{%s}' % value, True)
373 check('8.2 + 6', True)
Serhiy Storchakafc055252014-02-03 20:41:34 +0200374 check('3.1 + $a', True)
375 check('2 + "$a.$b"', True)
376 check('4*[llength "6 2"]', True)
377 check('{word one} < "word $a"', False)
378 check('4*2 < 7', False)
379 check('hypot($a, 4)', True)
380 check('5 / 4', True)
381 check('5 / 4.0', True)
382 check('5 / ( [string length "abcd"] + 0.0 )', True)
383 check('20.0/5.0', True)
384 check('"0x03" > "2"', True)
385 check('[string length "a\xbd\u20ac"]', True)
386 check(r'[string length "a\xbd\u20ac"]', True)
387 self.assertRaises(TclError, tcl.exprboolean, '"abc"')
Serhiy Storchakaea134da2015-04-02 18:46:50 +0300388 if tcl_version >= (8, 5): # bignum was added in Tcl 8.5
Serhiy Storchaka160f8922014-02-03 22:31:09 +0200389 check('2**64', True)
Serhiy Storchakafc055252014-02-03 20:41:34 +0200390
Serhiy Storchakaa5a4bd72015-04-02 19:57:52 +0300391 @unittest.skipUnless(tcl_version >= (8, 5), 'requires Tcl version >= 8.5')
Serhiy Storchakaf7de3dd2015-04-02 10:35:57 +0300392 def test_booleans(self):
393 tcl = self.interp
394 def check(expr, expected):
395 result = tcl.call('expr', expr)
Serhiy Storchaka9171fe52015-04-02 11:46:07 +0300396 if tcl.wantobjects():
397 self.assertEqual(result, expected)
398 self.assertIsInstance(result, int)
399 else:
400 self.assertIn(result, (expr, str(int(expected))))
401 self.assertIsInstance(result, str)
Serhiy Storchakaf7de3dd2015-04-02 10:35:57 +0300402 check('true', True)
403 check('yes', True)
404 check('on', True)
405 check('false', False)
406 check('no', False)
407 check('off', False)
408 check('1 < 2', True)
409 check('1 > 2', False)
410
Serhiy Storchakaea134da2015-04-02 18:46:50 +0300411 def test_expr_bignum(self):
412 tcl = self.interp
413 for i in self.get_integers():
414 result = tcl.call('expr', str(i))
415 if self.wantobjects:
416 self.assertEqual(result, i)
417 self.assertIsInstance(result, int)
418 else:
419 self.assertEqual(result, str(i))
420 self.assertIsInstance(result, str)
421 if tcl_version < (8, 5): # bignum was added in Tcl 8.5
Serhiy Storchaka2379d542015-04-02 20:07:09 +0300422 self.assertRaises(TclError, tcl.call, 'expr', str(2**1000))
Serhiy Storchakaea134da2015-04-02 18:46:50 +0300423
Serhiy Storchakadf4bb462013-02-07 15:40:03 +0200424 def test_passing_values(self):
425 def passValue(value):
426 return self.interp.call('set', '_', value)
427
Serhiy Storchakacc4290b2013-12-25 17:29:01 +0200428 self.assertEqual(passValue(True), True if self.wantobjects else '1')
429 self.assertEqual(passValue(False), False if self.wantobjects else '0')
Serhiy Storchakadf4bb462013-02-07 15:40:03 +0200430 self.assertEqual(passValue('string'), 'string')
431 self.assertEqual(passValue('string\u20ac'), 'string\u20ac')
Serhiy Storchaka1317e142014-02-03 21:24:07 +0200432 self.assertEqual(passValue('str\x00ing'), 'str\x00ing')
433 self.assertEqual(passValue('str\x00ing\xbd'), 'str\x00ing\xbd')
434 self.assertEqual(passValue('str\x00ing\u20ac'), 'str\x00ing\u20ac')
Serhiy Storchaka74596a82014-07-30 18:33:13 +0300435 self.assertEqual(passValue(b'str\x00ing'),
436 b'str\x00ing' if self.wantobjects else 'str\x00ing')
437 self.assertEqual(passValue(b'str\xc0\x80ing'),
438 b'str\xc0\x80ing' if self.wantobjects else 'str\xc0\x80ing')
439 self.assertEqual(passValue(b'str\xbding'),
440 b'str\xbding' if self.wantobjects else 'str\xbding')
Serhiy Storchakaea134da2015-04-02 18:46:50 +0300441 for i in self.get_integers():
Serhiy Storchakacc4290b2013-12-25 17:29:01 +0200442 self.assertEqual(passValue(i), i if self.wantobjects else str(i))
Serhiy Storchakaea134da2015-04-02 18:46:50 +0300443 if tcl_version < (8, 5): # bignum was added in Tcl 8.5
444 self.assertEqual(passValue(2**1000), str(2**1000))
Serhiy Storchakadf4bb462013-02-07 15:40:03 +0200445 for f in (0.0, 1.0, -1.0, 1/3,
446 sys.float_info.min, sys.float_info.max,
447 -sys.float_info.min, -sys.float_info.max):
Serhiy Storchakacc4290b2013-12-25 17:29:01 +0200448 if self.wantobjects:
Serhiy Storchakadf4bb462013-02-07 15:40:03 +0200449 self.assertEqual(passValue(f), f)
Serhiy Storchakacc4290b2013-12-25 17:29:01 +0200450 else:
451 self.assertEqual(float(passValue(f)), f)
452 if self.wantobjects:
453 f = passValue(float('nan'))
454 self.assertNotEqual(f, f)
455 self.assertEqual(passValue(float('inf')), float('inf'))
456 self.assertEqual(passValue(-float('inf')), -float('inf'))
457 else:
Serhiy Storchakacc4290b2013-12-25 17:29:01 +0200458 self.assertEqual(float(passValue(float('inf'))), float('inf'))
459 self.assertEqual(float(passValue(-float('inf'))), -float('inf'))
Serhiy Storchaka6f1435c2014-07-07 14:57:08 +0300460 # XXX NaN representation can be not parsable by float()
Serhiy Storchakacc4290b2013-12-25 17:29:01 +0200461 self.assertEqual(passValue((1, '2', (3.4,))),
462 (1, '2', (3.4,)) if self.wantobjects else '1 2 3.4')
Serhiy Storchaka2b00c492014-05-21 17:12:21 +0300463 self.assertEqual(passValue(['a', ['b', 'c']]),
464 ('a', ('b', 'c')) if self.wantobjects else 'a {b c}')
Martin v. Löwis2d5157e2010-06-04 19:50:26 +0000465
Serhiy Storchaka4b730162014-01-23 09:44:05 +0200466 def test_user_command(self):
467 result = None
468 def testfunc(arg):
469 nonlocal result
470 result = arg
471 return arg
472 self.interp.createcommand('testfunc', testfunc)
Antoine Pitrou220cc212014-02-23 19:39:06 +0100473 self.addCleanup(self.interp.tk.deletecommand, 'testfunc')
Serhiy Storchakad6ec3092014-08-18 17:47:29 +0300474 def check(value, expected=None, *, eq=self.assertEqual):
475 if expected is None:
476 expected = value
477 nonlocal result
478 result = None
Serhiy Storchakabdf0cb52014-01-23 16:48:44 +0200479 r = self.interp.call('testfunc', value)
480 self.assertIsInstance(result, str)
481 eq(result, expected)
482 self.assertIsInstance(r, str)
483 eq(r, expected)
484 def float_eq(actual, expected):
Serhiy Storchakabdf0cb52014-01-23 16:48:44 +0200485 self.assertAlmostEqual(float(actual), expected,
486 delta=abs(expected) * 1e-10)
Serhiy Storchaka4b730162014-01-23 09:44:05 +0200487
488 check(True, '1')
489 check(False, '0')
Serhiy Storchakad6ec3092014-08-18 17:47:29 +0300490 check('string')
491 check('string\xbd')
492 check('string\u20ac')
Serhiy Storchakaabf68ce2014-09-11 10:57:13 +0300493 check('')
Serhiy Storchaka1317e142014-02-03 21:24:07 +0200494 check(b'string', 'string')
Serhiy Storchaka74596a82014-07-30 18:33:13 +0300495 check(b'string\xe2\x82\xac', 'string\xe2\x82\xac')
496 check(b'string\xbd', 'string\xbd')
Serhiy Storchakaabf68ce2014-09-11 10:57:13 +0300497 check(b'', '')
Serhiy Storchakad6ec3092014-08-18 17:47:29 +0300498 check('str\x00ing')
499 check('str\x00ing\xbd')
500 check('str\x00ing\u20ac')
Serhiy Storchaka74596a82014-07-30 18:33:13 +0300501 check(b'str\x00ing', 'str\x00ing')
502 check(b'str\xc0\x80ing', 'str\xc0\x80ing')
503 check(b'str\xc0\x80ing\xe2\x82\xac', 'str\xc0\x80ing\xe2\x82\xac')
Serhiy Storchakaea134da2015-04-02 18:46:50 +0300504 for i in self.get_integers():
Serhiy Storchaka4b730162014-01-23 09:44:05 +0200505 check(i, str(i))
Serhiy Storchakaea134da2015-04-02 18:46:50 +0300506 if tcl_version < (8, 5): # bignum was added in Tcl 8.5
507 check(2**1000, str(2**1000))
Serhiy Storchakabdf0cb52014-01-23 16:48:44 +0200508 for f in (0.0, 1.0, -1.0):
509 check(f, repr(f))
510 for f in (1/3.0, sys.float_info.min, sys.float_info.max,
Serhiy Storchaka4b730162014-01-23 09:44:05 +0200511 -sys.float_info.min, -sys.float_info.max):
Serhiy Storchakad6ec3092014-08-18 17:47:29 +0300512 check(f, eq=float_eq)
513 check(float('inf'), eq=float_eq)
514 check(-float('inf'), eq=float_eq)
Serhiy Storchaka6f1435c2014-07-07 14:57:08 +0300515 # XXX NaN representation can be not parsable by float()
Serhiy Storchaka4b730162014-01-23 09:44:05 +0200516 check((), '')
517 check((1, (2,), (3, 4), '5 6', ()), '1 2 {3 4} {5 6} {}')
Serhiy Storchaka2b00c492014-05-21 17:12:21 +0300518 check([1, [2,], [3, 4], '5 6', []], '1 2 {3 4} {5 6} {}')
Serhiy Storchaka4b730162014-01-23 09:44:05 +0200519
Serhiy Storchaka275d5fd2013-07-11 20:34:47 +0300520 def test_splitlist(self):
521 splitlist = self.interp.tk.splitlist
522 call = self.interp.tk.call
523 self.assertRaises(TypeError, splitlist)
524 self.assertRaises(TypeError, splitlist, 'a', 'b')
525 self.assertRaises(TypeError, splitlist, 2)
526 testcases = [
527 ('2', ('2',)),
528 ('', ()),
529 ('{}', ('',)),
530 ('""', ('',)),
531 ('a\n b\t\r c\n ', ('a', 'b', 'c')),
532 (b'a\n b\t\r c\n ', ('a', 'b', 'c')),
533 ('a \u20ac', ('a', '\u20ac')),
534 (b'a \xe2\x82\xac', ('a', '\u20ac')),
Serhiy Storchaka1317e142014-02-03 21:24:07 +0200535 (b'a\xc0\x80b c\xc0\x80d', ('a\x00b', 'c\x00d')),
Serhiy Storchaka275d5fd2013-07-11 20:34:47 +0300536 ('a {b c}', ('a', 'b c')),
537 (r'a b\ c', ('a', 'b c')),
538 (('a', 'b c'), ('a', 'b c')),
539 ('a 2', ('a', '2')),
540 (('a', 2), ('a', 2)),
541 ('a 3.4', ('a', '3.4')),
542 (('a', 3.4), ('a', 3.4)),
543 ((), ()),
Serhiy Storchaka2b00c492014-05-21 17:12:21 +0300544 ([], ()),
545 (['a', ['b', 'c']], ('a', ['b', 'c'])),
Serhiy Storchakacc4290b2013-12-25 17:29:01 +0200546 (call('list', 1, '2', (3.4,)),
547 (1, '2', (3.4,)) if self.wantobjects else
548 ('1', '2', '3.4')),
Serhiy Storchaka275d5fd2013-07-11 20:34:47 +0300549 ]
Victor Stinnerece38d92014-09-04 09:53:16 +0200550 tk_patchlevel = get_tk_patchlevel()
Serhiy Storchakadfa689b2013-09-08 20:29:37 +0300551 if tcl_version >= (8, 5):
Victor Stinnerece38d92014-09-04 09:53:16 +0200552 if not self.wantobjects or tk_patchlevel < (8, 5, 5):
Serhiy Storchaka92af06b2014-02-02 23:04:24 +0200553 # Before 8.5.5 dicts were converted to lists through string
Serhiy Storchaka74596a82014-07-30 18:33:13 +0300554 expected = ('12', '\u20ac', '\xe2\x82\xac', '3.4')
Serhiy Storchaka92af06b2014-02-02 23:04:24 +0200555 else:
Serhiy Storchaka74596a82014-07-30 18:33:13 +0300556 expected = (12, '\u20ac', b'\xe2\x82\xac', (3.4,))
Serhiy Storchakadfa689b2013-09-08 20:29:37 +0300557 testcases += [
Serhiy Storchaka92af06b2014-02-02 23:04:24 +0200558 (call('dict', 'create', 12, '\u20ac', b'\xe2\x82\xac', (3.4,)),
559 expected),
Serhiy Storchakadfa689b2013-09-08 20:29:37 +0300560 ]
Victor Stinnerece38d92014-09-04 09:53:16 +0200561 dbg_info = ('want objects? %s, Tcl version: %s, Tk patchlevel: %s'
562 % (self.wantobjects, tcl_version, tk_patchlevel))
Serhiy Storchaka275d5fd2013-07-11 20:34:47 +0300563 for arg, res in testcases:
Victor Stinnerece38d92014-09-04 09:53:16 +0200564 self.assertEqual(splitlist(arg), res,
565 'arg=%a, %s' % (arg, dbg_info))
Serhiy Storchaka275d5fd2013-07-11 20:34:47 +0300566 self.assertRaises(TclError, splitlist, '{')
567
568 def test_split(self):
569 split = self.interp.tk.split
570 call = self.interp.tk.call
571 self.assertRaises(TypeError, split)
572 self.assertRaises(TypeError, split, 'a', 'b')
573 self.assertRaises(TypeError, split, 2)
574 testcases = [
575 ('2', '2'),
576 ('', ''),
577 ('{}', ''),
578 ('""', ''),
579 ('{', '{'),
580 ('a\n b\t\r c\n ', ('a', 'b', 'c')),
581 (b'a\n b\t\r c\n ', ('a', 'b', 'c')),
582 ('a \u20ac', ('a', '\u20ac')),
583 (b'a \xe2\x82\xac', ('a', '\u20ac')),
Serhiy Storchaka1317e142014-02-03 21:24:07 +0200584 (b'a\xc0\x80b', 'a\x00b'),
585 (b'a\xc0\x80b c\xc0\x80d', ('a\x00b', 'c\x00d')),
586 (b'{a\xc0\x80b c\xc0\x80d', '{a\x00b c\x00d'),
Serhiy Storchaka275d5fd2013-07-11 20:34:47 +0300587 ('a {b c}', ('a', ('b', 'c'))),
588 (r'a b\ c', ('a', ('b', 'c'))),
589 (('a', b'b c'), ('a', ('b', 'c'))),
590 (('a', 'b c'), ('a', ('b', 'c'))),
591 ('a 2', ('a', '2')),
592 (('a', 2), ('a', 2)),
593 ('a 3.4', ('a', '3.4')),
594 (('a', 3.4), ('a', 3.4)),
595 (('a', (2, 3.4)), ('a', (2, 3.4))),
596 ((), ()),
Serhiy Storchaka2b00c492014-05-21 17:12:21 +0300597 ([], ()),
598 (['a', 'b c'], ('a', ('b', 'c'))),
599 (['a', ['b', 'c']], ('a', ('b', 'c'))),
Serhiy Storchakacc4290b2013-12-25 17:29:01 +0200600 (call('list', 1, '2', (3.4,)),
601 (1, '2', (3.4,)) if self.wantobjects else
602 ('1', '2', '3.4')),
Serhiy Storchaka275d5fd2013-07-11 20:34:47 +0300603 ]
Serhiy Storchakadfa689b2013-09-08 20:29:37 +0300604 if tcl_version >= (8, 5):
Serhiy Storchaka92af06b2014-02-02 23:04:24 +0200605 if not self.wantobjects or get_tk_patchlevel() < (8, 5, 5):
606 # Before 8.5.5 dicts were converted to lists through string
Serhiy Storchaka74596a82014-07-30 18:33:13 +0300607 expected = ('12', '\u20ac', '\xe2\x82\xac', '3.4')
Serhiy Storchaka92af06b2014-02-02 23:04:24 +0200608 else:
Serhiy Storchaka74596a82014-07-30 18:33:13 +0300609 expected = (12, '\u20ac', b'\xe2\x82\xac', (3.4,))
Serhiy Storchakadfa689b2013-09-08 20:29:37 +0300610 testcases += [
611 (call('dict', 'create', 12, '\u20ac', b'\xe2\x82\xac', (3.4,)),
Serhiy Storchaka92af06b2014-02-02 23:04:24 +0200612 expected),
Serhiy Storchakadfa689b2013-09-08 20:29:37 +0300613 ]
Serhiy Storchaka275d5fd2013-07-11 20:34:47 +0300614 for arg, res in testcases:
615 self.assertEqual(split(arg), res, msg=arg)
616
Serhiy Storchaka8f0a1d02014-09-06 22:47:58 +0300617 def test_splitdict(self):
618 splitdict = tkinter._splitdict
619 tcl = self.interp.tk
620
621 arg = '-a {1 2 3} -something foo status {}'
622 self.assertEqual(splitdict(tcl, arg, False),
623 {'-a': '1 2 3', '-something': 'foo', 'status': ''})
624 self.assertEqual(splitdict(tcl, arg),
625 {'a': '1 2 3', 'something': 'foo', 'status': ''})
626
627 arg = ('-a', (1, 2, 3), '-something', 'foo', 'status', '{}')
628 self.assertEqual(splitdict(tcl, arg, False),
629 {'-a': (1, 2, 3), '-something': 'foo', 'status': '{}'})
630 self.assertEqual(splitdict(tcl, arg),
631 {'a': (1, 2, 3), 'something': 'foo', 'status': '{}'})
632
633 self.assertRaises(RuntimeError, splitdict, tcl, '-a b -c ')
634 self.assertRaises(RuntimeError, splitdict, tcl, ('-a', 'b', '-c'))
635
636 arg = tcl.call('list',
637 '-a', (1, 2, 3), '-something', 'foo', 'status', ())
638 self.assertEqual(splitdict(tcl, arg),
639 {'a': (1, 2, 3) if self.wantobjects else '1 2 3',
640 'something': 'foo', 'status': ''})
641
642 if tcl_version >= (8, 5):
643 arg = tcl.call('dict', 'create',
644 '-a', (1, 2, 3), '-something', 'foo', 'status', ())
645 if not self.wantobjects or get_tk_patchlevel() < (8, 5, 5):
646 # Before 8.5.5 dicts were converted to lists through string
647 expected = {'a': '1 2 3', 'something': 'foo', 'status': ''}
648 else:
649 expected = {'a': (1, 2, 3), 'something': 'foo', 'status': ''}
650 self.assertEqual(splitdict(tcl, arg), expected)
651
Neal Norwitz63dfece2004-02-19 02:37:29 +0000652
Serhiy Storchaka9e6b9752013-08-21 21:38:21 +0300653class BigmemTclTest(unittest.TestCase):
654
655 def setUp(self):
656 self.interp = Tcl()
657
Serhiy Storchaka5cfc79d2014-02-07 10:06:39 +0200658 @support.cpython_only
659 @unittest.skipUnless(INT_MAX < PY_SSIZE_T_MAX, "needs UINT_MAX < SIZE_MAX")
660 @support.bigmemtest(size=INT_MAX + 1, memuse=5, dry_run=False)
Serhiy Storchaka79851d72014-05-30 14:24:03 +0300661 def test_huge_string_call(self, size):
Serhiy Storchaka9e6b9752013-08-21 21:38:21 +0300662 value = ' ' * size
663 self.assertRaises(OverflowError, self.interp.call, 'set', '_', value)
664
Serhiy Storchaka79851d72014-05-30 14:24:03 +0300665 @support.cpython_only
666 @unittest.skipUnless(INT_MAX < PY_SSIZE_T_MAX, "needs UINT_MAX < SIZE_MAX")
667 @support.bigmemtest(size=INT_MAX + 1, memuse=9, dry_run=False)
668 def test_huge_string_builtins(self, size):
669 value = '1' + ' ' * size
Serhiy Storchakaaecfa9e2014-05-30 15:54:35 +0300670 self.assertRaises(OverflowError, self.interp.tk.getint, value)
671 self.assertRaises(OverflowError, self.interp.tk.getdouble, value)
672 self.assertRaises(OverflowError, self.interp.tk.getboolean, value)
Serhiy Storchaka79851d72014-05-30 14:24:03 +0300673 self.assertRaises(OverflowError, self.interp.eval, value)
674 self.assertRaises(OverflowError, self.interp.evalfile, value)
675 self.assertRaises(OverflowError, self.interp.record, value)
676 self.assertRaises(OverflowError, self.interp.adderrorinfo, value)
677 self.assertRaises(OverflowError, self.interp.setvar, value, 'x', 'a')
678 self.assertRaises(OverflowError, self.interp.setvar, 'x', value, 'a')
679 self.assertRaises(OverflowError, self.interp.unsetvar, value)
680 self.assertRaises(OverflowError, self.interp.unsetvar, 'x', value)
681 self.assertRaises(OverflowError, self.interp.adderrorinfo, value)
682 self.assertRaises(OverflowError, self.interp.exprstring, value)
683 self.assertRaises(OverflowError, self.interp.exprlong, value)
684 self.assertRaises(OverflowError, self.interp.exprboolean, value)
685 self.assertRaises(OverflowError, self.interp.splitlist, value)
686 self.assertRaises(OverflowError, self.interp.split, value)
687 self.assertRaises(OverflowError, self.interp.createcommand, value, max)
688 self.assertRaises(OverflowError, self.interp.deletecommand, value)
689
Serhiy Storchaka9e6b9752013-08-21 21:38:21 +0300690
Serhiy Storchaka8db18232013-11-20 17:43:49 +0200691def setUpModule():
692 if support.verbose:
693 tcl = Tcl()
694 print('patchlevel =', tcl.call('info', 'patchlevel'))
695
696
Neal Norwitz63dfece2004-02-19 02:37:29 +0000697def test_main():
Serhiy Storchaka9e6b9752013-08-21 21:38:21 +0300698 support.run_unittest(TclTest, TkinterTest, BigmemTclTest)
Neal Norwitz63dfece2004-02-19 02:37:29 +0000699
David Aschere2b4b322004-02-18 05:59:53 +0000700if __name__ == "__main__":
Neal Norwitz63dfece2004-02-19 02:37:29 +0000701 test_main()