blob: b612517941ff45ed6d9993ea1274c2543bdcd517 [file] [log] [blame]
David Aschere2b4b322004-02-18 05:59:53 +00001import unittest
Serhiy Storchaka462c3572015-04-22 08:36:03 +03002import re
Hirokazu Yamamotodda7fdf2010-09-23 15:28:35 +00003import sys
David Aschere2b4b322004-02-18 05:59:53 +00004import os
Benjamin Petersonee8712c2008-05-20 21:35:26 +00005from test import support
R. David Murraya21e4ca2009-03-31 23:16:50 +00006
7# Skip this test if the _tkinter module wasn't built.
8_tkinter = support.import_module('_tkinter')
9
Terry Jan Reedy743c85a2013-03-16 02:37:06 -040010# Make sure tkinter._fix runs to set up the environment
Serhiy Storchaka8f0a1d02014-09-06 22:47:58 +030011tkinter = support.import_fresh_module('tkinter')
Terry Jan Reedy743c85a2013-03-16 02:37:06 -040012
Guilherme Polofa8fba92009-02-07 02:33:47 +000013from tkinter import Tcl
David Aschere2b4b322004-02-18 05:59:53 +000014from _tkinter import TclError
15
Serhiy Storchaka5cfc79d2014-02-07 10:06:39 +020016try:
17 from _testcapi import INT_MAX, PY_SSIZE_T_MAX
18except ImportError:
19 INT_MAX = PY_SSIZE_T_MAX = sys.maxsize
20
Serhiy Storchaka462c3572015-04-22 08:36:03 +030021tcl_version = tuple(map(int, _tkinter.TCL_VERSION.split('.')))
Serhiy Storchakadfa689b2013-09-08 20:29:37 +030022
Serhiy Storchaka92af06b2014-02-02 23:04:24 +020023_tk_patchlevel = None
24def get_tk_patchlevel():
25 global _tk_patchlevel
26 if _tk_patchlevel is None:
27 tcl = Tcl()
Serhiy Storchaka462c3572015-04-22 08:36:03 +030028 patchlevel = tcl.call('info', 'patchlevel')
29 m = re.fullmatch(r'(\d+)\.(\d+)([ab.])(\d+)', patchlevel)
30 major, minor, releaselevel, serial = m.groups()
31 major, minor, serial = int(major), int(minor), int(serial)
32 releaselevel = {'a': 'alpha', 'b': 'beta', '.': 'final'}[releaselevel]
33 if releaselevel == 'final':
34 _tk_patchlevel = major, minor, serial, releaselevel, 0
35 else:
36 _tk_patchlevel = major, minor, 0, releaselevel, serial
Serhiy Storchaka92af06b2014-02-02 23:04:24 +020037 return _tk_patchlevel
38
Benjamin Petersonc4bbc8d2009-01-30 03:39:35 +000039
40class TkinterTest(unittest.TestCase):
41
42 def testFlattenLen(self):
43 # flatten(<object with no length>)
44 self.assertRaises(TypeError, _tkinter._flatten, True)
45
46
David Aschere2b4b322004-02-18 05:59:53 +000047class TclTest(unittest.TestCase):
48
49 def setUp(self):
50 self.interp = Tcl()
Serhiy Storchakacc4290b2013-12-25 17:29:01 +020051 self.wantobjects = self.interp.tk.wantobjects()
David Aschere2b4b322004-02-18 05:59:53 +000052
53 def testEval(self):
54 tcl = self.interp
55 tcl.eval('set a 1')
56 self.assertEqual(tcl.eval('set a'),'1')
57
Serhiy Storchaka1317e142014-02-03 21:24:07 +020058 def test_eval_null_in_result(self):
59 tcl = self.interp
60 self.assertEqual(tcl.eval('set a "a\\0b"'), 'a\x00b')
61
David Aschere2b4b322004-02-18 05:59:53 +000062 def testEvalException(self):
63 tcl = self.interp
64 self.assertRaises(TclError,tcl.eval,'set a')
65
66 def testEvalException2(self):
67 tcl = self.interp
68 self.assertRaises(TclError,tcl.eval,'this is wrong')
69
70 def testCall(self):
71 tcl = self.interp
72 tcl.call('set','a','1')
73 self.assertEqual(tcl.call('set','a'),'1')
74
75 def testCallException(self):
76 tcl = self.interp
77 self.assertRaises(TclError,tcl.call,'set','a')
78
79 def testCallException2(self):
80 tcl = self.interp
81 self.assertRaises(TclError,tcl.call,'this','is','wrong')
82
83 def testSetVar(self):
84 tcl = self.interp
85 tcl.setvar('a','1')
86 self.assertEqual(tcl.eval('set a'),'1')
87
88 def testSetVarArray(self):
89 tcl = self.interp
90 tcl.setvar('a(1)','1')
91 self.assertEqual(tcl.eval('set a(1)'),'1')
92
93 def testGetVar(self):
94 tcl = self.interp
95 tcl.eval('set a 1')
96 self.assertEqual(tcl.getvar('a'),'1')
97
98 def testGetVarArray(self):
99 tcl = self.interp
100 tcl.eval('set a(1) 1')
101 self.assertEqual(tcl.getvar('a(1)'),'1')
102
103 def testGetVarException(self):
104 tcl = self.interp
105 self.assertRaises(TclError,tcl.getvar,'a')
106
107 def testGetVarArrayException(self):
108 tcl = self.interp
109 self.assertRaises(TclError,tcl.getvar,'a(1)')
110
111 def testUnsetVar(self):
112 tcl = self.interp
113 tcl.setvar('a',1)
114 self.assertEqual(tcl.eval('info exists a'),'1')
115 tcl.unsetvar('a')
116 self.assertEqual(tcl.eval('info exists a'),'0')
117
118 def testUnsetVarArray(self):
119 tcl = self.interp
120 tcl.setvar('a(1)',1)
121 tcl.setvar('a(2)',2)
122 self.assertEqual(tcl.eval('info exists a(1)'),'1')
123 self.assertEqual(tcl.eval('info exists a(2)'),'1')
124 tcl.unsetvar('a(1)')
125 self.assertEqual(tcl.eval('info exists a(1)'),'0')
126 self.assertEqual(tcl.eval('info exists a(2)'),'1')
127
128 def testUnsetVarException(self):
129 tcl = self.interp
130 self.assertRaises(TclError,tcl.unsetvar,'a')
Tim Peters27f88362004-07-08 04:22:35 +0000131
Serhiy Storchakaea134da2015-04-02 18:46:50 +0300132 def get_integers(self):
Serhiy Storchaka4c7dc482015-04-02 18:49:14 +0300133 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 +0300134 # bignum was added in Tcl 8.5, but its support is able only since 8.5.8
135 if (get_tk_patchlevel() >= (8, 6, 0, 'final') or
136 (8, 5, 8) <= get_tk_patchlevel() < (8, 6)):
Serhiy Storchakaea134da2015-04-02 18:46:50 +0300137 integers += (2**63, -2**63-1, 2**1000, -2**1000)
138 return integers
139
Serhiy Storchaka9f1f4f42014-05-30 14:07:38 +0300140 def test_getint(self):
141 tcl = self.interp.tk
Serhiy Storchakaea134da2015-04-02 18:46:50 +0300142 for i in self.get_integers():
143 self.assertEqual(tcl.getint(' %d ' % i), i)
Serhiy Storchaka2379d542015-04-02 20:07:09 +0300144 if tcl_version >= (8, 5):
145 self.assertEqual(tcl.getint(' %#o ' % i), i)
146 self.assertEqual(tcl.getint((' %#o ' % i).replace('o', '')), i)
Serhiy Storchakaea134da2015-04-02 18:46:50 +0300147 self.assertEqual(tcl.getint(' %#x ' % i), i)
148 if tcl_version < (8, 5): # bignum was added in Tcl 8.5
149 self.assertRaises(TclError, tcl.getint, str(2**1000))
Serhiy Storchaka9f1f4f42014-05-30 14:07:38 +0300150 self.assertEqual(tcl.getint(42), 42)
151 self.assertRaises(TypeError, tcl.getint)
152 self.assertRaises(TypeError, tcl.getint, '42', '10')
153 self.assertRaises(TypeError, tcl.getint, b'42')
154 self.assertRaises(TypeError, tcl.getint, 42.0)
155 self.assertRaises(TclError, tcl.getint, 'a')
156 self.assertRaises((TypeError, ValueError, TclError),
157 tcl.getint, '42\0')
158 self.assertRaises((UnicodeEncodeError, ValueError, TclError),
159 tcl.getint, '42\ud800')
160
161 def test_getdouble(self):
162 tcl = self.interp.tk
163 self.assertEqual(tcl.getdouble(' 42 '), 42.0)
164 self.assertEqual(tcl.getdouble(' 42.5 '), 42.5)
165 self.assertEqual(tcl.getdouble(42.5), 42.5)
Serhiy Storchaka645058d2015-05-06 14:00:04 +0300166 self.assertEqual(tcl.getdouble(42), 42.0)
Serhiy Storchaka9f1f4f42014-05-30 14:07:38 +0300167 self.assertRaises(TypeError, tcl.getdouble)
168 self.assertRaises(TypeError, tcl.getdouble, '42.5', '10')
169 self.assertRaises(TypeError, tcl.getdouble, b'42.5')
Serhiy Storchaka9f1f4f42014-05-30 14:07:38 +0300170 self.assertRaises(TclError, tcl.getdouble, 'a')
171 self.assertRaises((TypeError, ValueError, TclError),
172 tcl.getdouble, '42.5\0')
173 self.assertRaises((UnicodeEncodeError, ValueError, TclError),
174 tcl.getdouble, '42.5\ud800')
175
176 def test_getboolean(self):
177 tcl = self.interp.tk
178 self.assertIs(tcl.getboolean('on'), True)
179 self.assertIs(tcl.getboolean('1'), True)
Serhiy Storchaka9a6e2012015-04-04 12:43:01 +0300180 self.assertIs(tcl.getboolean(42), True)
181 self.assertIs(tcl.getboolean(0), False)
Serhiy Storchaka9f1f4f42014-05-30 14:07:38 +0300182 self.assertRaises(TypeError, tcl.getboolean)
183 self.assertRaises(TypeError, tcl.getboolean, 'on', '1')
184 self.assertRaises(TypeError, tcl.getboolean, b'on')
185 self.assertRaises(TypeError, tcl.getboolean, 1.0)
186 self.assertRaises(TclError, tcl.getboolean, 'a')
187 self.assertRaises((TypeError, ValueError, TclError),
188 tcl.getboolean, 'on\0')
189 self.assertRaises((UnicodeEncodeError, ValueError, TclError),
190 tcl.getboolean, 'on\ud800')
191
David Aschere2b4b322004-02-18 05:59:53 +0000192 def testEvalFile(self):
193 tcl = self.interp
Serhiy Storchaka1317e142014-02-03 21:24:07 +0200194 with open(support.TESTFN, 'w') as f:
195 self.addCleanup(support.unlink, support.TESTFN)
196 f.write("""set a 1
197 set b 2
198 set c [ expr $a + $b ]
199 """)
200 tcl.evalfile(support.TESTFN)
David Aschere2b4b322004-02-18 05:59:53 +0000201 self.assertEqual(tcl.eval('set a'),'1')
202 self.assertEqual(tcl.eval('set b'),'2')
203 self.assertEqual(tcl.eval('set c'),'3')
204
Serhiy Storchaka1317e142014-02-03 21:24:07 +0200205 def test_evalfile_null_in_result(self):
206 tcl = self.interp
207 with open(support.TESTFN, 'w') as f:
208 self.addCleanup(support.unlink, support.TESTFN)
209 f.write("""
210 set a "a\0b"
211 set b "a\\0b"
212 """)
213 tcl.evalfile(support.TESTFN)
214 self.assertEqual(tcl.eval('set a'), 'a\x00b')
215 self.assertEqual(tcl.eval('set b'), 'a\x00b')
216
David Aschere2b4b322004-02-18 05:59:53 +0000217 def testEvalFileException(self):
218 tcl = self.interp
219 filename = "doesnotexists"
220 try:
221 os.remove(filename)
Guido van Rossumb940e112007-01-10 16:19:56 +0000222 except Exception as e:
David Aschere2b4b322004-02-18 05:59:53 +0000223 pass
224 self.assertRaises(TclError,tcl.evalfile,filename)
225
David Aschere2b4b322004-02-18 05:59:53 +0000226 def testPackageRequireException(self):
227 tcl = self.interp
228 self.assertRaises(TclError,tcl.eval,'package require DNE')
229
Hirokazu Yamamotodda7fdf2010-09-23 15:28:35 +0000230 @unittest.skipUnless(sys.platform == 'win32', 'Requires Windows')
Martin v. Löwis2d5157e2010-06-04 19:50:26 +0000231 def testLoadWithUNC(self):
Martin v. Löwis2d5157e2010-06-04 19:50:26 +0000232 # Build a UNC path from the regular path.
233 # Something like
234 # \\%COMPUTERNAME%\c$\python27\python.exe
235
236 fullname = os.path.abspath(sys.executable)
237 if fullname[1] != ':':
Hirokazu Yamamotodda7fdf2010-09-23 15:28:35 +0000238 raise unittest.SkipTest('Absolute path should have drive part')
Martin v. Löwis2d5157e2010-06-04 19:50:26 +0000239 unc_name = r'\\%s\%s$\%s' % (os.environ['COMPUTERNAME'],
240 fullname[0],
241 fullname[3:])
Hirokazu Yamamotodda7fdf2010-09-23 15:28:35 +0000242 if not os.path.exists(unc_name):
243 raise unittest.SkipTest('Cannot connect to UNC Path')
Martin v. Löwis2d5157e2010-06-04 19:50:26 +0000244
Georg Brandlec5ae3b2010-07-31 19:17:11 +0000245 with support.EnvironmentVarGuard() as env:
Martin v. Löwis2d5157e2010-06-04 19:50:26 +0000246 env.unset("TCL_LIBRARY")
Hirokazu Yamamotof2dec8d2010-09-18 04:42:41 +0000247 f = os.popen('%s -c "import tkinter; print(tkinter)"' % (unc_name,))
Martin v. Löwis2d5157e2010-06-04 19:50:26 +0000248
Hirokazu Yamamotof2dec8d2010-09-18 04:42:41 +0000249 self.assertIn('tkinter', f.read())
Martin v. Löwis2d5157e2010-06-04 19:50:26 +0000250 # exit code must be zero
251 self.assertEqual(f.close(), None)
252
Serhiy Storchakafc055252014-02-03 20:41:34 +0200253 def test_exprstring(self):
254 tcl = self.interp
255 tcl.call('set', 'a', 3)
256 tcl.call('set', 'b', 6)
257 def check(expr, expected):
258 result = tcl.exprstring(expr)
259 self.assertEqual(result, expected)
260 self.assertIsInstance(result, str)
261
262 self.assertRaises(TypeError, tcl.exprstring)
263 self.assertRaises(TypeError, tcl.exprstring, '8.2', '+6')
264 self.assertRaises(TypeError, tcl.exprstring, b'8.2 + 6')
265 self.assertRaises(TclError, tcl.exprstring, 'spam')
266 check('', '0')
267 check('8.2 + 6', '14.2')
Serhiy Storchakafc055252014-02-03 20:41:34 +0200268 check('3.1 + $a', '6.1')
269 check('2 + "$a.$b"', '5.6')
270 check('4*[llength "6 2"]', '8')
271 check('{word one} < "word $a"', '0')
272 check('4*2 < 7', '0')
273 check('hypot($a, 4)', '5.0')
274 check('5 / 4', '1')
275 check('5 / 4.0', '1.25')
276 check('5 / ( [string length "abcd"] + 0.0 )', '1.25')
277 check('20.0/5.0', '4.0')
278 check('"0x03" > "2"', '1')
279 check('[string length "a\xbd\u20ac"]', '3')
280 check(r'[string length "a\xbd\u20ac"]', '3')
281 check('"abc"', 'abc')
282 check('"a\xbd\u20ac"', 'a\xbd\u20ac')
283 check(r'"a\xbd\u20ac"', 'a\xbd\u20ac')
Serhiy Storchaka1317e142014-02-03 21:24:07 +0200284 check(r'"a\0b"', 'a\x00b')
Serhiy Storchakaea134da2015-04-02 18:46:50 +0300285 if tcl_version >= (8, 5): # bignum was added in Tcl 8.5
Serhiy Storchaka160f8922014-02-03 22:31:09 +0200286 check('2**64', str(2**64))
Serhiy Storchakafc055252014-02-03 20:41:34 +0200287
288 def test_exprdouble(self):
289 tcl = self.interp
290 tcl.call('set', 'a', 3)
291 tcl.call('set', 'b', 6)
292 def check(expr, expected):
293 result = tcl.exprdouble(expr)
294 self.assertEqual(result, expected)
295 self.assertIsInstance(result, float)
296
297 self.assertRaises(TypeError, tcl.exprdouble)
298 self.assertRaises(TypeError, tcl.exprdouble, '8.2', '+6')
299 self.assertRaises(TypeError, tcl.exprdouble, b'8.2 + 6')
300 self.assertRaises(TclError, tcl.exprdouble, 'spam')
301 check('', 0.0)
302 check('8.2 + 6', 14.2)
Serhiy Storchakafc055252014-02-03 20:41:34 +0200303 check('3.1 + $a', 6.1)
304 check('2 + "$a.$b"', 5.6)
305 check('4*[llength "6 2"]', 8.0)
306 check('{word one} < "word $a"', 0.0)
307 check('4*2 < 7', 0.0)
308 check('hypot($a, 4)', 5.0)
309 check('5 / 4', 1.0)
310 check('5 / 4.0', 1.25)
311 check('5 / ( [string length "abcd"] + 0.0 )', 1.25)
312 check('20.0/5.0', 4.0)
313 check('"0x03" > "2"', 1.0)
314 check('[string length "a\xbd\u20ac"]', 3.0)
315 check(r'[string length "a\xbd\u20ac"]', 3.0)
316 self.assertRaises(TclError, tcl.exprdouble, '"abc"')
Serhiy Storchakaea134da2015-04-02 18:46:50 +0300317 if tcl_version >= (8, 5): # bignum was added in Tcl 8.5
Serhiy Storchaka160f8922014-02-03 22:31:09 +0200318 check('2**64', float(2**64))
Serhiy Storchakafc055252014-02-03 20:41:34 +0200319
320 def test_exprlong(self):
321 tcl = self.interp
322 tcl.call('set', 'a', 3)
323 tcl.call('set', 'b', 6)
324 def check(expr, expected):
325 result = tcl.exprlong(expr)
326 self.assertEqual(result, expected)
327 self.assertIsInstance(result, int)
328
329 self.assertRaises(TypeError, tcl.exprlong)
330 self.assertRaises(TypeError, tcl.exprlong, '8.2', '+6')
331 self.assertRaises(TypeError, tcl.exprlong, b'8.2 + 6')
332 self.assertRaises(TclError, tcl.exprlong, 'spam')
333 check('', 0)
334 check('8.2 + 6', 14)
Serhiy Storchakafc055252014-02-03 20:41:34 +0200335 check('3.1 + $a', 6)
336 check('2 + "$a.$b"', 5)
337 check('4*[llength "6 2"]', 8)
338 check('{word one} < "word $a"', 0)
339 check('4*2 < 7', 0)
340 check('hypot($a, 4)', 5)
341 check('5 / 4', 1)
342 check('5 / 4.0', 1)
343 check('5 / ( [string length "abcd"] + 0.0 )', 1)
344 check('20.0/5.0', 4)
345 check('"0x03" > "2"', 1)
346 check('[string length "a\xbd\u20ac"]', 3)
347 check(r'[string length "a\xbd\u20ac"]', 3)
348 self.assertRaises(TclError, tcl.exprlong, '"abc"')
Serhiy Storchakaea134da2015-04-02 18:46:50 +0300349 if tcl_version >= (8, 5): # bignum was added in Tcl 8.5
Serhiy Storchaka160f8922014-02-03 22:31:09 +0200350 self.assertRaises(TclError, tcl.exprlong, '2**64')
Serhiy Storchakafc055252014-02-03 20:41:34 +0200351
352 def test_exprboolean(self):
353 tcl = self.interp
354 tcl.call('set', 'a', 3)
355 tcl.call('set', 'b', 6)
356 def check(expr, expected):
357 result = tcl.exprboolean(expr)
358 self.assertEqual(result, expected)
359 self.assertIsInstance(result, int)
360 self.assertNotIsInstance(result, bool)
361
362 self.assertRaises(TypeError, tcl.exprboolean)
363 self.assertRaises(TypeError, tcl.exprboolean, '8.2', '+6')
364 self.assertRaises(TypeError, tcl.exprboolean, b'8.2 + 6')
365 self.assertRaises(TclError, tcl.exprboolean, 'spam')
366 check('', False)
367 for value in ('0', 'false', 'no', 'off'):
368 check(value, False)
369 check('"%s"' % value, False)
370 check('{%s}' % value, False)
371 for value in ('1', 'true', 'yes', 'on'):
372 check(value, True)
373 check('"%s"' % value, True)
374 check('{%s}' % value, True)
375 check('8.2 + 6', True)
Serhiy Storchakafc055252014-02-03 20:41:34 +0200376 check('3.1 + $a', True)
377 check('2 + "$a.$b"', True)
378 check('4*[llength "6 2"]', True)
379 check('{word one} < "word $a"', False)
380 check('4*2 < 7', False)
381 check('hypot($a, 4)', True)
382 check('5 / 4', True)
383 check('5 / 4.0', True)
384 check('5 / ( [string length "abcd"] + 0.0 )', True)
385 check('20.0/5.0', True)
386 check('"0x03" > "2"', True)
387 check('[string length "a\xbd\u20ac"]', True)
388 check(r'[string length "a\xbd\u20ac"]', True)
389 self.assertRaises(TclError, tcl.exprboolean, '"abc"')
Serhiy Storchakaea134da2015-04-02 18:46:50 +0300390 if tcl_version >= (8, 5): # bignum was added in Tcl 8.5
Serhiy Storchaka160f8922014-02-03 22:31:09 +0200391 check('2**64', True)
Serhiy Storchakafc055252014-02-03 20:41:34 +0200392
Serhiy Storchakaa5a4bd72015-04-02 19:57:52 +0300393 @unittest.skipUnless(tcl_version >= (8, 5), 'requires Tcl version >= 8.5')
Serhiy Storchakaf7de3dd2015-04-02 10:35:57 +0300394 def test_booleans(self):
395 tcl = self.interp
396 def check(expr, expected):
397 result = tcl.call('expr', expr)
Serhiy Storchaka9171fe52015-04-02 11:46:07 +0300398 if tcl.wantobjects():
399 self.assertEqual(result, expected)
400 self.assertIsInstance(result, int)
401 else:
402 self.assertIn(result, (expr, str(int(expected))))
403 self.assertIsInstance(result, str)
Serhiy Storchakaf7de3dd2015-04-02 10:35:57 +0300404 check('true', True)
405 check('yes', True)
406 check('on', True)
407 check('false', False)
408 check('no', False)
409 check('off', False)
410 check('1 < 2', True)
411 check('1 > 2', False)
412
Serhiy Storchakaea134da2015-04-02 18:46:50 +0300413 def test_expr_bignum(self):
414 tcl = self.interp
415 for i in self.get_integers():
416 result = tcl.call('expr', str(i))
417 if self.wantobjects:
418 self.assertEqual(result, i)
419 self.assertIsInstance(result, int)
420 else:
421 self.assertEqual(result, str(i))
422 self.assertIsInstance(result, str)
423 if tcl_version < (8, 5): # bignum was added in Tcl 8.5
Serhiy Storchaka2379d542015-04-02 20:07:09 +0300424 self.assertRaises(TclError, tcl.call, 'expr', str(2**1000))
Serhiy Storchakaea134da2015-04-02 18:46:50 +0300425
Serhiy Storchakadf4bb462013-02-07 15:40:03 +0200426 def test_passing_values(self):
427 def passValue(value):
428 return self.interp.call('set', '_', value)
429
Serhiy Storchakacc4290b2013-12-25 17:29:01 +0200430 self.assertEqual(passValue(True), True if self.wantobjects else '1')
431 self.assertEqual(passValue(False), False if self.wantobjects else '0')
Serhiy Storchakadf4bb462013-02-07 15:40:03 +0200432 self.assertEqual(passValue('string'), 'string')
433 self.assertEqual(passValue('string\u20ac'), 'string\u20ac')
Serhiy Storchaka1317e142014-02-03 21:24:07 +0200434 self.assertEqual(passValue('str\x00ing'), 'str\x00ing')
435 self.assertEqual(passValue('str\x00ing\xbd'), 'str\x00ing\xbd')
436 self.assertEqual(passValue('str\x00ing\u20ac'), 'str\x00ing\u20ac')
Serhiy Storchaka74596a82014-07-30 18:33:13 +0300437 self.assertEqual(passValue(b'str\x00ing'),
438 b'str\x00ing' if self.wantobjects else 'str\x00ing')
439 self.assertEqual(passValue(b'str\xc0\x80ing'),
440 b'str\xc0\x80ing' if self.wantobjects else 'str\xc0\x80ing')
441 self.assertEqual(passValue(b'str\xbding'),
442 b'str\xbding' if self.wantobjects else 'str\xbding')
Serhiy Storchakaea134da2015-04-02 18:46:50 +0300443 for i in self.get_integers():
Serhiy Storchakacc4290b2013-12-25 17:29:01 +0200444 self.assertEqual(passValue(i), i if self.wantobjects else str(i))
Serhiy Storchakaea134da2015-04-02 18:46:50 +0300445 if tcl_version < (8, 5): # bignum was added in Tcl 8.5
446 self.assertEqual(passValue(2**1000), str(2**1000))
Serhiy Storchakadf4bb462013-02-07 15:40:03 +0200447 for f in (0.0, 1.0, -1.0, 1/3,
448 sys.float_info.min, sys.float_info.max,
449 -sys.float_info.min, -sys.float_info.max):
Serhiy Storchakacc4290b2013-12-25 17:29:01 +0200450 if self.wantobjects:
Serhiy Storchakadf4bb462013-02-07 15:40:03 +0200451 self.assertEqual(passValue(f), f)
Serhiy Storchakacc4290b2013-12-25 17:29:01 +0200452 else:
453 self.assertEqual(float(passValue(f)), f)
454 if self.wantobjects:
455 f = passValue(float('nan'))
456 self.assertNotEqual(f, f)
457 self.assertEqual(passValue(float('inf')), float('inf'))
458 self.assertEqual(passValue(-float('inf')), -float('inf'))
459 else:
Serhiy Storchakacc4290b2013-12-25 17:29:01 +0200460 self.assertEqual(float(passValue(float('inf'))), float('inf'))
461 self.assertEqual(float(passValue(-float('inf'))), -float('inf'))
Serhiy Storchaka6f1435c2014-07-07 14:57:08 +0300462 # XXX NaN representation can be not parsable by float()
Serhiy Storchakacc4290b2013-12-25 17:29:01 +0200463 self.assertEqual(passValue((1, '2', (3.4,))),
464 (1, '2', (3.4,)) if self.wantobjects else '1 2 3.4')
Serhiy Storchaka2b00c492014-05-21 17:12:21 +0300465 self.assertEqual(passValue(['a', ['b', 'c']]),
466 ('a', ('b', 'c')) if self.wantobjects else 'a {b c}')
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} {}')
Serhiy Storchaka2b00c492014-05-21 17:12:21 +0300520 check([1, [2,], [3, 4], '5 6', []], '1 2 {3 4} {5 6} {}')
Serhiy Storchaka4b730162014-01-23 09:44:05 +0200521
Serhiy Storchaka275d5fd2013-07-11 20:34:47 +0300522 def test_splitlist(self):
523 splitlist = self.interp.tk.splitlist
524 call = self.interp.tk.call
525 self.assertRaises(TypeError, splitlist)
526 self.assertRaises(TypeError, splitlist, 'a', 'b')
527 self.assertRaises(TypeError, splitlist, 2)
528 testcases = [
529 ('2', ('2',)),
530 ('', ()),
531 ('{}', ('',)),
532 ('""', ('',)),
533 ('a\n b\t\r c\n ', ('a', 'b', 'c')),
534 (b'a\n b\t\r c\n ', ('a', 'b', 'c')),
535 ('a \u20ac', ('a', '\u20ac')),
536 (b'a \xe2\x82\xac', ('a', '\u20ac')),
Serhiy Storchaka1317e142014-02-03 21:24:07 +0200537 (b'a\xc0\x80b c\xc0\x80d', ('a\x00b', 'c\x00d')),
Serhiy Storchaka275d5fd2013-07-11 20:34:47 +0300538 ('a {b c}', ('a', 'b c')),
539 (r'a b\ c', ('a', 'b c')),
540 (('a', 'b c'), ('a', 'b c')),
541 ('a 2', ('a', '2')),
542 (('a', 2), ('a', 2)),
543 ('a 3.4', ('a', '3.4')),
544 (('a', 3.4), ('a', 3.4)),
545 ((), ()),
Serhiy Storchaka2b00c492014-05-21 17:12:21 +0300546 ([], ()),
547 (['a', ['b', 'c']], ('a', ['b', 'c'])),
Serhiy Storchakacc4290b2013-12-25 17:29:01 +0200548 (call('list', 1, '2', (3.4,)),
549 (1, '2', (3.4,)) if self.wantobjects else
550 ('1', '2', '3.4')),
Serhiy Storchaka275d5fd2013-07-11 20:34:47 +0300551 ]
Victor Stinnerece38d92014-09-04 09:53:16 +0200552 tk_patchlevel = get_tk_patchlevel()
Serhiy Storchakadfa689b2013-09-08 20:29:37 +0300553 if tcl_version >= (8, 5):
Victor Stinnerece38d92014-09-04 09:53:16 +0200554 if not self.wantobjects or tk_patchlevel < (8, 5, 5):
Serhiy Storchaka92af06b2014-02-02 23:04:24 +0200555 # Before 8.5.5 dicts were converted to lists through string
Serhiy Storchaka74596a82014-07-30 18:33:13 +0300556 expected = ('12', '\u20ac', '\xe2\x82\xac', '3.4')
Serhiy Storchaka92af06b2014-02-02 23:04:24 +0200557 else:
Serhiy Storchaka74596a82014-07-30 18:33:13 +0300558 expected = (12, '\u20ac', b'\xe2\x82\xac', (3.4,))
Serhiy Storchakadfa689b2013-09-08 20:29:37 +0300559 testcases += [
Serhiy Storchaka92af06b2014-02-02 23:04:24 +0200560 (call('dict', 'create', 12, '\u20ac', b'\xe2\x82\xac', (3.4,)),
561 expected),
Serhiy Storchakadfa689b2013-09-08 20:29:37 +0300562 ]
Victor Stinnerece38d92014-09-04 09:53:16 +0200563 dbg_info = ('want objects? %s, Tcl version: %s, Tk patchlevel: %s'
564 % (self.wantobjects, tcl_version, tk_patchlevel))
Serhiy Storchaka275d5fd2013-07-11 20:34:47 +0300565 for arg, res in testcases:
Victor Stinnerece38d92014-09-04 09:53:16 +0200566 self.assertEqual(splitlist(arg), res,
567 'arg=%a, %s' % (arg, dbg_info))
Serhiy Storchaka275d5fd2013-07-11 20:34:47 +0300568 self.assertRaises(TclError, splitlist, '{')
569
570 def test_split(self):
571 split = self.interp.tk.split
572 call = self.interp.tk.call
573 self.assertRaises(TypeError, split)
574 self.assertRaises(TypeError, split, 'a', 'b')
575 self.assertRaises(TypeError, split, 2)
576 testcases = [
577 ('2', '2'),
578 ('', ''),
579 ('{}', ''),
580 ('""', ''),
581 ('{', '{'),
582 ('a\n b\t\r c\n ', ('a', 'b', 'c')),
583 (b'a\n b\t\r c\n ', ('a', 'b', 'c')),
584 ('a \u20ac', ('a', '\u20ac')),
585 (b'a \xe2\x82\xac', ('a', '\u20ac')),
Serhiy Storchaka1317e142014-02-03 21:24:07 +0200586 (b'a\xc0\x80b', 'a\x00b'),
587 (b'a\xc0\x80b c\xc0\x80d', ('a\x00b', 'c\x00d')),
588 (b'{a\xc0\x80b c\xc0\x80d', '{a\x00b c\x00d'),
Serhiy Storchaka275d5fd2013-07-11 20:34:47 +0300589 ('a {b c}', ('a', ('b', 'c'))),
590 (r'a b\ c', ('a', ('b', 'c'))),
591 (('a', b'b c'), ('a', ('b', 'c'))),
592 (('a', 'b c'), ('a', ('b', 'c'))),
593 ('a 2', ('a', '2')),
594 (('a', 2), ('a', 2)),
595 ('a 3.4', ('a', '3.4')),
596 (('a', 3.4), ('a', 3.4)),
597 (('a', (2, 3.4)), ('a', (2, 3.4))),
598 ((), ()),
Serhiy Storchaka2b00c492014-05-21 17:12:21 +0300599 ([], ()),
600 (['a', 'b c'], ('a', ('b', 'c'))),
601 (['a', ['b', 'c']], ('a', ('b', 'c'))),
Serhiy Storchakacc4290b2013-12-25 17:29:01 +0200602 (call('list', 1, '2', (3.4,)),
603 (1, '2', (3.4,)) if self.wantobjects else
604 ('1', '2', '3.4')),
Serhiy Storchaka275d5fd2013-07-11 20:34:47 +0300605 ]
Serhiy Storchakadfa689b2013-09-08 20:29:37 +0300606 if tcl_version >= (8, 5):
Serhiy Storchaka92af06b2014-02-02 23:04:24 +0200607 if not self.wantobjects or get_tk_patchlevel() < (8, 5, 5):
608 # Before 8.5.5 dicts were converted to lists through string
Serhiy Storchaka74596a82014-07-30 18:33:13 +0300609 expected = ('12', '\u20ac', '\xe2\x82\xac', '3.4')
Serhiy Storchaka92af06b2014-02-02 23:04:24 +0200610 else:
Serhiy Storchaka74596a82014-07-30 18:33:13 +0300611 expected = (12, '\u20ac', b'\xe2\x82\xac', (3.4,))
Serhiy Storchakadfa689b2013-09-08 20:29:37 +0300612 testcases += [
613 (call('dict', 'create', 12, '\u20ac', b'\xe2\x82\xac', (3.4,)),
Serhiy Storchaka92af06b2014-02-02 23:04:24 +0200614 expected),
Serhiy Storchakadfa689b2013-09-08 20:29:37 +0300615 ]
Serhiy Storchaka275d5fd2013-07-11 20:34:47 +0300616 for arg, res in testcases:
617 self.assertEqual(split(arg), res, msg=arg)
618
Serhiy Storchaka8f0a1d02014-09-06 22:47:58 +0300619 def test_splitdict(self):
620 splitdict = tkinter._splitdict
621 tcl = self.interp.tk
622
623 arg = '-a {1 2 3} -something foo status {}'
624 self.assertEqual(splitdict(tcl, arg, False),
625 {'-a': '1 2 3', '-something': 'foo', 'status': ''})
626 self.assertEqual(splitdict(tcl, arg),
627 {'a': '1 2 3', 'something': 'foo', 'status': ''})
628
629 arg = ('-a', (1, 2, 3), '-something', 'foo', 'status', '{}')
630 self.assertEqual(splitdict(tcl, arg, False),
631 {'-a': (1, 2, 3), '-something': 'foo', 'status': '{}'})
632 self.assertEqual(splitdict(tcl, arg),
633 {'a': (1, 2, 3), 'something': 'foo', 'status': '{}'})
634
635 self.assertRaises(RuntimeError, splitdict, tcl, '-a b -c ')
636 self.assertRaises(RuntimeError, splitdict, tcl, ('-a', 'b', '-c'))
637
638 arg = tcl.call('list',
639 '-a', (1, 2, 3), '-something', 'foo', 'status', ())
640 self.assertEqual(splitdict(tcl, arg),
641 {'a': (1, 2, 3) if self.wantobjects else '1 2 3',
642 'something': 'foo', 'status': ''})
643
644 if tcl_version >= (8, 5):
645 arg = tcl.call('dict', 'create',
646 '-a', (1, 2, 3), '-something', 'foo', 'status', ())
647 if not self.wantobjects or get_tk_patchlevel() < (8, 5, 5):
648 # Before 8.5.5 dicts were converted to lists through string
649 expected = {'a': '1 2 3', 'something': 'foo', 'status': ''}
650 else:
651 expected = {'a': (1, 2, 3), 'something': 'foo', 'status': ''}
652 self.assertEqual(splitdict(tcl, arg), expected)
653
Neal Norwitz63dfece2004-02-19 02:37:29 +0000654
Serhiy Storchaka9e6b9752013-08-21 21:38:21 +0300655class BigmemTclTest(unittest.TestCase):
656
657 def setUp(self):
658 self.interp = Tcl()
659
Serhiy Storchaka5cfc79d2014-02-07 10:06:39 +0200660 @support.cpython_only
661 @unittest.skipUnless(INT_MAX < PY_SSIZE_T_MAX, "needs UINT_MAX < SIZE_MAX")
662 @support.bigmemtest(size=INT_MAX + 1, memuse=5, dry_run=False)
Serhiy Storchaka79851d72014-05-30 14:24:03 +0300663 def test_huge_string_call(self, size):
Serhiy Storchaka9e6b9752013-08-21 21:38:21 +0300664 value = ' ' * size
665 self.assertRaises(OverflowError, self.interp.call, 'set', '_', value)
666
Serhiy Storchaka79851d72014-05-30 14:24:03 +0300667 @support.cpython_only
668 @unittest.skipUnless(INT_MAX < PY_SSIZE_T_MAX, "needs UINT_MAX < SIZE_MAX")
669 @support.bigmemtest(size=INT_MAX + 1, memuse=9, dry_run=False)
670 def test_huge_string_builtins(self, size):
671 value = '1' + ' ' * size
Serhiy Storchakaaecfa9e2014-05-30 15:54:35 +0300672 self.assertRaises(OverflowError, self.interp.tk.getint, value)
673 self.assertRaises(OverflowError, self.interp.tk.getdouble, value)
674 self.assertRaises(OverflowError, self.interp.tk.getboolean, value)
Serhiy Storchaka79851d72014-05-30 14:24:03 +0300675 self.assertRaises(OverflowError, self.interp.eval, value)
676 self.assertRaises(OverflowError, self.interp.evalfile, value)
677 self.assertRaises(OverflowError, self.interp.record, value)
678 self.assertRaises(OverflowError, self.interp.adderrorinfo, value)
679 self.assertRaises(OverflowError, self.interp.setvar, value, 'x', 'a')
680 self.assertRaises(OverflowError, self.interp.setvar, 'x', value, 'a')
681 self.assertRaises(OverflowError, self.interp.unsetvar, value)
682 self.assertRaises(OverflowError, self.interp.unsetvar, 'x', value)
683 self.assertRaises(OverflowError, self.interp.adderrorinfo, value)
684 self.assertRaises(OverflowError, self.interp.exprstring, value)
685 self.assertRaises(OverflowError, self.interp.exprlong, value)
686 self.assertRaises(OverflowError, self.interp.exprboolean, value)
687 self.assertRaises(OverflowError, self.interp.splitlist, value)
688 self.assertRaises(OverflowError, self.interp.split, value)
689 self.assertRaises(OverflowError, self.interp.createcommand, value, max)
690 self.assertRaises(OverflowError, self.interp.deletecommand, value)
691
Serhiy Storchaka9e6b9752013-08-21 21:38:21 +0300692
Serhiy Storchaka8db18232013-11-20 17:43:49 +0200693def setUpModule():
694 if support.verbose:
695 tcl = Tcl()
696 print('patchlevel =', tcl.call('info', 'patchlevel'))
697
698
Neal Norwitz63dfece2004-02-19 02:37:29 +0000699def test_main():
Serhiy Storchaka9e6b9752013-08-21 21:38:21 +0300700 support.run_unittest(TclTest, TkinterTest, BigmemTclTest)
Neal Norwitz63dfece2004-02-19 02:37:29 +0000701
David Aschere2b4b322004-02-18 05:59:53 +0000702if __name__ == "__main__":
Neal Norwitz63dfece2004-02-19 02:37:29 +0000703 test_main()