blob: b6565631b7f011d89a9656efadf04a8f549a5aad [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
Benjamin Petersonee8712c2008-05-20 21:35:26 +00006from test import support
R. David Murraya21e4ca2009-03-31 23:16:50 +00007
8# Skip this test if the _tkinter module wasn't built.
9_tkinter = support.import_module('_tkinter')
10
Terry Jan Reedy743c85a2013-03-16 02:37:06 -040011# Make sure tkinter._fix runs to set up the environment
Serhiy Storchaka8f0a1d02014-09-06 22:47:58 +030012tkinter = support.import_fresh_module('tkinter')
Terry Jan Reedy743c85a2013-03-16 02:37:06 -040013
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):
134 integers = (0, 1, -1, 2**31-1, -2**31)
135 if tcl_version >= (8, 4): # wideInt was added in Tcl 8.4
136 integers += (2**31, -2**31-1, 2**63-1, -2**63)
Serhiy Storchaka3af7a382015-04-22 10:53:08 +0300137 # bignum was added in Tcl 8.5, but its support is able only since 8.5.8
138 if (get_tk_patchlevel() >= (8, 6, 0, 'final') or
139 (8, 5, 8) <= get_tk_patchlevel() < (8, 6)):
Serhiy Storchakaea134da2015-04-02 18:46:50 +0300140 integers += (2**63, -2**63-1, 2**1000, -2**1000)
141 return integers
142
Serhiy Storchaka9f1f4f42014-05-30 14:07:38 +0300143 def test_getint(self):
144 tcl = self.interp.tk
Serhiy Storchakaea134da2015-04-02 18:46:50 +0300145 for i in self.get_integers():
146 self.assertEqual(tcl.getint(' %d ' % i), i)
Serhiy Storchaka2379d542015-04-02 20:07:09 +0300147 if tcl_version >= (8, 5):
148 self.assertEqual(tcl.getint(' %#o ' % i), i)
149 self.assertEqual(tcl.getint((' %#o ' % i).replace('o', '')), i)
Serhiy Storchakaea134da2015-04-02 18:46:50 +0300150 self.assertEqual(tcl.getint(' %#x ' % i), i)
151 if tcl_version < (8, 5): # bignum was added in Tcl 8.5
152 self.assertRaises(TclError, tcl.getint, str(2**1000))
Serhiy Storchaka9f1f4f42014-05-30 14:07:38 +0300153 self.assertEqual(tcl.getint(42), 42)
154 self.assertRaises(TypeError, tcl.getint)
155 self.assertRaises(TypeError, tcl.getint, '42', '10')
156 self.assertRaises(TypeError, tcl.getint, b'42')
157 self.assertRaises(TypeError, tcl.getint, 42.0)
158 self.assertRaises(TclError, tcl.getint, 'a')
159 self.assertRaises((TypeError, ValueError, TclError),
160 tcl.getint, '42\0')
161 self.assertRaises((UnicodeEncodeError, ValueError, TclError),
162 tcl.getint, '42\ud800')
163
164 def test_getdouble(self):
165 tcl = self.interp.tk
166 self.assertEqual(tcl.getdouble(' 42 '), 42.0)
167 self.assertEqual(tcl.getdouble(' 42.5 '), 42.5)
168 self.assertEqual(tcl.getdouble(42.5), 42.5)
169 self.assertRaises(TypeError, tcl.getdouble)
170 self.assertRaises(TypeError, tcl.getdouble, '42.5', '10')
171 self.assertRaises(TypeError, tcl.getdouble, b'42.5')
172 self.assertRaises(TypeError, tcl.getdouble, 42)
173 self.assertRaises(TclError, tcl.getdouble, 'a')
174 self.assertRaises((TypeError, ValueError, TclError),
175 tcl.getdouble, '42.5\0')
176 self.assertRaises((UnicodeEncodeError, ValueError, TclError),
177 tcl.getdouble, '42.5\ud800')
178
179 def test_getboolean(self):
180 tcl = self.interp.tk
181 self.assertIs(tcl.getboolean('on'), True)
182 self.assertIs(tcl.getboolean('1'), True)
Serhiy Storchaka9a6e2012015-04-04 12:43:01 +0300183 self.assertIs(tcl.getboolean(42), True)
184 self.assertIs(tcl.getboolean(0), False)
Serhiy Storchaka9f1f4f42014-05-30 14:07:38 +0300185 self.assertRaises(TypeError, tcl.getboolean)
186 self.assertRaises(TypeError, tcl.getboolean, 'on', '1')
187 self.assertRaises(TypeError, tcl.getboolean, b'on')
188 self.assertRaises(TypeError, tcl.getboolean, 1.0)
189 self.assertRaises(TclError, tcl.getboolean, 'a')
190 self.assertRaises((TypeError, ValueError, TclError),
191 tcl.getboolean, 'on\0')
192 self.assertRaises((UnicodeEncodeError, ValueError, TclError),
193 tcl.getboolean, 'on\ud800')
194
David Aschere2b4b322004-02-18 05:59:53 +0000195 def testEvalFile(self):
196 tcl = self.interp
Serhiy Storchaka1317e142014-02-03 21:24:07 +0200197 with open(support.TESTFN, 'w') as f:
198 self.addCleanup(support.unlink, support.TESTFN)
199 f.write("""set a 1
200 set b 2
201 set c [ expr $a + $b ]
202 """)
203 tcl.evalfile(support.TESTFN)
David Aschere2b4b322004-02-18 05:59:53 +0000204 self.assertEqual(tcl.eval('set a'),'1')
205 self.assertEqual(tcl.eval('set b'),'2')
206 self.assertEqual(tcl.eval('set c'),'3')
207
Serhiy Storchaka1317e142014-02-03 21:24:07 +0200208 def test_evalfile_null_in_result(self):
209 tcl = self.interp
210 with open(support.TESTFN, 'w') as f:
211 self.addCleanup(support.unlink, support.TESTFN)
212 f.write("""
213 set a "a\0b"
214 set b "a\\0b"
215 """)
216 tcl.evalfile(support.TESTFN)
217 self.assertEqual(tcl.eval('set a'), 'a\x00b')
218 self.assertEqual(tcl.eval('set b'), 'a\x00b')
219
David Aschere2b4b322004-02-18 05:59:53 +0000220 def testEvalFileException(self):
221 tcl = self.interp
222 filename = "doesnotexists"
223 try:
224 os.remove(filename)
Guido van Rossumb940e112007-01-10 16:19:56 +0000225 except Exception as e:
David Aschere2b4b322004-02-18 05:59:53 +0000226 pass
227 self.assertRaises(TclError,tcl.evalfile,filename)
228
David Aschere2b4b322004-02-18 05:59:53 +0000229 def testPackageRequireException(self):
230 tcl = self.interp
231 self.assertRaises(TclError,tcl.eval,'package require DNE')
232
Hirokazu Yamamotodda7fdf2010-09-23 15:28:35 +0000233 @unittest.skipUnless(sys.platform == 'win32', 'Requires Windows')
Martin v. Löwis2d5157e2010-06-04 19:50:26 +0000234 def testLoadWithUNC(self):
Martin v. Löwis2d5157e2010-06-04 19:50:26 +0000235 # Build a UNC path from the regular path.
236 # Something like
237 # \\%COMPUTERNAME%\c$\python27\python.exe
238
239 fullname = os.path.abspath(sys.executable)
240 if fullname[1] != ':':
Hirokazu Yamamotodda7fdf2010-09-23 15:28:35 +0000241 raise unittest.SkipTest('Absolute path should have drive part')
Martin v. Löwis2d5157e2010-06-04 19:50:26 +0000242 unc_name = r'\\%s\%s$\%s' % (os.environ['COMPUTERNAME'],
243 fullname[0],
244 fullname[3:])
Hirokazu Yamamotodda7fdf2010-09-23 15:28:35 +0000245 if not os.path.exists(unc_name):
246 raise unittest.SkipTest('Cannot connect to UNC Path')
Martin v. Löwis2d5157e2010-06-04 19:50:26 +0000247
Georg Brandlec5ae3b2010-07-31 19:17:11 +0000248 with support.EnvironmentVarGuard() as env:
Martin v. Löwis2d5157e2010-06-04 19:50:26 +0000249 env.unset("TCL_LIBRARY")
Zachary Ware83fd0a82015-10-12 23:27:58 -0500250 stdout = subprocess.check_output(
251 [unc_name, '-c', 'import tkinter; print(tkinter)'])
Martin v. Löwis2d5157e2010-06-04 19:50:26 +0000252
Zachary Ware83fd0a82015-10-12 23:27:58 -0500253 self.assertIn(b'tkinter', stdout)
Martin v. Löwis2d5157e2010-06-04 19:50:26 +0000254
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()