blob: 3183ea850f73b77c2b9ed20eeac547a5d90185bf [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')
Miss Islington (bot)dc191242019-10-04 03:28:54 -0700432 self.assertEqual(passValue('string\U0001f4bb'), 'string\U0001f4bb')
Serhiy Storchaka1317e142014-02-03 21:24:07 +0200433 self.assertEqual(passValue('str\x00ing'), 'str\x00ing')
434 self.assertEqual(passValue('str\x00ing\xbd'), 'str\x00ing\xbd')
435 self.assertEqual(passValue('str\x00ing\u20ac'), 'str\x00ing\u20ac')
Miss Islington (bot)dc191242019-10-04 03:28:54 -0700436 self.assertEqual(passValue('str\x00ing\U0001f4bb'),
437 'str\x00ing\U0001f4bb')
Serhiy Storchaka74596a82014-07-30 18:33:13 +0300438 self.assertEqual(passValue(b'str\x00ing'),
439 b'str\x00ing' if self.wantobjects else 'str\x00ing')
440 self.assertEqual(passValue(b'str\xc0\x80ing'),
441 b'str\xc0\x80ing' if self.wantobjects else 'str\xc0\x80ing')
442 self.assertEqual(passValue(b'str\xbding'),
443 b'str\xbding' if self.wantobjects else 'str\xbding')
Serhiy Storchakaea134da2015-04-02 18:46:50 +0300444 for i in self.get_integers():
Serhiy Storchakacc4290b2013-12-25 17:29:01 +0200445 self.assertEqual(passValue(i), i if self.wantobjects else str(i))
Serhiy Storchakaea134da2015-04-02 18:46:50 +0300446 if tcl_version < (8, 5): # bignum was added in Tcl 8.5
447 self.assertEqual(passValue(2**1000), str(2**1000))
Serhiy Storchakadf4bb462013-02-07 15:40:03 +0200448 for f in (0.0, 1.0, -1.0, 1/3,
449 sys.float_info.min, sys.float_info.max,
450 -sys.float_info.min, -sys.float_info.max):
Serhiy Storchakacc4290b2013-12-25 17:29:01 +0200451 if self.wantobjects:
Serhiy Storchakadf4bb462013-02-07 15:40:03 +0200452 self.assertEqual(passValue(f), f)
Serhiy Storchakacc4290b2013-12-25 17:29:01 +0200453 else:
454 self.assertEqual(float(passValue(f)), f)
455 if self.wantobjects:
456 f = passValue(float('nan'))
457 self.assertNotEqual(f, f)
458 self.assertEqual(passValue(float('inf')), float('inf'))
459 self.assertEqual(passValue(-float('inf')), -float('inf'))
460 else:
Serhiy Storchakacc4290b2013-12-25 17:29:01 +0200461 self.assertEqual(float(passValue(float('inf'))), float('inf'))
462 self.assertEqual(float(passValue(-float('inf'))), -float('inf'))
Serhiy Storchaka6f1435c2014-07-07 14:57:08 +0300463 # XXX NaN representation can be not parsable by float()
Serhiy Storchakacc4290b2013-12-25 17:29:01 +0200464 self.assertEqual(passValue((1, '2', (3.4,))),
465 (1, '2', (3.4,)) if self.wantobjects else '1 2 3.4')
Serhiy Storchaka2b00c492014-05-21 17:12:21 +0300466 self.assertEqual(passValue(['a', ['b', 'c']]),
467 ('a', ('b', 'c')) if self.wantobjects else 'a {b c}')
Martin v. Löwis2d5157e2010-06-04 19:50:26 +0000468
Serhiy Storchaka4b730162014-01-23 09:44:05 +0200469 def test_user_command(self):
470 result = None
471 def testfunc(arg):
472 nonlocal result
473 result = arg
474 return arg
475 self.interp.createcommand('testfunc', testfunc)
Antoine Pitrou220cc212014-02-23 19:39:06 +0100476 self.addCleanup(self.interp.tk.deletecommand, 'testfunc')
Serhiy Storchakad6ec3092014-08-18 17:47:29 +0300477 def check(value, expected=None, *, eq=self.assertEqual):
478 if expected is None:
479 expected = value
480 nonlocal result
481 result = None
Serhiy Storchakabdf0cb52014-01-23 16:48:44 +0200482 r = self.interp.call('testfunc', value)
483 self.assertIsInstance(result, str)
484 eq(result, expected)
485 self.assertIsInstance(r, str)
486 eq(r, expected)
487 def float_eq(actual, expected):
Serhiy Storchakabdf0cb52014-01-23 16:48:44 +0200488 self.assertAlmostEqual(float(actual), expected,
489 delta=abs(expected) * 1e-10)
Serhiy Storchaka4b730162014-01-23 09:44:05 +0200490
491 check(True, '1')
492 check(False, '0')
Serhiy Storchakad6ec3092014-08-18 17:47:29 +0300493 check('string')
494 check('string\xbd')
495 check('string\u20ac')
Miss Islington (bot)dc191242019-10-04 03:28:54 -0700496 check('string\U0001f4bb')
Serhiy Storchakaabf68ce2014-09-11 10:57:13 +0300497 check('')
Serhiy Storchaka1317e142014-02-03 21:24:07 +0200498 check(b'string', 'string')
Serhiy Storchaka74596a82014-07-30 18:33:13 +0300499 check(b'string\xe2\x82\xac', 'string\xe2\x82\xac')
500 check(b'string\xbd', 'string\xbd')
Serhiy Storchakaabf68ce2014-09-11 10:57:13 +0300501 check(b'', '')
Serhiy Storchakad6ec3092014-08-18 17:47:29 +0300502 check('str\x00ing')
503 check('str\x00ing\xbd')
504 check('str\x00ing\u20ac')
Serhiy Storchaka74596a82014-07-30 18:33:13 +0300505 check(b'str\x00ing', 'str\x00ing')
506 check(b'str\xc0\x80ing', 'str\xc0\x80ing')
507 check(b'str\xc0\x80ing\xe2\x82\xac', 'str\xc0\x80ing\xe2\x82\xac')
Serhiy Storchakaea134da2015-04-02 18:46:50 +0300508 for i in self.get_integers():
Serhiy Storchaka4b730162014-01-23 09:44:05 +0200509 check(i, str(i))
Serhiy Storchakaea134da2015-04-02 18:46:50 +0300510 if tcl_version < (8, 5): # bignum was added in Tcl 8.5
511 check(2**1000, str(2**1000))
Serhiy Storchakabdf0cb52014-01-23 16:48:44 +0200512 for f in (0.0, 1.0, -1.0):
513 check(f, repr(f))
514 for f in (1/3.0, sys.float_info.min, sys.float_info.max,
Serhiy Storchaka4b730162014-01-23 09:44:05 +0200515 -sys.float_info.min, -sys.float_info.max):
Serhiy Storchakad6ec3092014-08-18 17:47:29 +0300516 check(f, eq=float_eq)
517 check(float('inf'), eq=float_eq)
518 check(-float('inf'), eq=float_eq)
Serhiy Storchaka6f1435c2014-07-07 14:57:08 +0300519 # XXX NaN representation can be not parsable by float()
Serhiy Storchaka4b730162014-01-23 09:44:05 +0200520 check((), '')
521 check((1, (2,), (3, 4), '5 6', ()), '1 2 {3 4} {5 6} {}')
Serhiy Storchaka2b00c492014-05-21 17:12:21 +0300522 check([1, [2,], [3, 4], '5 6', []], '1 2 {3 4} {5 6} {}')
Serhiy Storchaka4b730162014-01-23 09:44:05 +0200523
Serhiy Storchaka275d5fd2013-07-11 20:34:47 +0300524 def test_splitlist(self):
525 splitlist = self.interp.tk.splitlist
526 call = self.interp.tk.call
527 self.assertRaises(TypeError, splitlist)
528 self.assertRaises(TypeError, splitlist, 'a', 'b')
529 self.assertRaises(TypeError, splitlist, 2)
530 testcases = [
531 ('2', ('2',)),
532 ('', ()),
533 ('{}', ('',)),
534 ('""', ('',)),
535 ('a\n b\t\r c\n ', ('a', 'b', 'c')),
536 (b'a\n b\t\r c\n ', ('a', 'b', 'c')),
537 ('a \u20ac', ('a', '\u20ac')),
Miss Islington (bot)dc191242019-10-04 03:28:54 -0700538 ('a \U0001f4bb', ('a', '\U0001f4bb')),
Serhiy Storchaka275d5fd2013-07-11 20:34:47 +0300539 (b'a \xe2\x82\xac', ('a', '\u20ac')),
Serhiy Storchaka1317e142014-02-03 21:24:07 +0200540 (b'a\xc0\x80b c\xc0\x80d', ('a\x00b', 'c\x00d')),
Serhiy Storchaka275d5fd2013-07-11 20:34:47 +0300541 ('a {b c}', ('a', 'b c')),
542 (r'a b\ c', ('a', 'b c')),
543 (('a', 'b c'), ('a', 'b c')),
544 ('a 2', ('a', '2')),
545 (('a', 2), ('a', 2)),
546 ('a 3.4', ('a', '3.4')),
547 (('a', 3.4), ('a', 3.4)),
548 ((), ()),
Serhiy Storchaka2b00c492014-05-21 17:12:21 +0300549 ([], ()),
550 (['a', ['b', 'c']], ('a', ['b', 'c'])),
Serhiy Storchakacc4290b2013-12-25 17:29:01 +0200551 (call('list', 1, '2', (3.4,)),
552 (1, '2', (3.4,)) if self.wantobjects else
553 ('1', '2', '3.4')),
Serhiy Storchaka275d5fd2013-07-11 20:34:47 +0300554 ]
Victor Stinnerece38d92014-09-04 09:53:16 +0200555 tk_patchlevel = get_tk_patchlevel()
Serhiy Storchakadfa689b2013-09-08 20:29:37 +0300556 if tcl_version >= (8, 5):
Victor Stinnerece38d92014-09-04 09:53:16 +0200557 if not self.wantobjects or tk_patchlevel < (8, 5, 5):
Serhiy Storchaka92af06b2014-02-02 23:04:24 +0200558 # Before 8.5.5 dicts were converted to lists through string
Serhiy Storchaka74596a82014-07-30 18:33:13 +0300559 expected = ('12', '\u20ac', '\xe2\x82\xac', '3.4')
Serhiy Storchaka92af06b2014-02-02 23:04:24 +0200560 else:
Serhiy Storchaka74596a82014-07-30 18:33:13 +0300561 expected = (12, '\u20ac', b'\xe2\x82\xac', (3.4,))
Serhiy Storchakadfa689b2013-09-08 20:29:37 +0300562 testcases += [
Serhiy Storchaka92af06b2014-02-02 23:04:24 +0200563 (call('dict', 'create', 12, '\u20ac', b'\xe2\x82\xac', (3.4,)),
564 expected),
Serhiy Storchakadfa689b2013-09-08 20:29:37 +0300565 ]
Victor Stinnerece38d92014-09-04 09:53:16 +0200566 dbg_info = ('want objects? %s, Tcl version: %s, Tk patchlevel: %s'
567 % (self.wantobjects, tcl_version, tk_patchlevel))
Serhiy Storchaka275d5fd2013-07-11 20:34:47 +0300568 for arg, res in testcases:
Victor Stinnerece38d92014-09-04 09:53:16 +0200569 self.assertEqual(splitlist(arg), res,
570 'arg=%a, %s' % (arg, dbg_info))
Serhiy Storchaka275d5fd2013-07-11 20:34:47 +0300571 self.assertRaises(TclError, splitlist, '{')
572
573 def test_split(self):
574 split = self.interp.tk.split
575 call = self.interp.tk.call
576 self.assertRaises(TypeError, split)
577 self.assertRaises(TypeError, split, 'a', 'b')
578 self.assertRaises(TypeError, split, 2)
579 testcases = [
580 ('2', '2'),
581 ('', ''),
582 ('{}', ''),
583 ('""', ''),
584 ('{', '{'),
585 ('a\n b\t\r c\n ', ('a', 'b', 'c')),
586 (b'a\n b\t\r c\n ', ('a', 'b', 'c')),
587 ('a \u20ac', ('a', '\u20ac')),
588 (b'a \xe2\x82\xac', ('a', '\u20ac')),
Serhiy Storchaka1317e142014-02-03 21:24:07 +0200589 (b'a\xc0\x80b', 'a\x00b'),
590 (b'a\xc0\x80b c\xc0\x80d', ('a\x00b', 'c\x00d')),
591 (b'{a\xc0\x80b c\xc0\x80d', '{a\x00b c\x00d'),
Serhiy Storchaka275d5fd2013-07-11 20:34:47 +0300592 ('a {b c}', ('a', ('b', 'c'))),
593 (r'a b\ c', ('a', ('b', 'c'))),
594 (('a', b'b c'), ('a', ('b', 'c'))),
595 (('a', 'b c'), ('a', ('b', 'c'))),
596 ('a 2', ('a', '2')),
597 (('a', 2), ('a', 2)),
598 ('a 3.4', ('a', '3.4')),
599 (('a', 3.4), ('a', 3.4)),
600 (('a', (2, 3.4)), ('a', (2, 3.4))),
601 ((), ()),
Serhiy Storchaka2b00c492014-05-21 17:12:21 +0300602 ([], ()),
603 (['a', 'b c'], ('a', ('b', 'c'))),
604 (['a', ['b', 'c']], ('a', ('b', 'c'))),
Serhiy Storchakacc4290b2013-12-25 17:29:01 +0200605 (call('list', 1, '2', (3.4,)),
606 (1, '2', (3.4,)) if self.wantobjects else
607 ('1', '2', '3.4')),
Serhiy Storchaka275d5fd2013-07-11 20:34:47 +0300608 ]
Serhiy Storchakadfa689b2013-09-08 20:29:37 +0300609 if tcl_version >= (8, 5):
Serhiy Storchaka92af06b2014-02-02 23:04:24 +0200610 if not self.wantobjects or get_tk_patchlevel() < (8, 5, 5):
611 # Before 8.5.5 dicts were converted to lists through string
Serhiy Storchaka74596a82014-07-30 18:33:13 +0300612 expected = ('12', '\u20ac', '\xe2\x82\xac', '3.4')
Serhiy Storchaka92af06b2014-02-02 23:04:24 +0200613 else:
Serhiy Storchaka74596a82014-07-30 18:33:13 +0300614 expected = (12, '\u20ac', b'\xe2\x82\xac', (3.4,))
Serhiy Storchakadfa689b2013-09-08 20:29:37 +0300615 testcases += [
616 (call('dict', 'create', 12, '\u20ac', b'\xe2\x82\xac', (3.4,)),
Serhiy Storchaka92af06b2014-02-02 23:04:24 +0200617 expected),
Serhiy Storchakadfa689b2013-09-08 20:29:37 +0300618 ]
Serhiy Storchaka275d5fd2013-07-11 20:34:47 +0300619 for arg, res in testcases:
620 self.assertEqual(split(arg), res, msg=arg)
621
Serhiy Storchaka8f0a1d02014-09-06 22:47:58 +0300622 def test_splitdict(self):
623 splitdict = tkinter._splitdict
624 tcl = self.interp.tk
625
626 arg = '-a {1 2 3} -something foo status {}'
627 self.assertEqual(splitdict(tcl, arg, False),
628 {'-a': '1 2 3', '-something': 'foo', 'status': ''})
629 self.assertEqual(splitdict(tcl, arg),
630 {'a': '1 2 3', 'something': 'foo', 'status': ''})
631
632 arg = ('-a', (1, 2, 3), '-something', 'foo', 'status', '{}')
633 self.assertEqual(splitdict(tcl, arg, False),
634 {'-a': (1, 2, 3), '-something': 'foo', 'status': '{}'})
635 self.assertEqual(splitdict(tcl, arg),
636 {'a': (1, 2, 3), 'something': 'foo', 'status': '{}'})
637
638 self.assertRaises(RuntimeError, splitdict, tcl, '-a b -c ')
639 self.assertRaises(RuntimeError, splitdict, tcl, ('-a', 'b', '-c'))
640
641 arg = tcl.call('list',
642 '-a', (1, 2, 3), '-something', 'foo', 'status', ())
643 self.assertEqual(splitdict(tcl, arg),
644 {'a': (1, 2, 3) if self.wantobjects else '1 2 3',
645 'something': 'foo', 'status': ''})
646
647 if tcl_version >= (8, 5):
648 arg = tcl.call('dict', 'create',
649 '-a', (1, 2, 3), '-something', 'foo', 'status', ())
650 if not self.wantobjects or get_tk_patchlevel() < (8, 5, 5):
651 # Before 8.5.5 dicts were converted to lists through string
652 expected = {'a': '1 2 3', 'something': 'foo', 'status': ''}
653 else:
654 expected = {'a': (1, 2, 3), 'something': 'foo', 'status': ''}
655 self.assertEqual(splitdict(tcl, arg), expected)
656
Serhiy Storchaka5bb5bbf2018-06-30 09:20:28 +0300657 def test_join(self):
658 join = tkinter._join
659 tcl = self.interp.tk
660 def unpack(s):
661 return tcl.call('lindex', s, 0)
662 def check(value):
663 self.assertEqual(unpack(join([value])), value)
664 self.assertEqual(unpack(join([value, 0])), value)
665 self.assertEqual(unpack(unpack(join([[value]]))), value)
666 self.assertEqual(unpack(unpack(join([[value, 0]]))), value)
667 self.assertEqual(unpack(unpack(join([[value], 0]))), value)
668 self.assertEqual(unpack(unpack(join([[value, 0], 0]))), value)
669 check('')
670 check('spam')
671 check('sp am')
672 check('sp\tam')
673 check('sp\nam')
674 check(' \t\n')
675 check('{spam}')
676 check('{sp am}')
677 check('"spam"')
678 check('"sp am"')
679 check('{"spam"}')
680 check('"{spam}"')
681 check('sp\\am')
682 check('"sp\\am"')
683 check('"{}" "{}"')
684 check('"\\')
685 check('"{')
686 check('"}')
687 check('\n\\')
688 check('\n{')
689 check('\n}')
690 check('\\\n')
691 check('{\n')
692 check('}\n')
693
Serhiy Storchakae3f1b092016-05-08 20:46:22 +0300694 def test_new_tcl_obj(self):
695 self.assertRaises(TypeError, _tkinter.Tcl_Obj)
Neal Norwitz63dfece2004-02-19 02:37:29 +0000696
Serhiy Storchaka9e6b9752013-08-21 21:38:21 +0300697class BigmemTclTest(unittest.TestCase):
698
699 def setUp(self):
700 self.interp = Tcl()
701
Serhiy Storchaka5cfc79d2014-02-07 10:06:39 +0200702 @support.cpython_only
703 @unittest.skipUnless(INT_MAX < PY_SSIZE_T_MAX, "needs UINT_MAX < SIZE_MAX")
704 @support.bigmemtest(size=INT_MAX + 1, memuse=5, dry_run=False)
Serhiy Storchaka79851d72014-05-30 14:24:03 +0300705 def test_huge_string_call(self, size):
Serhiy Storchaka9e6b9752013-08-21 21:38:21 +0300706 value = ' ' * size
Serhiy Storchaka27c623c2017-10-03 22:39:55 +0300707 self.assertRaises(OverflowError, self.interp.call, 'string', 'index', value, 0)
Serhiy Storchaka9e6b9752013-08-21 21:38:21 +0300708
Serhiy Storchaka79851d72014-05-30 14:24:03 +0300709 @support.cpython_only
710 @unittest.skipUnless(INT_MAX < PY_SSIZE_T_MAX, "needs UINT_MAX < SIZE_MAX")
Serhiy Storchaka27c623c2017-10-03 22:39:55 +0300711 @support.bigmemtest(size=INT_MAX + 1, memuse=2, dry_run=False)
Serhiy Storchaka79851d72014-05-30 14:24:03 +0300712 def test_huge_string_builtins(self, size):
Serhiy Storchaka27c623c2017-10-03 22:39:55 +0300713 tk = self.interp.tk
Serhiy Storchaka79851d72014-05-30 14:24:03 +0300714 value = '1' + ' ' * size
Serhiy Storchaka27c623c2017-10-03 22:39:55 +0300715 self.assertRaises(OverflowError, tk.getint, value)
716 self.assertRaises(OverflowError, tk.getdouble, value)
717 self.assertRaises(OverflowError, tk.getboolean, value)
718 self.assertRaises(OverflowError, tk.eval, value)
719 self.assertRaises(OverflowError, tk.evalfile, value)
720 self.assertRaises(OverflowError, tk.record, value)
721 self.assertRaises(OverflowError, tk.adderrorinfo, value)
722 self.assertRaises(OverflowError, tk.setvar, value, 'x', 'a')
723 self.assertRaises(OverflowError, tk.setvar, 'x', value, 'a')
724 self.assertRaises(OverflowError, tk.unsetvar, value)
725 self.assertRaises(OverflowError, tk.unsetvar, 'x', value)
726 self.assertRaises(OverflowError, tk.adderrorinfo, value)
727 self.assertRaises(OverflowError, tk.exprstring, value)
728 self.assertRaises(OverflowError, tk.exprlong, value)
729 self.assertRaises(OverflowError, tk.exprboolean, value)
730 self.assertRaises(OverflowError, tk.splitlist, value)
731 self.assertRaises(OverflowError, tk.split, value)
732 self.assertRaises(OverflowError, tk.createcommand, value, max)
733 self.assertRaises(OverflowError, tk.deletecommand, value)
734
735 @support.cpython_only
736 @unittest.skipUnless(INT_MAX < PY_SSIZE_T_MAX, "needs UINT_MAX < SIZE_MAX")
737 @support.bigmemtest(size=INT_MAX + 1, memuse=6, dry_run=False)
738 def test_huge_string_builtins2(self, size):
739 # These commands require larger memory for possible error messages
740 tk = self.interp.tk
741 value = '1' + ' ' * size
742 self.assertRaises(OverflowError, tk.evalfile, value)
743 self.assertRaises(OverflowError, tk.unsetvar, value)
744 self.assertRaises(OverflowError, tk.unsetvar, 'x', value)
Serhiy Storchaka79851d72014-05-30 14:24:03 +0300745
Serhiy Storchaka9e6b9752013-08-21 21:38:21 +0300746
Serhiy Storchaka8db18232013-11-20 17:43:49 +0200747def setUpModule():
748 if support.verbose:
749 tcl = Tcl()
750 print('patchlevel =', tcl.call('info', 'patchlevel'))
751
752
Neal Norwitz63dfece2004-02-19 02:37:29 +0000753def test_main():
Serhiy Storchaka9e6b9752013-08-21 21:38:21 +0300754 support.run_unittest(TclTest, TkinterTest, BigmemTclTest)
Neal Norwitz63dfece2004-02-19 02:37:29 +0000755
David Aschere2b4b322004-02-18 05:59:53 +0000756if __name__ == "__main__":
Neal Norwitz63dfece2004-02-19 02:37:29 +0000757 test_main()