blob: 80f1668bcecab876ca2b84821f77f1edc6afcdb8 [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
Zachary Ware7dc9dea2015-05-22 11:36:53 -050011import tkinter
Guilherme Polofa8fba92009-02-07 02:33:47 +000012from tkinter import Tcl
David Aschere2b4b322004-02-18 05:59:53 +000013from _tkinter import TclError
14
Serhiy Storchaka5cfc79d2014-02-07 10:06:39 +020015try:
16 from _testcapi import INT_MAX, PY_SSIZE_T_MAX
17except ImportError:
18 INT_MAX = PY_SSIZE_T_MAX = sys.maxsize
19
Serhiy Storchaka462c3572015-04-22 08:36:03 +030020tcl_version = tuple(map(int, _tkinter.TCL_VERSION.split('.')))
Serhiy Storchakadfa689b2013-09-08 20:29:37 +030021
Serhiy Storchaka92af06b2014-02-02 23:04:24 +020022_tk_patchlevel = None
23def get_tk_patchlevel():
24 global _tk_patchlevel
25 if _tk_patchlevel is None:
26 tcl = Tcl()
Serhiy Storchaka462c3572015-04-22 08:36:03 +030027 patchlevel = tcl.call('info', 'patchlevel')
28 m = re.fullmatch(r'(\d+)\.(\d+)([ab.])(\d+)', patchlevel)
29 major, minor, releaselevel, serial = m.groups()
30 major, minor, serial = int(major), int(minor), int(serial)
31 releaselevel = {'a': 'alpha', 'b': 'beta', '.': 'final'}[releaselevel]
32 if releaselevel == 'final':
33 _tk_patchlevel = major, minor, serial, releaselevel, 0
34 else:
35 _tk_patchlevel = major, minor, 0, releaselevel, serial
Serhiy Storchaka92af06b2014-02-02 23:04:24 +020036 return _tk_patchlevel
37
Benjamin Petersonc4bbc8d2009-01-30 03:39:35 +000038
39class TkinterTest(unittest.TestCase):
40
41 def testFlattenLen(self):
42 # flatten(<object with no length>)
43 self.assertRaises(TypeError, _tkinter._flatten, True)
44
45
David Aschere2b4b322004-02-18 05:59:53 +000046class TclTest(unittest.TestCase):
47
48 def setUp(self):
49 self.interp = Tcl()
Serhiy Storchakacc4290b2013-12-25 17:29:01 +020050 self.wantobjects = self.interp.tk.wantobjects()
David Aschere2b4b322004-02-18 05:59:53 +000051
52 def testEval(self):
53 tcl = self.interp
54 tcl.eval('set a 1')
55 self.assertEqual(tcl.eval('set a'),'1')
56
Serhiy Storchaka1317e142014-02-03 21:24:07 +020057 def test_eval_null_in_result(self):
58 tcl = self.interp
59 self.assertEqual(tcl.eval('set a "a\\0b"'), 'a\x00b')
60
David Aschere2b4b322004-02-18 05:59:53 +000061 def testEvalException(self):
62 tcl = self.interp
63 self.assertRaises(TclError,tcl.eval,'set a')
64
65 def testEvalException2(self):
66 tcl = self.interp
67 self.assertRaises(TclError,tcl.eval,'this is wrong')
68
69 def testCall(self):
70 tcl = self.interp
71 tcl.call('set','a','1')
72 self.assertEqual(tcl.call('set','a'),'1')
73
74 def testCallException(self):
75 tcl = self.interp
76 self.assertRaises(TclError,tcl.call,'set','a')
77
78 def testCallException2(self):
79 tcl = self.interp
80 self.assertRaises(TclError,tcl.call,'this','is','wrong')
81
82 def testSetVar(self):
83 tcl = self.interp
84 tcl.setvar('a','1')
85 self.assertEqual(tcl.eval('set a'),'1')
86
87 def testSetVarArray(self):
88 tcl = self.interp
89 tcl.setvar('a(1)','1')
90 self.assertEqual(tcl.eval('set a(1)'),'1')
91
92 def testGetVar(self):
93 tcl = self.interp
94 tcl.eval('set a 1')
95 self.assertEqual(tcl.getvar('a'),'1')
96
97 def testGetVarArray(self):
98 tcl = self.interp
99 tcl.eval('set a(1) 1')
100 self.assertEqual(tcl.getvar('a(1)'),'1')
101
102 def testGetVarException(self):
103 tcl = self.interp
104 self.assertRaises(TclError,tcl.getvar,'a')
105
106 def testGetVarArrayException(self):
107 tcl = self.interp
108 self.assertRaises(TclError,tcl.getvar,'a(1)')
109
110 def testUnsetVar(self):
111 tcl = self.interp
112 tcl.setvar('a',1)
113 self.assertEqual(tcl.eval('info exists a'),'1')
114 tcl.unsetvar('a')
115 self.assertEqual(tcl.eval('info exists a'),'0')
116
117 def testUnsetVarArray(self):
118 tcl = self.interp
119 tcl.setvar('a(1)',1)
120 tcl.setvar('a(2)',2)
121 self.assertEqual(tcl.eval('info exists a(1)'),'1')
122 self.assertEqual(tcl.eval('info exists a(2)'),'1')
123 tcl.unsetvar('a(1)')
124 self.assertEqual(tcl.eval('info exists a(1)'),'0')
125 self.assertEqual(tcl.eval('info exists a(2)'),'1')
126
127 def testUnsetVarException(self):
128 tcl = self.interp
129 self.assertRaises(TclError,tcl.unsetvar,'a')
Tim Peters27f88362004-07-08 04:22:35 +0000130
Serhiy Storchakaea134da2015-04-02 18:46:50 +0300131 def get_integers(self):
Serhiy Storchaka4c7dc482015-04-02 18:49:14 +0300132 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 +0300133 # bignum was added in Tcl 8.5, but its support is able only since 8.5.8
134 if (get_tk_patchlevel() >= (8, 6, 0, 'final') or
135 (8, 5, 8) <= get_tk_patchlevel() < (8, 6)):
Serhiy Storchakaea134da2015-04-02 18:46:50 +0300136 integers += (2**63, -2**63-1, 2**1000, -2**1000)
137 return integers
138
Serhiy Storchaka9f1f4f42014-05-30 14:07:38 +0300139 def test_getint(self):
140 tcl = self.interp.tk
Serhiy Storchakaea134da2015-04-02 18:46:50 +0300141 for i in self.get_integers():
142 self.assertEqual(tcl.getint(' %d ' % i), i)
Serhiy Storchaka2379d542015-04-02 20:07:09 +0300143 if tcl_version >= (8, 5):
144 self.assertEqual(tcl.getint(' %#o ' % i), i)
145 self.assertEqual(tcl.getint((' %#o ' % i).replace('o', '')), i)
Serhiy Storchakaea134da2015-04-02 18:46:50 +0300146 self.assertEqual(tcl.getint(' %#x ' % i), i)
147 if tcl_version < (8, 5): # bignum was added in Tcl 8.5
148 self.assertRaises(TclError, tcl.getint, str(2**1000))
Serhiy Storchaka9f1f4f42014-05-30 14:07:38 +0300149 self.assertEqual(tcl.getint(42), 42)
150 self.assertRaises(TypeError, tcl.getint)
151 self.assertRaises(TypeError, tcl.getint, '42', '10')
152 self.assertRaises(TypeError, tcl.getint, b'42')
153 self.assertRaises(TypeError, tcl.getint, 42.0)
154 self.assertRaises(TclError, tcl.getint, 'a')
155 self.assertRaises((TypeError, ValueError, TclError),
156 tcl.getint, '42\0')
157 self.assertRaises((UnicodeEncodeError, ValueError, TclError),
158 tcl.getint, '42\ud800')
159
160 def test_getdouble(self):
161 tcl = self.interp.tk
162 self.assertEqual(tcl.getdouble(' 42 '), 42.0)
163 self.assertEqual(tcl.getdouble(' 42.5 '), 42.5)
164 self.assertEqual(tcl.getdouble(42.5), 42.5)
Serhiy Storchaka645058d2015-05-06 14:00:04 +0300165 self.assertEqual(tcl.getdouble(42), 42.0)
Serhiy Storchaka9f1f4f42014-05-30 14:07:38 +0300166 self.assertRaises(TypeError, tcl.getdouble)
167 self.assertRaises(TypeError, tcl.getdouble, '42.5', '10')
168 self.assertRaises(TypeError, tcl.getdouble, b'42.5')
Serhiy Storchaka9f1f4f42014-05-30 14:07:38 +0300169 self.assertRaises(TclError, tcl.getdouble, 'a')
170 self.assertRaises((TypeError, ValueError, TclError),
171 tcl.getdouble, '42.5\0')
172 self.assertRaises((UnicodeEncodeError, ValueError, TclError),
173 tcl.getdouble, '42.5\ud800')
174
175 def test_getboolean(self):
176 tcl = self.interp.tk
177 self.assertIs(tcl.getboolean('on'), True)
178 self.assertIs(tcl.getboolean('1'), True)
Serhiy Storchaka9a6e2012015-04-04 12:43:01 +0300179 self.assertIs(tcl.getboolean(42), True)
180 self.assertIs(tcl.getboolean(0), False)
Serhiy Storchaka9f1f4f42014-05-30 14:07:38 +0300181 self.assertRaises(TypeError, tcl.getboolean)
182 self.assertRaises(TypeError, tcl.getboolean, 'on', '1')
183 self.assertRaises(TypeError, tcl.getboolean, b'on')
184 self.assertRaises(TypeError, tcl.getboolean, 1.0)
185 self.assertRaises(TclError, tcl.getboolean, 'a')
186 self.assertRaises((TypeError, ValueError, TclError),
187 tcl.getboolean, 'on\0')
188 self.assertRaises((UnicodeEncodeError, ValueError, TclError),
189 tcl.getboolean, 'on\ud800')
190
David Aschere2b4b322004-02-18 05:59:53 +0000191 def testEvalFile(self):
192 tcl = self.interp
Serhiy Storchaka1317e142014-02-03 21:24:07 +0200193 with open(support.TESTFN, 'w') as f:
194 self.addCleanup(support.unlink, support.TESTFN)
195 f.write("""set a 1
196 set b 2
197 set c [ expr $a + $b ]
198 """)
199 tcl.evalfile(support.TESTFN)
David Aschere2b4b322004-02-18 05:59:53 +0000200 self.assertEqual(tcl.eval('set a'),'1')
201 self.assertEqual(tcl.eval('set b'),'2')
202 self.assertEqual(tcl.eval('set c'),'3')
203
Serhiy Storchaka1317e142014-02-03 21:24:07 +0200204 def test_evalfile_null_in_result(self):
205 tcl = self.interp
206 with open(support.TESTFN, 'w') as f:
207 self.addCleanup(support.unlink, support.TESTFN)
208 f.write("""
209 set a "a\0b"
210 set b "a\\0b"
211 """)
212 tcl.evalfile(support.TESTFN)
213 self.assertEqual(tcl.eval('set a'), 'a\x00b')
214 self.assertEqual(tcl.eval('set b'), 'a\x00b')
215
David Aschere2b4b322004-02-18 05:59:53 +0000216 def testEvalFileException(self):
217 tcl = self.interp
218 filename = "doesnotexists"
219 try:
220 os.remove(filename)
Guido van Rossumb940e112007-01-10 16:19:56 +0000221 except Exception as e:
David Aschere2b4b322004-02-18 05:59:53 +0000222 pass
223 self.assertRaises(TclError,tcl.evalfile,filename)
224
David Aschere2b4b322004-02-18 05:59:53 +0000225 def testPackageRequireException(self):
226 tcl = self.interp
227 self.assertRaises(TclError,tcl.eval,'package require DNE')
228
Hirokazu Yamamotodda7fdf2010-09-23 15:28:35 +0000229 @unittest.skipUnless(sys.platform == 'win32', 'Requires Windows')
Martin v. Löwis2d5157e2010-06-04 19:50:26 +0000230 def testLoadWithUNC(self):
Martin v. Löwis2d5157e2010-06-04 19:50:26 +0000231 # Build a UNC path from the regular path.
232 # Something like
233 # \\%COMPUTERNAME%\c$\python27\python.exe
234
235 fullname = os.path.abspath(sys.executable)
236 if fullname[1] != ':':
Hirokazu Yamamotodda7fdf2010-09-23 15:28:35 +0000237 raise unittest.SkipTest('Absolute path should have drive part')
Martin v. Löwis2d5157e2010-06-04 19:50:26 +0000238 unc_name = r'\\%s\%s$\%s' % (os.environ['COMPUTERNAME'],
239 fullname[0],
240 fullname[3:])
Hirokazu Yamamotodda7fdf2010-09-23 15:28:35 +0000241 if not os.path.exists(unc_name):
242 raise unittest.SkipTest('Cannot connect to UNC Path')
Martin v. Löwis2d5157e2010-06-04 19:50:26 +0000243
Georg Brandlec5ae3b2010-07-31 19:17:11 +0000244 with support.EnvironmentVarGuard() as env:
Martin v. Löwis2d5157e2010-06-04 19:50:26 +0000245 env.unset("TCL_LIBRARY")
Zachary Ware83fd0a82015-10-12 23:27:58 -0500246 stdout = subprocess.check_output(
247 [unc_name, '-c', 'import tkinter; print(tkinter)'])
Martin v. Löwis2d5157e2010-06-04 19:50:26 +0000248
Zachary Ware83fd0a82015-10-12 23:27:58 -0500249 self.assertIn(b'tkinter', stdout)
Martin v. Löwis2d5157e2010-06-04 19:50:26 +0000250
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
Serhiy Storchaka5bb5bbf2018-06-30 09:20:28 +0300652 def test_join(self):
653 join = tkinter._join
654 tcl = self.interp.tk
655 def unpack(s):
656 return tcl.call('lindex', s, 0)
657 def check(value):
658 self.assertEqual(unpack(join([value])), value)
659 self.assertEqual(unpack(join([value, 0])), value)
660 self.assertEqual(unpack(unpack(join([[value]]))), value)
661 self.assertEqual(unpack(unpack(join([[value, 0]]))), value)
662 self.assertEqual(unpack(unpack(join([[value], 0]))), value)
663 self.assertEqual(unpack(unpack(join([[value, 0], 0]))), value)
664 check('')
665 check('spam')
666 check('sp am')
667 check('sp\tam')
668 check('sp\nam')
669 check(' \t\n')
670 check('{spam}')
671 check('{sp am}')
672 check('"spam"')
673 check('"sp am"')
674 check('{"spam"}')
675 check('"{spam}"')
676 check('sp\\am')
677 check('"sp\\am"')
678 check('"{}" "{}"')
679 check('"\\')
680 check('"{')
681 check('"}')
682 check('\n\\')
683 check('\n{')
684 check('\n}')
685 check('\\\n')
686 check('{\n')
687 check('}\n')
688
Serhiy Storchakae3f1b092016-05-08 20:46:22 +0300689 def test_new_tcl_obj(self):
690 self.assertRaises(TypeError, _tkinter.Tcl_Obj)
Neal Norwitz63dfece2004-02-19 02:37:29 +0000691
Serhiy Storchaka9e6b9752013-08-21 21:38:21 +0300692class BigmemTclTest(unittest.TestCase):
693
694 def setUp(self):
695 self.interp = Tcl()
696
Serhiy Storchaka5cfc79d2014-02-07 10:06:39 +0200697 @support.cpython_only
698 @unittest.skipUnless(INT_MAX < PY_SSIZE_T_MAX, "needs UINT_MAX < SIZE_MAX")
699 @support.bigmemtest(size=INT_MAX + 1, memuse=5, dry_run=False)
Serhiy Storchaka79851d72014-05-30 14:24:03 +0300700 def test_huge_string_call(self, size):
Serhiy Storchaka9e6b9752013-08-21 21:38:21 +0300701 value = ' ' * size
Serhiy Storchaka27c623c2017-10-03 22:39:55 +0300702 self.assertRaises(OverflowError, self.interp.call, 'string', 'index', value, 0)
Serhiy Storchaka9e6b9752013-08-21 21:38:21 +0300703
Serhiy Storchaka79851d72014-05-30 14:24:03 +0300704 @support.cpython_only
705 @unittest.skipUnless(INT_MAX < PY_SSIZE_T_MAX, "needs UINT_MAX < SIZE_MAX")
Serhiy Storchaka27c623c2017-10-03 22:39:55 +0300706 @support.bigmemtest(size=INT_MAX + 1, memuse=2, dry_run=False)
Serhiy Storchaka79851d72014-05-30 14:24:03 +0300707 def test_huge_string_builtins(self, size):
Serhiy Storchaka27c623c2017-10-03 22:39:55 +0300708 tk = self.interp.tk
Serhiy Storchaka79851d72014-05-30 14:24:03 +0300709 value = '1' + ' ' * size
Serhiy Storchaka27c623c2017-10-03 22:39:55 +0300710 self.assertRaises(OverflowError, tk.getint, value)
711 self.assertRaises(OverflowError, tk.getdouble, value)
712 self.assertRaises(OverflowError, tk.getboolean, value)
713 self.assertRaises(OverflowError, tk.eval, value)
714 self.assertRaises(OverflowError, tk.evalfile, value)
715 self.assertRaises(OverflowError, tk.record, value)
716 self.assertRaises(OverflowError, tk.adderrorinfo, value)
717 self.assertRaises(OverflowError, tk.setvar, value, 'x', 'a')
718 self.assertRaises(OverflowError, tk.setvar, 'x', value, 'a')
719 self.assertRaises(OverflowError, tk.unsetvar, value)
720 self.assertRaises(OverflowError, tk.unsetvar, 'x', value)
721 self.assertRaises(OverflowError, tk.adderrorinfo, value)
722 self.assertRaises(OverflowError, tk.exprstring, value)
723 self.assertRaises(OverflowError, tk.exprlong, value)
724 self.assertRaises(OverflowError, tk.exprboolean, value)
725 self.assertRaises(OverflowError, tk.splitlist, value)
726 self.assertRaises(OverflowError, tk.split, value)
727 self.assertRaises(OverflowError, tk.createcommand, value, max)
728 self.assertRaises(OverflowError, tk.deletecommand, value)
729
730 @support.cpython_only
731 @unittest.skipUnless(INT_MAX < PY_SSIZE_T_MAX, "needs UINT_MAX < SIZE_MAX")
732 @support.bigmemtest(size=INT_MAX + 1, memuse=6, dry_run=False)
733 def test_huge_string_builtins2(self, size):
734 # These commands require larger memory for possible error messages
735 tk = self.interp.tk
736 value = '1' + ' ' * size
737 self.assertRaises(OverflowError, tk.evalfile, value)
738 self.assertRaises(OverflowError, tk.unsetvar, value)
739 self.assertRaises(OverflowError, tk.unsetvar, 'x', value)
Serhiy Storchaka79851d72014-05-30 14:24:03 +0300740
Serhiy Storchaka9e6b9752013-08-21 21:38:21 +0300741
Serhiy Storchaka8db18232013-11-20 17:43:49 +0200742def setUpModule():
743 if support.verbose:
744 tcl = Tcl()
745 print('patchlevel =', tcl.call('info', 'patchlevel'))
746
747
Neal Norwitz63dfece2004-02-19 02:37:29 +0000748def test_main():
Serhiy Storchaka9e6b9752013-08-21 21:38:21 +0300749 support.run_unittest(TclTest, TkinterTest, BigmemTclTest)
Neal Norwitz63dfece2004-02-19 02:37:29 +0000750
David Aschere2b4b322004-02-18 05:59:53 +0000751if __name__ == "__main__":
Neal Norwitz63dfece2004-02-19 02:37:29 +0000752 test_main()