blob: 66e9d49dfeaf32f035c077a25d4fcb6e84ec1b56 [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
Terry Jan Reedy743c85a2013-03-16 02:37:06 -040010# Make sure tkinter._fix runs to set up the environment
Serhiy Storchaka8f0a1d02014-09-06 22:47:58 +030011tkinter = support.import_fresh_module('tkinter')
Terry Jan Reedy743c85a2013-03-16 02:37:06 -040012
Guilherme Polofa8fba92009-02-07 02:33:47 +000013from tkinter import Tcl
David Aschere2b4b322004-02-18 05:59:53 +000014from _tkinter import TclError
15
Serhiy Storchaka5cfc79d2014-02-07 10:06:39 +020016try:
17 from _testcapi import INT_MAX, PY_SSIZE_T_MAX
18except ImportError:
19 INT_MAX = PY_SSIZE_T_MAX = sys.maxsize
20
Serhiy Storchaka462c3572015-04-22 08:36:03 +030021tcl_version = tuple(map(int, _tkinter.TCL_VERSION.split('.')))
Serhiy Storchakadfa689b2013-09-08 20:29:37 +030022
Serhiy Storchaka92af06b2014-02-02 23:04:24 +020023_tk_patchlevel = None
24def get_tk_patchlevel():
25 global _tk_patchlevel
26 if _tk_patchlevel is None:
27 tcl = Tcl()
Serhiy Storchaka462c3572015-04-22 08:36:03 +030028 patchlevel = tcl.call('info', 'patchlevel')
29 m = re.fullmatch(r'(\d+)\.(\d+)([ab.])(\d+)', patchlevel)
30 major, minor, releaselevel, serial = m.groups()
31 major, minor, serial = int(major), int(minor), int(serial)
32 releaselevel = {'a': 'alpha', 'b': 'beta', '.': 'final'}[releaselevel]
33 if releaselevel == 'final':
34 _tk_patchlevel = major, minor, serial, releaselevel, 0
35 else:
36 _tk_patchlevel = major, minor, 0, releaselevel, serial
Serhiy Storchaka92af06b2014-02-02 23:04:24 +020037 return _tk_patchlevel
38
Benjamin Petersonc4bbc8d2009-01-30 03:39:35 +000039
40class TkinterTest(unittest.TestCase):
41
42 def testFlattenLen(self):
43 # flatten(<object with no length>)
44 self.assertRaises(TypeError, _tkinter._flatten, True)
45
46
David Aschere2b4b322004-02-18 05:59:53 +000047class TclTest(unittest.TestCase):
48
49 def setUp(self):
50 self.interp = Tcl()
Serhiy Storchakacc4290b2013-12-25 17:29:01 +020051 self.wantobjects = self.interp.tk.wantobjects()
David Aschere2b4b322004-02-18 05:59:53 +000052
53 def testEval(self):
54 tcl = self.interp
55 tcl.eval('set a 1')
56 self.assertEqual(tcl.eval('set a'),'1')
57
Serhiy Storchaka1317e142014-02-03 21:24:07 +020058 def test_eval_null_in_result(self):
59 tcl = self.interp
60 self.assertEqual(tcl.eval('set a "a\\0b"'), 'a\x00b')
61
David Aschere2b4b322004-02-18 05:59:53 +000062 def testEvalException(self):
63 tcl = self.interp
64 self.assertRaises(TclError,tcl.eval,'set a')
65
66 def testEvalException2(self):
67 tcl = self.interp
68 self.assertRaises(TclError,tcl.eval,'this is wrong')
69
70 def testCall(self):
71 tcl = self.interp
72 tcl.call('set','a','1')
73 self.assertEqual(tcl.call('set','a'),'1')
74
75 def testCallException(self):
76 tcl = self.interp
77 self.assertRaises(TclError,tcl.call,'set','a')
78
79 def testCallException2(self):
80 tcl = self.interp
81 self.assertRaises(TclError,tcl.call,'this','is','wrong')
82
83 def testSetVar(self):
84 tcl = self.interp
85 tcl.setvar('a','1')
86 self.assertEqual(tcl.eval('set a'),'1')
87
88 def testSetVarArray(self):
89 tcl = self.interp
90 tcl.setvar('a(1)','1')
91 self.assertEqual(tcl.eval('set a(1)'),'1')
92
93 def testGetVar(self):
94 tcl = self.interp
95 tcl.eval('set a 1')
96 self.assertEqual(tcl.getvar('a'),'1')
97
98 def testGetVarArray(self):
99 tcl = self.interp
100 tcl.eval('set a(1) 1')
101 self.assertEqual(tcl.getvar('a(1)'),'1')
102
103 def testGetVarException(self):
104 tcl = self.interp
105 self.assertRaises(TclError,tcl.getvar,'a')
106
107 def testGetVarArrayException(self):
108 tcl = self.interp
109 self.assertRaises(TclError,tcl.getvar,'a(1)')
110
111 def testUnsetVar(self):
112 tcl = self.interp
113 tcl.setvar('a',1)
114 self.assertEqual(tcl.eval('info exists a'),'1')
115 tcl.unsetvar('a')
116 self.assertEqual(tcl.eval('info exists a'),'0')
117
118 def testUnsetVarArray(self):
119 tcl = self.interp
120 tcl.setvar('a(1)',1)
121 tcl.setvar('a(2)',2)
122 self.assertEqual(tcl.eval('info exists a(1)'),'1')
123 self.assertEqual(tcl.eval('info exists a(2)'),'1')
124 tcl.unsetvar('a(1)')
125 self.assertEqual(tcl.eval('info exists a(1)'),'0')
126 self.assertEqual(tcl.eval('info exists a(2)'),'1')
127
128 def testUnsetVarException(self):
129 tcl = self.interp
130 self.assertRaises(TclError,tcl.unsetvar,'a')
Tim Peters27f88362004-07-08 04:22:35 +0000131
Serhiy Storchakaea134da2015-04-02 18:46:50 +0300132 def get_integers(self):
133 integers = (0, 1, -1, 2**31-1, -2**31)
134 if tcl_version >= (8, 4): # wideInt was added in Tcl 8.4
135 integers += (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)
168 self.assertRaises(TypeError, tcl.getdouble)
169 self.assertRaises(TypeError, tcl.getdouble, '42.5', '10')
170 self.assertRaises(TypeError, tcl.getdouble, b'42.5')
171 self.assertRaises(TypeError, tcl.getdouble, 42)
172 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
Serhiy Storchaka1317e142014-02-03 21:24:07 +0200196 with open(support.TESTFN, 'w') as f:
197 self.addCleanup(support.unlink, support.TESTFN)
198 f.write("""set a 1
199 set b 2
200 set c [ expr $a + $b ]
201 """)
202 tcl.evalfile(support.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
209 with open(support.TESTFN, 'w') as f:
210 self.addCleanup(support.unlink, support.TESTFN)
211 f.write("""
212 set a "a\0b"
213 set b "a\\0b"
214 """)
215 tcl.evalfile(support.TESTFN)
216 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
Georg Brandlec5ae3b2010-07-31 19:17:11 +0000247 with support.EnvironmentVarGuard() as env:
Martin v. Löwis2d5157e2010-06-04 19:50:26 +0000248 env.unset("TCL_LIBRARY")
Hirokazu Yamamotof2dec8d2010-09-18 04:42:41 +0000249 f = os.popen('%s -c "import tkinter; print(tkinter)"' % (unc_name,))
Martin v. Löwis2d5157e2010-06-04 19:50:26 +0000250
Hirokazu Yamamotof2dec8d2010-09-18 04:42:41 +0000251 self.assertIn('tkinter', f.read())
Martin v. Löwis2d5157e2010-06-04 19:50:26 +0000252 # exit code must be zero
253 self.assertEqual(f.close(), None)
254
Serhiy Storchakafc055252014-02-03 20:41:34 +0200255 def test_exprstring(self):
256 tcl = self.interp
257 tcl.call('set', 'a', 3)
258 tcl.call('set', 'b', 6)
259 def check(expr, expected):
260 result = tcl.exprstring(expr)
261 self.assertEqual(result, expected)
262 self.assertIsInstance(result, str)
263
264 self.assertRaises(TypeError, tcl.exprstring)
265 self.assertRaises(TypeError, tcl.exprstring, '8.2', '+6')
266 self.assertRaises(TypeError, tcl.exprstring, b'8.2 + 6')
267 self.assertRaises(TclError, tcl.exprstring, 'spam')
268 check('', '0')
269 check('8.2 + 6', '14.2')
Serhiy Storchakafc055252014-02-03 20:41:34 +0200270 check('3.1 + $a', '6.1')
271 check('2 + "$a.$b"', '5.6')
272 check('4*[llength "6 2"]', '8')
273 check('{word one} < "word $a"', '0')
274 check('4*2 < 7', '0')
275 check('hypot($a, 4)', '5.0')
276 check('5 / 4', '1')
277 check('5 / 4.0', '1.25')
278 check('5 / ( [string length "abcd"] + 0.0 )', '1.25')
279 check('20.0/5.0', '4.0')
280 check('"0x03" > "2"', '1')
281 check('[string length "a\xbd\u20ac"]', '3')
282 check(r'[string length "a\xbd\u20ac"]', '3')
283 check('"abc"', 'abc')
284 check('"a\xbd\u20ac"', 'a\xbd\u20ac')
285 check(r'"a\xbd\u20ac"', 'a\xbd\u20ac')
Serhiy Storchaka1317e142014-02-03 21:24:07 +0200286 check(r'"a\0b"', 'a\x00b')
Serhiy Storchakaea134da2015-04-02 18:46:50 +0300287 if tcl_version >= (8, 5): # bignum was added in Tcl 8.5
Serhiy Storchaka160f8922014-02-03 22:31:09 +0200288 check('2**64', str(2**64))
Serhiy Storchakafc055252014-02-03 20:41:34 +0200289
290 def test_exprdouble(self):
291 tcl = self.interp
292 tcl.call('set', 'a', 3)
293 tcl.call('set', 'b', 6)
294 def check(expr, expected):
295 result = tcl.exprdouble(expr)
296 self.assertEqual(result, expected)
297 self.assertIsInstance(result, float)
298
299 self.assertRaises(TypeError, tcl.exprdouble)
300 self.assertRaises(TypeError, tcl.exprdouble, '8.2', '+6')
301 self.assertRaises(TypeError, tcl.exprdouble, b'8.2 + 6')
302 self.assertRaises(TclError, tcl.exprdouble, 'spam')
303 check('', 0.0)
304 check('8.2 + 6', 14.2)
Serhiy Storchakafc055252014-02-03 20:41:34 +0200305 check('3.1 + $a', 6.1)
306 check('2 + "$a.$b"', 5.6)
307 check('4*[llength "6 2"]', 8.0)
308 check('{word one} < "word $a"', 0.0)
309 check('4*2 < 7', 0.0)
310 check('hypot($a, 4)', 5.0)
311 check('5 / 4', 1.0)
312 check('5 / 4.0', 1.25)
313 check('5 / ( [string length "abcd"] + 0.0 )', 1.25)
314 check('20.0/5.0', 4.0)
315 check('"0x03" > "2"', 1.0)
316 check('[string length "a\xbd\u20ac"]', 3.0)
317 check(r'[string length "a\xbd\u20ac"]', 3.0)
318 self.assertRaises(TclError, tcl.exprdouble, '"abc"')
Serhiy Storchakaea134da2015-04-02 18:46:50 +0300319 if tcl_version >= (8, 5): # bignum was added in Tcl 8.5
Serhiy Storchaka160f8922014-02-03 22:31:09 +0200320 check('2**64', float(2**64))
Serhiy Storchakafc055252014-02-03 20:41:34 +0200321
322 def test_exprlong(self):
323 tcl = self.interp
324 tcl.call('set', 'a', 3)
325 tcl.call('set', 'b', 6)
326 def check(expr, expected):
327 result = tcl.exprlong(expr)
328 self.assertEqual(result, expected)
329 self.assertIsInstance(result, int)
330
331 self.assertRaises(TypeError, tcl.exprlong)
332 self.assertRaises(TypeError, tcl.exprlong, '8.2', '+6')
333 self.assertRaises(TypeError, tcl.exprlong, b'8.2 + 6')
334 self.assertRaises(TclError, tcl.exprlong, 'spam')
335 check('', 0)
336 check('8.2 + 6', 14)
Serhiy Storchakafc055252014-02-03 20:41:34 +0200337 check('3.1 + $a', 6)
338 check('2 + "$a.$b"', 5)
339 check('4*[llength "6 2"]', 8)
340 check('{word one} < "word $a"', 0)
341 check('4*2 < 7', 0)
342 check('hypot($a, 4)', 5)
343 check('5 / 4', 1)
344 check('5 / 4.0', 1)
345 check('5 / ( [string length "abcd"] + 0.0 )', 1)
346 check('20.0/5.0', 4)
347 check('"0x03" > "2"', 1)
348 check('[string length "a\xbd\u20ac"]', 3)
349 check(r'[string length "a\xbd\u20ac"]', 3)
350 self.assertRaises(TclError, tcl.exprlong, '"abc"')
Serhiy Storchakaea134da2015-04-02 18:46:50 +0300351 if tcl_version >= (8, 5): # bignum was added in Tcl 8.5
Serhiy Storchaka160f8922014-02-03 22:31:09 +0200352 self.assertRaises(TclError, tcl.exprlong, '2**64')
Serhiy Storchakafc055252014-02-03 20:41:34 +0200353
354 def test_exprboolean(self):
355 tcl = self.interp
356 tcl.call('set', 'a', 3)
357 tcl.call('set', 'b', 6)
358 def check(expr, expected):
359 result = tcl.exprboolean(expr)
360 self.assertEqual(result, expected)
361 self.assertIsInstance(result, int)
362 self.assertNotIsInstance(result, bool)
363
364 self.assertRaises(TypeError, tcl.exprboolean)
365 self.assertRaises(TypeError, tcl.exprboolean, '8.2', '+6')
366 self.assertRaises(TypeError, tcl.exprboolean, b'8.2 + 6')
367 self.assertRaises(TclError, tcl.exprboolean, 'spam')
368 check('', False)
369 for value in ('0', 'false', 'no', 'off'):
370 check(value, False)
371 check('"%s"' % value, False)
372 check('{%s}' % value, False)
373 for value in ('1', 'true', 'yes', 'on'):
374 check(value, True)
375 check('"%s"' % value, True)
376 check('{%s}' % value, True)
377 check('8.2 + 6', True)
Serhiy Storchakafc055252014-02-03 20:41:34 +0200378 check('3.1 + $a', True)
379 check('2 + "$a.$b"', True)
380 check('4*[llength "6 2"]', True)
381 check('{word one} < "word $a"', False)
382 check('4*2 < 7', False)
383 check('hypot($a, 4)', True)
384 check('5 / 4', True)
385 check('5 / 4.0', True)
386 check('5 / ( [string length "abcd"] + 0.0 )', True)
387 check('20.0/5.0', True)
388 check('"0x03" > "2"', True)
389 check('[string length "a\xbd\u20ac"]', True)
390 check(r'[string length "a\xbd\u20ac"]', True)
391 self.assertRaises(TclError, tcl.exprboolean, '"abc"')
Serhiy Storchakaea134da2015-04-02 18:46:50 +0300392 if tcl_version >= (8, 5): # bignum was added in Tcl 8.5
Serhiy Storchaka160f8922014-02-03 22:31:09 +0200393 check('2**64', True)
Serhiy Storchakafc055252014-02-03 20:41:34 +0200394
Serhiy Storchakaa5a4bd72015-04-02 19:57:52 +0300395 @unittest.skipUnless(tcl_version >= (8, 5), 'requires Tcl version >= 8.5')
Serhiy Storchakaf7de3dd2015-04-02 10:35:57 +0300396 def test_booleans(self):
397 tcl = self.interp
398 def check(expr, expected):
399 result = tcl.call('expr', expr)
Serhiy Storchaka9171fe52015-04-02 11:46:07 +0300400 if tcl.wantobjects():
401 self.assertEqual(result, expected)
402 self.assertIsInstance(result, int)
403 else:
404 self.assertIn(result, (expr, str(int(expected))))
405 self.assertIsInstance(result, str)
Serhiy Storchakaf7de3dd2015-04-02 10:35:57 +0300406 check('true', True)
407 check('yes', True)
408 check('on', True)
409 check('false', False)
410 check('no', False)
411 check('off', False)
412 check('1 < 2', True)
413 check('1 > 2', False)
414
Serhiy Storchakaea134da2015-04-02 18:46:50 +0300415 def test_expr_bignum(self):
416 tcl = self.interp
417 for i in self.get_integers():
418 result = tcl.call('expr', str(i))
419 if self.wantobjects:
420 self.assertEqual(result, i)
421 self.assertIsInstance(result, int)
422 else:
423 self.assertEqual(result, str(i))
424 self.assertIsInstance(result, str)
425 if tcl_version < (8, 5): # bignum was added in Tcl 8.5
Serhiy Storchaka2379d542015-04-02 20:07:09 +0300426 self.assertRaises(TclError, tcl.call, 'expr', str(2**1000))
Serhiy Storchakaea134da2015-04-02 18:46:50 +0300427
Serhiy Storchakadf4bb462013-02-07 15:40:03 +0200428 def test_passing_values(self):
429 def passValue(value):
430 return self.interp.call('set', '_', value)
431
Serhiy Storchakacc4290b2013-12-25 17:29:01 +0200432 self.assertEqual(passValue(True), True if self.wantobjects else '1')
433 self.assertEqual(passValue(False), False if self.wantobjects else '0')
Serhiy Storchakadf4bb462013-02-07 15:40:03 +0200434 self.assertEqual(passValue('string'), 'string')
435 self.assertEqual(passValue('string\u20ac'), 'string\u20ac')
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 Storchaka74596a82014-07-30 18:33:13 +0300439 self.assertEqual(passValue(b'str\x00ing'),
440 b'str\x00ing' if self.wantobjects else 'str\x00ing')
441 self.assertEqual(passValue(b'str\xc0\x80ing'),
442 b'str\xc0\x80ing' if self.wantobjects else 'str\xc0\x80ing')
443 self.assertEqual(passValue(b'str\xbding'),
444 b'str\xbding' if self.wantobjects else 'str\xbding')
Serhiy Storchakaea134da2015-04-02 18:46:50 +0300445 for i in self.get_integers():
Serhiy Storchakacc4290b2013-12-25 17:29:01 +0200446 self.assertEqual(passValue(i), i if self.wantobjects else str(i))
Serhiy Storchakaea134da2015-04-02 18:46:50 +0300447 if tcl_version < (8, 5): # bignum was added in Tcl 8.5
448 self.assertEqual(passValue(2**1000), str(2**1000))
Serhiy Storchakadf4bb462013-02-07 15:40:03 +0200449 for f in (0.0, 1.0, -1.0, 1/3,
450 sys.float_info.min, sys.float_info.max,
451 -sys.float_info.min, -sys.float_info.max):
Serhiy Storchakacc4290b2013-12-25 17:29:01 +0200452 if self.wantobjects:
Serhiy Storchakadf4bb462013-02-07 15:40:03 +0200453 self.assertEqual(passValue(f), f)
Serhiy Storchakacc4290b2013-12-25 17:29:01 +0200454 else:
455 self.assertEqual(float(passValue(f)), f)
456 if self.wantobjects:
457 f = passValue(float('nan'))
458 self.assertNotEqual(f, f)
459 self.assertEqual(passValue(float('inf')), float('inf'))
460 self.assertEqual(passValue(-float('inf')), -float('inf'))
461 else:
Serhiy Storchakacc4290b2013-12-25 17:29:01 +0200462 self.assertEqual(float(passValue(float('inf'))), float('inf'))
463 self.assertEqual(float(passValue(-float('inf'))), -float('inf'))
Serhiy Storchaka6f1435c2014-07-07 14:57:08 +0300464 # XXX NaN representation can be not parsable by float()
Serhiy Storchakacc4290b2013-12-25 17:29:01 +0200465 self.assertEqual(passValue((1, '2', (3.4,))),
466 (1, '2', (3.4,)) if self.wantobjects else '1 2 3.4')
Martin v. Löwis2d5157e2010-06-04 19:50:26 +0000467
Serhiy Storchaka4b730162014-01-23 09:44:05 +0200468 def test_user_command(self):
469 result = None
470 def testfunc(arg):
471 nonlocal result
472 result = arg
473 return arg
474 self.interp.createcommand('testfunc', testfunc)
Antoine Pitrou220cc212014-02-23 19:39:06 +0100475 self.addCleanup(self.interp.tk.deletecommand, 'testfunc')
Serhiy Storchakad6ec3092014-08-18 17:47:29 +0300476 def check(value, expected=None, *, eq=self.assertEqual):
477 if expected is None:
478 expected = value
479 nonlocal result
480 result = None
Serhiy Storchakabdf0cb52014-01-23 16:48:44 +0200481 r = self.interp.call('testfunc', value)
482 self.assertIsInstance(result, str)
483 eq(result, expected)
484 self.assertIsInstance(r, str)
485 eq(r, expected)
486 def float_eq(actual, expected):
Serhiy Storchakabdf0cb52014-01-23 16:48:44 +0200487 self.assertAlmostEqual(float(actual), expected,
488 delta=abs(expected) * 1e-10)
Serhiy Storchaka4b730162014-01-23 09:44:05 +0200489
490 check(True, '1')
491 check(False, '0')
Serhiy Storchakad6ec3092014-08-18 17:47:29 +0300492 check('string')
493 check('string\xbd')
494 check('string\u20ac')
Serhiy Storchakaabf68ce2014-09-11 10:57:13 +0300495 check('')
Serhiy Storchaka1317e142014-02-03 21:24:07 +0200496 check(b'string', 'string')
Serhiy Storchaka74596a82014-07-30 18:33:13 +0300497 check(b'string\xe2\x82\xac', 'string\xe2\x82\xac')
498 check(b'string\xbd', 'string\xbd')
Serhiy Storchakaabf68ce2014-09-11 10:57:13 +0300499 check(b'', '')
Serhiy Storchakad6ec3092014-08-18 17:47:29 +0300500 check('str\x00ing')
501 check('str\x00ing\xbd')
502 check('str\x00ing\u20ac')
Serhiy Storchaka74596a82014-07-30 18:33:13 +0300503 check(b'str\x00ing', 'str\x00ing')
504 check(b'str\xc0\x80ing', 'str\xc0\x80ing')
505 check(b'str\xc0\x80ing\xe2\x82\xac', 'str\xc0\x80ing\xe2\x82\xac')
Serhiy Storchakaea134da2015-04-02 18:46:50 +0300506 for i in self.get_integers():
Serhiy Storchaka4b730162014-01-23 09:44:05 +0200507 check(i, str(i))
Serhiy Storchakaea134da2015-04-02 18:46:50 +0300508 if tcl_version < (8, 5): # bignum was added in Tcl 8.5
509 check(2**1000, str(2**1000))
Serhiy Storchakabdf0cb52014-01-23 16:48:44 +0200510 for f in (0.0, 1.0, -1.0):
511 check(f, repr(f))
512 for f in (1/3.0, sys.float_info.min, sys.float_info.max,
Serhiy Storchaka4b730162014-01-23 09:44:05 +0200513 -sys.float_info.min, -sys.float_info.max):
Serhiy Storchakad6ec3092014-08-18 17:47:29 +0300514 check(f, eq=float_eq)
515 check(float('inf'), eq=float_eq)
516 check(-float('inf'), eq=float_eq)
Serhiy Storchaka6f1435c2014-07-07 14:57:08 +0300517 # XXX NaN representation can be not parsable by float()
Serhiy Storchaka4b730162014-01-23 09:44:05 +0200518 check((), '')
519 check((1, (2,), (3, 4), '5 6', ()), '1 2 {3 4} {5 6} {}')
520
Serhiy Storchaka275d5fd2013-07-11 20:34:47 +0300521 def test_splitlist(self):
522 splitlist = self.interp.tk.splitlist
523 call = self.interp.tk.call
524 self.assertRaises(TypeError, splitlist)
525 self.assertRaises(TypeError, splitlist, 'a', 'b')
526 self.assertRaises(TypeError, splitlist, 2)
527 testcases = [
528 ('2', ('2',)),
529 ('', ()),
530 ('{}', ('',)),
531 ('""', ('',)),
532 ('a\n b\t\r c\n ', ('a', 'b', 'c')),
533 (b'a\n b\t\r c\n ', ('a', 'b', 'c')),
534 ('a \u20ac', ('a', '\u20ac')),
535 (b'a \xe2\x82\xac', ('a', '\u20ac')),
Serhiy Storchaka1317e142014-02-03 21:24:07 +0200536 (b'a\xc0\x80b c\xc0\x80d', ('a\x00b', 'c\x00d')),
Serhiy Storchaka275d5fd2013-07-11 20:34:47 +0300537 ('a {b c}', ('a', 'b c')),
538 (r'a b\ c', ('a', 'b c')),
539 (('a', 'b c'), ('a', 'b c')),
540 ('a 2', ('a', '2')),
541 (('a', 2), ('a', 2)),
542 ('a 3.4', ('a', '3.4')),
543 (('a', 3.4), ('a', 3.4)),
544 ((), ()),
Serhiy Storchakacc4290b2013-12-25 17:29:01 +0200545 (call('list', 1, '2', (3.4,)),
546 (1, '2', (3.4,)) if self.wantobjects else
547 ('1', '2', '3.4')),
Serhiy Storchaka275d5fd2013-07-11 20:34:47 +0300548 ]
Serhiy Storchakadfa689b2013-09-08 20:29:37 +0300549 if tcl_version >= (8, 5):
Serhiy Storchaka92af06b2014-02-02 23:04:24 +0200550 if not self.wantobjects or get_tk_patchlevel() < (8, 5, 5):
551 # Before 8.5.5 dicts were converted to lists through string
Serhiy Storchaka74596a82014-07-30 18:33:13 +0300552 expected = ('12', '\u20ac', '\xe2\x82\xac', '3.4')
Serhiy Storchaka92af06b2014-02-02 23:04:24 +0200553 else:
Serhiy Storchaka74596a82014-07-30 18:33:13 +0300554 expected = (12, '\u20ac', b'\xe2\x82\xac', (3.4,))
Serhiy Storchakadfa689b2013-09-08 20:29:37 +0300555 testcases += [
Serhiy Storchaka92af06b2014-02-02 23:04:24 +0200556 (call('dict', 'create', 12, '\u20ac', b'\xe2\x82\xac', (3.4,)),
557 expected),
Serhiy Storchakadfa689b2013-09-08 20:29:37 +0300558 ]
Serhiy Storchaka275d5fd2013-07-11 20:34:47 +0300559 for arg, res in testcases:
560 self.assertEqual(splitlist(arg), res, msg=arg)
561 self.assertRaises(TclError, splitlist, '{')
562
563 def test_split(self):
564 split = self.interp.tk.split
565 call = self.interp.tk.call
566 self.assertRaises(TypeError, split)
567 self.assertRaises(TypeError, split, 'a', 'b')
568 self.assertRaises(TypeError, split, 2)
569 testcases = [
570 ('2', '2'),
571 ('', ''),
572 ('{}', ''),
573 ('""', ''),
574 ('{', '{'),
575 ('a\n b\t\r c\n ', ('a', 'b', 'c')),
576 (b'a\n b\t\r c\n ', ('a', 'b', 'c')),
577 ('a \u20ac', ('a', '\u20ac')),
578 (b'a \xe2\x82\xac', ('a', '\u20ac')),
Serhiy Storchaka1317e142014-02-03 21:24:07 +0200579 (b'a\xc0\x80b', 'a\x00b'),
580 (b'a\xc0\x80b c\xc0\x80d', ('a\x00b', 'c\x00d')),
581 (b'{a\xc0\x80b c\xc0\x80d', '{a\x00b c\x00d'),
Serhiy Storchaka275d5fd2013-07-11 20:34:47 +0300582 ('a {b c}', ('a', ('b', 'c'))),
583 (r'a b\ c', ('a', ('b', 'c'))),
584 (('a', b'b c'), ('a', ('b', 'c'))),
585 (('a', 'b c'), ('a', ('b', 'c'))),
586 ('a 2', ('a', '2')),
587 (('a', 2), ('a', 2)),
588 ('a 3.4', ('a', '3.4')),
589 (('a', 3.4), ('a', 3.4)),
590 (('a', (2, 3.4)), ('a', (2, 3.4))),
591 ((), ()),
Serhiy Storchakacc4290b2013-12-25 17:29:01 +0200592 (call('list', 1, '2', (3.4,)),
593 (1, '2', (3.4,)) if self.wantobjects else
594 ('1', '2', '3.4')),
Serhiy Storchaka275d5fd2013-07-11 20:34:47 +0300595 ]
Serhiy Storchakadfa689b2013-09-08 20:29:37 +0300596 if tcl_version >= (8, 5):
Serhiy Storchaka92af06b2014-02-02 23:04:24 +0200597 if not self.wantobjects or get_tk_patchlevel() < (8, 5, 5):
598 # Before 8.5.5 dicts were converted to lists through string
Serhiy Storchaka74596a82014-07-30 18:33:13 +0300599 expected = ('12', '\u20ac', '\xe2\x82\xac', '3.4')
Serhiy Storchaka92af06b2014-02-02 23:04:24 +0200600 else:
Serhiy Storchaka74596a82014-07-30 18:33:13 +0300601 expected = (12, '\u20ac', b'\xe2\x82\xac', (3.4,))
Serhiy Storchakadfa689b2013-09-08 20:29:37 +0300602 testcases += [
603 (call('dict', 'create', 12, '\u20ac', b'\xe2\x82\xac', (3.4,)),
Serhiy Storchaka92af06b2014-02-02 23:04:24 +0200604 expected),
Serhiy Storchakadfa689b2013-09-08 20:29:37 +0300605 ]
Serhiy Storchaka275d5fd2013-07-11 20:34:47 +0300606 for arg, res in testcases:
607 self.assertEqual(split(arg), res, msg=arg)
608
Serhiy Storchaka8f0a1d02014-09-06 22:47:58 +0300609 def test_splitdict(self):
610 splitdict = tkinter._splitdict
611 tcl = self.interp.tk
612
613 arg = '-a {1 2 3} -something foo status {}'
614 self.assertEqual(splitdict(tcl, arg, False),
615 {'-a': '1 2 3', '-something': 'foo', 'status': ''})
616 self.assertEqual(splitdict(tcl, arg),
617 {'a': '1 2 3', 'something': 'foo', 'status': ''})
618
619 arg = ('-a', (1, 2, 3), '-something', 'foo', 'status', '{}')
620 self.assertEqual(splitdict(tcl, arg, False),
621 {'-a': (1, 2, 3), '-something': 'foo', 'status': '{}'})
622 self.assertEqual(splitdict(tcl, arg),
623 {'a': (1, 2, 3), 'something': 'foo', 'status': '{}'})
624
625 self.assertRaises(RuntimeError, splitdict, tcl, '-a b -c ')
626 self.assertRaises(RuntimeError, splitdict, tcl, ('-a', 'b', '-c'))
627
628 arg = tcl.call('list',
629 '-a', (1, 2, 3), '-something', 'foo', 'status', ())
630 self.assertEqual(splitdict(tcl, arg),
631 {'a': (1, 2, 3) if self.wantobjects else '1 2 3',
632 'something': 'foo', 'status': ''})
633
634 if tcl_version >= (8, 5):
635 arg = tcl.call('dict', 'create',
636 '-a', (1, 2, 3), '-something', 'foo', 'status', ())
637 if not self.wantobjects or get_tk_patchlevel() < (8, 5, 5):
638 # Before 8.5.5 dicts were converted to lists through string
639 expected = {'a': '1 2 3', 'something': 'foo', 'status': ''}
640 else:
641 expected = {'a': (1, 2, 3), 'something': 'foo', 'status': ''}
642 self.assertEqual(splitdict(tcl, arg), expected)
643
Neal Norwitz63dfece2004-02-19 02:37:29 +0000644
Serhiy Storchaka9e6b9752013-08-21 21:38:21 +0300645class BigmemTclTest(unittest.TestCase):
646
647 def setUp(self):
648 self.interp = Tcl()
649
Serhiy Storchaka5cfc79d2014-02-07 10:06:39 +0200650 @support.cpython_only
651 @unittest.skipUnless(INT_MAX < PY_SSIZE_T_MAX, "needs UINT_MAX < SIZE_MAX")
652 @support.bigmemtest(size=INT_MAX + 1, memuse=5, dry_run=False)
Serhiy Storchaka79851d72014-05-30 14:24:03 +0300653 def test_huge_string_call(self, size):
Serhiy Storchaka9e6b9752013-08-21 21:38:21 +0300654 value = ' ' * size
655 self.assertRaises(OverflowError, self.interp.call, 'set', '_', value)
656
Serhiy Storchaka79851d72014-05-30 14:24:03 +0300657 @support.cpython_only
658 @unittest.skipUnless(INT_MAX < PY_SSIZE_T_MAX, "needs UINT_MAX < SIZE_MAX")
659 @support.bigmemtest(size=INT_MAX + 1, memuse=9, dry_run=False)
660 def test_huge_string_builtins(self, size):
661 value = '1' + ' ' * size
Serhiy Storchakaaecfa9e2014-05-30 15:54:35 +0300662 self.assertRaises(OverflowError, self.interp.tk.getint, value)
663 self.assertRaises(OverflowError, self.interp.tk.getdouble, value)
664 self.assertRaises(OverflowError, self.interp.tk.getboolean, value)
Serhiy Storchaka79851d72014-05-30 14:24:03 +0300665 self.assertRaises(OverflowError, self.interp.eval, value)
666 self.assertRaises(OverflowError, self.interp.evalfile, value)
667 self.assertRaises(OverflowError, self.interp.record, value)
668 self.assertRaises(OverflowError, self.interp.adderrorinfo, value)
669 self.assertRaises(OverflowError, self.interp.setvar, value, 'x', 'a')
670 self.assertRaises(OverflowError, self.interp.setvar, 'x', value, 'a')
671 self.assertRaises(OverflowError, self.interp.unsetvar, value)
672 self.assertRaises(OverflowError, self.interp.unsetvar, 'x', value)
673 self.assertRaises(OverflowError, self.interp.adderrorinfo, value)
674 self.assertRaises(OverflowError, self.interp.exprstring, value)
675 self.assertRaises(OverflowError, self.interp.exprlong, value)
676 self.assertRaises(OverflowError, self.interp.exprboolean, value)
677 self.assertRaises(OverflowError, self.interp.splitlist, value)
678 self.assertRaises(OverflowError, self.interp.split, value)
679 self.assertRaises(OverflowError, self.interp.createcommand, value, max)
680 self.assertRaises(OverflowError, self.interp.deletecommand, value)
681
Serhiy Storchaka9e6b9752013-08-21 21:38:21 +0300682
Serhiy Storchaka8db18232013-11-20 17:43:49 +0200683def setUpModule():
684 if support.verbose:
685 tcl = Tcl()
686 print('patchlevel =', tcl.call('info', 'patchlevel'))
687
688
Neal Norwitz63dfece2004-02-19 02:37:29 +0000689def test_main():
Serhiy Storchaka9e6b9752013-08-21 21:38:21 +0300690 support.run_unittest(TclTest, TkinterTest, BigmemTclTest)
Neal Norwitz63dfece2004-02-19 02:37:29 +0000691
David Aschere2b4b322004-02-18 05:59:53 +0000692if __name__ == "__main__":
Neal Norwitz63dfece2004-02-19 02:37:29 +0000693 test_main()