1 import unittest
2 import subprocess
3 import sys
4 import os
5 from test import support
6 from test.support import import_helper
7 from test.support import os_helper
8
9 # Skip this test if the _tkinter module wasn't built.
10 _tkinter = import_helper.import_module('_tkinter')
11
12 import tkinter
13 from tkinter import Tcl
14 from _tkinter import TclError
15
16 try:
17 from _testcapi import INT_MAX, PY_SSIZE_T_MAX
18 except ImportError:
19 INT_MAX = PY_SSIZE_T_MAX = sys.maxsize
20
21 tcl_version = tuple(map(int, _tkinter.TCL_VERSION.split('.')))
22
23
24 class ESC[4;38;5;81mTkinterTest(ESC[4;38;5;149munittestESC[4;38;5;149m.ESC[4;38;5;149mTestCase):
25
26 def testFlattenLen(self):
27 # Object without length.
28 self.assertRaises(TypeError, _tkinter._flatten, True)
29 # Object with length, but not sequence.
30 self.assertRaises(TypeError, _tkinter._flatten, {})
31 # Sequence or set, but not tuple or list.
32 # (issue44608: there were leaks in the following cases)
33 self.assertRaises(TypeError, _tkinter._flatten, 'string')
34 self.assertRaises(TypeError, _tkinter._flatten, {'set'})
35
36
37 class ESC[4;38;5;81mTclTest(ESC[4;38;5;149munittestESC[4;38;5;149m.ESC[4;38;5;149mTestCase):
38
39 def setUp(self):
40 self.interp = Tcl()
41 self.wantobjects = self.interp.tk.wantobjects()
42
43 def testEval(self):
44 tcl = self.interp
45 tcl.eval('set a 1')
46 self.assertEqual(tcl.eval('set a'),'1')
47
48 def test_eval_null_in_result(self):
49 tcl = self.interp
50 self.assertEqual(tcl.eval('set a "a\\0b"'), 'a\x00b')
51
52 def test_eval_surrogates_in_result(self):
53 tcl = self.interp
54 self.assertIn(tcl.eval(r'set a "<\ud83d\udcbb>"'), '<\U0001f4bb>')
55
56 def testEvalException(self):
57 tcl = self.interp
58 self.assertRaises(TclError,tcl.eval,'set a')
59
60 def testEvalException2(self):
61 tcl = self.interp
62 self.assertRaises(TclError,tcl.eval,'this is wrong')
63
64 def testCall(self):
65 tcl = self.interp
66 tcl.call('set','a','1')
67 self.assertEqual(tcl.call('set','a'),'1')
68
69 def testCallException(self):
70 tcl = self.interp
71 self.assertRaises(TclError,tcl.call,'set','a')
72
73 def testCallException2(self):
74 tcl = self.interp
75 self.assertRaises(TclError,tcl.call,'this','is','wrong')
76
77 def testSetVar(self):
78 tcl = self.interp
79 tcl.setvar('a','1')
80 self.assertEqual(tcl.eval('set a'),'1')
81
82 def testSetVarArray(self):
83 tcl = self.interp
84 tcl.setvar('a(1)','1')
85 self.assertEqual(tcl.eval('set a(1)'),'1')
86
87 def testGetVar(self):
88 tcl = self.interp
89 tcl.eval('set a 1')
90 self.assertEqual(tcl.getvar('a'),'1')
91
92 def testGetVarArray(self):
93 tcl = self.interp
94 tcl.eval('set a(1) 1')
95 self.assertEqual(tcl.getvar('a(1)'),'1')
96
97 def testGetVarException(self):
98 tcl = self.interp
99 self.assertRaises(TclError,tcl.getvar,'a')
100
101 def testGetVarArrayException(self):
102 tcl = self.interp
103 self.assertRaises(TclError,tcl.getvar,'a(1)')
104
105 def testUnsetVar(self):
106 tcl = self.interp
107 tcl.setvar('a',1)
108 self.assertEqual(tcl.eval('info exists a'),'1')
109 tcl.unsetvar('a')
110 self.assertEqual(tcl.eval('info exists a'),'0')
111
112 def testUnsetVarArray(self):
113 tcl = self.interp
114 tcl.setvar('a(1)',1)
115 tcl.setvar('a(2)',2)
116 self.assertEqual(tcl.eval('info exists a(1)'),'1')
117 self.assertEqual(tcl.eval('info exists a(2)'),'1')
118 tcl.unsetvar('a(1)')
119 self.assertEqual(tcl.eval('info exists a(1)'),'0')
120 self.assertEqual(tcl.eval('info exists a(2)'),'1')
121
122 def testUnsetVarException(self):
123 tcl = self.interp
124 self.assertRaises(TclError,tcl.unsetvar,'a')
125
126 def get_integers(self):
127 return (0, 1, -1,
128 2**31-1, -2**31, 2**31, -2**31-1,
129 2**63-1, -2**63, 2**63, -2**63-1,
130 2**1000, -2**1000)
131
132 def test_getint(self):
133 tcl = self.interp.tk
134 for i in self.get_integers():
135 self.assertEqual(tcl.getint(' %d ' % i), i)
136 self.assertEqual(tcl.getint(' %#o ' % i), i)
137 # Numbers starting with 0 are parsed as decimal in Tcl 9.0
138 # and as octal in older versions.
139 self.assertEqual(tcl.getint((' %#o ' % i).replace('o', '')),
140 i if tcl_version < (9, 0) else int('%o' % i))
141 self.assertEqual(tcl.getint(' %#x ' % i), i)
142 self.assertEqual(tcl.getint(42), 42)
143 self.assertRaises(TypeError, tcl.getint)
144 self.assertRaises(TypeError, tcl.getint, '42', '10')
145 self.assertRaises(TypeError, tcl.getint, b'42')
146 self.assertRaises(TypeError, tcl.getint, 42.0)
147 self.assertRaises(TclError, tcl.getint, 'a')
148 self.assertRaises((TypeError, ValueError, TclError),
149 tcl.getint, '42\0')
150 self.assertRaises((UnicodeEncodeError, ValueError, TclError),
151 tcl.getint, '42\ud800')
152
153 def test_getdouble(self):
154 tcl = self.interp.tk
155 self.assertEqual(tcl.getdouble(' 42 '), 42.0)
156 self.assertEqual(tcl.getdouble(' 42.5 '), 42.5)
157 self.assertEqual(tcl.getdouble(42.5), 42.5)
158 self.assertEqual(tcl.getdouble(42), 42.0)
159 self.assertRaises(TypeError, tcl.getdouble)
160 self.assertRaises(TypeError, tcl.getdouble, '42.5', '10')
161 self.assertRaises(TypeError, tcl.getdouble, b'42.5')
162 self.assertRaises(TclError, tcl.getdouble, 'a')
163 self.assertRaises((TypeError, ValueError, TclError),
164 tcl.getdouble, '42.5\0')
165 self.assertRaises((UnicodeEncodeError, ValueError, TclError),
166 tcl.getdouble, '42.5\ud800')
167
168 def test_getboolean(self):
169 tcl = self.interp.tk
170 self.assertIs(tcl.getboolean('on'), True)
171 self.assertIs(tcl.getboolean('1'), True)
172 self.assertIs(tcl.getboolean(42), True)
173 self.assertIs(tcl.getboolean(0), False)
174 self.assertRaises(TypeError, tcl.getboolean)
175 self.assertRaises(TypeError, tcl.getboolean, 'on', '1')
176 self.assertRaises(TypeError, tcl.getboolean, b'on')
177 self.assertRaises(TypeError, tcl.getboolean, 1.0)
178 self.assertRaises(TclError, tcl.getboolean, 'a')
179 self.assertRaises((TypeError, ValueError, TclError),
180 tcl.getboolean, 'on\0')
181 self.assertRaises((UnicodeEncodeError, ValueError, TclError),
182 tcl.getboolean, 'on\ud800')
183
184 def testEvalFile(self):
185 tcl = self.interp
186 filename = os_helper.TESTFN_ASCII
187 self.addCleanup(os_helper.unlink, filename)
188 with open(filename, 'w') as f:
189 f.write("""set a 1
190 set b 2
191 set c [ expr $a + $b ]
192 """)
193 tcl.evalfile(filename)
194 self.assertEqual(tcl.eval('set a'),'1')
195 self.assertEqual(tcl.eval('set b'),'2')
196 self.assertEqual(tcl.eval('set c'),'3')
197
198 def test_evalfile_null_in_result(self):
199 tcl = self.interp
200 filename = os_helper.TESTFN_ASCII
201 self.addCleanup(os_helper.unlink, filename)
202 with open(filename, 'w') as f:
203 f.write("""
204 set a "a\0b"
205 set b "a\\0b"
206 """)
207 tcl.evalfile(filename)
208 self.assertEqual(tcl.eval('set a'), 'a\x00b')
209 self.assertEqual(tcl.eval('set b'), 'a\x00b')
210
211 def test_evalfile_surrogates_in_result(self):
212 tcl = self.interp
213 encoding = tcl.call('encoding', 'system')
214 self.addCleanup(tcl.call, 'encoding', 'system', encoding)
215 tcl.call('encoding', 'system', 'utf-8')
216
217 filename = os_helper.TESTFN_ASCII
218 self.addCleanup(os_helper.unlink, filename)
219 with open(filename, 'wb') as f:
220 f.write(b"""
221 set a "<\xed\xa0\xbd\xed\xb2\xbb>"
222 set b "<\\ud83d\\udcbb>"
223 """)
224 tcl.evalfile(filename)
225 self.assertEqual(tcl.eval('set a'), '<\U0001f4bb>')
226 self.assertEqual(tcl.eval('set b'), '<\U0001f4bb>')
227
228 def testEvalFileException(self):
229 tcl = self.interp
230 filename = "doesnotexists"
231 try:
232 os.remove(filename)
233 except Exception as e:
234 pass
235 self.assertRaises(TclError,tcl.evalfile,filename)
236
237 def testPackageRequireException(self):
238 tcl = self.interp
239 self.assertRaises(TclError,tcl.eval,'package require DNE')
240
241 @unittest.skipUnless(sys.platform == 'win32', 'Requires Windows')
242 def testLoadWithUNC(self):
243 # Build a UNC path from the regular path.
244 # Something like
245 # \\%COMPUTERNAME%\c$\python27\python.exe
246
247 fullname = os.path.abspath(sys.executable)
248 if fullname[1] != ':':
249 raise unittest.SkipTest('Absolute path should have drive part')
250 unc_name = r'\\%s\%s$\%s' % (os.environ['COMPUTERNAME'],
251 fullname[0],
252 fullname[3:])
253 if not os.path.exists(unc_name):
254 raise unittest.SkipTest('Cannot connect to UNC Path')
255
256 with os_helper.EnvironmentVarGuard() as env:
257 env.unset("TCL_LIBRARY")
258 stdout = subprocess.check_output(
259 [unc_name, '-c', 'import tkinter; print(tkinter)'])
260
261 self.assertIn(b'tkinter', stdout)
262
263 def test_exprstring(self):
264 tcl = self.interp
265 tcl.call('set', 'a', 3)
266 tcl.call('set', 'b', 6)
267 def check(expr, expected):
268 result = tcl.exprstring(expr)
269 self.assertEqual(result, expected)
270 self.assertIsInstance(result, str)
271
272 self.assertRaises(TypeError, tcl.exprstring)
273 self.assertRaises(TypeError, tcl.exprstring, '8.2', '+6')
274 self.assertRaises(TypeError, tcl.exprstring, b'8.2 + 6')
275 self.assertRaises(TclError, tcl.exprstring, 'spam')
276 check('', '0')
277 check('8.2 + 6', '14.2')
278 check('3.1 + $a', '6.1')
279 check('2 + "$a.$b"', '5.6')
280 check('4*[llength "6 2"]', '8')
281 check('{word one} < "word $a"', '0')
282 check('4*2 < 7', '0')
283 check('hypot($a, 4)', '5.0')
284 check('5 / 4', '1')
285 check('5 / 4.0', '1.25')
286 check('5 / ( [string length "abcd"] + 0.0 )', '1.25')
287 check('20.0/5.0', '4.0')
288 check('"0x03" > "2"', '1')
289 check('[string length "a\xbd\u20ac"]', '3')
290 check(r'[string length "a\xbd\u20ac"]', '3')
291 check('"abc"', 'abc')
292 check('"a\xbd\u20ac"', 'a\xbd\u20ac')
293 check(r'"a\xbd\u20ac"', 'a\xbd\u20ac')
294 check(r'"a\0b"', 'a\x00b')
295 check('2**64', str(2**64))
296
297 def test_exprdouble(self):
298 tcl = self.interp
299 tcl.call('set', 'a', 3)
300 tcl.call('set', 'b', 6)
301 def check(expr, expected):
302 result = tcl.exprdouble(expr)
303 self.assertEqual(result, expected)
304 self.assertIsInstance(result, float)
305
306 self.assertRaises(TypeError, tcl.exprdouble)
307 self.assertRaises(TypeError, tcl.exprdouble, '8.2', '+6')
308 self.assertRaises(TypeError, tcl.exprdouble, b'8.2 + 6')
309 self.assertRaises(TclError, tcl.exprdouble, 'spam')
310 check('', 0.0)
311 check('8.2 + 6', 14.2)
312 check('3.1 + $a', 6.1)
313 check('2 + "$a.$b"', 5.6)
314 check('4*[llength "6 2"]', 8.0)
315 check('{word one} < "word $a"', 0.0)
316 check('4*2 < 7', 0.0)
317 check('hypot($a, 4)', 5.0)
318 check('5 / 4', 1.0)
319 check('5 / 4.0', 1.25)
320 check('5 / ( [string length "abcd"] + 0.0 )', 1.25)
321 check('20.0/5.0', 4.0)
322 check('"0x03" > "2"', 1.0)
323 check('[string length "a\xbd\u20ac"]', 3.0)
324 check(r'[string length "a\xbd\u20ac"]', 3.0)
325 self.assertRaises(TclError, tcl.exprdouble, '"abc"')
326 check('2**64', float(2**64))
327
328 def test_exprlong(self):
329 tcl = self.interp
330 tcl.call('set', 'a', 3)
331 tcl.call('set', 'b', 6)
332 def check(expr, expected):
333 result = tcl.exprlong(expr)
334 self.assertEqual(result, expected)
335 self.assertIsInstance(result, int)
336
337 self.assertRaises(TypeError, tcl.exprlong)
338 self.assertRaises(TypeError, tcl.exprlong, '8.2', '+6')
339 self.assertRaises(TypeError, tcl.exprlong, b'8.2 + 6')
340 self.assertRaises(TclError, tcl.exprlong, 'spam')
341 check('', 0)
342 check('8.2 + 6', 14)
343 check('3.1 + $a', 6)
344 check('2 + "$a.$b"', 5)
345 check('4*[llength "6 2"]', 8)
346 check('{word one} < "word $a"', 0)
347 check('4*2 < 7', 0)
348 check('hypot($a, 4)', 5)
349 check('5 / 4', 1)
350 check('5 / 4.0', 1)
351 check('5 / ( [string length "abcd"] + 0.0 )', 1)
352 check('20.0/5.0', 4)
353 check('"0x03" > "2"', 1)
354 check('[string length "a\xbd\u20ac"]', 3)
355 check(r'[string length "a\xbd\u20ac"]', 3)
356 self.assertRaises(TclError, tcl.exprlong, '"abc"')
357 self.assertRaises(TclError, tcl.exprlong, '2**64')
358
359 def test_exprboolean(self):
360 tcl = self.interp
361 tcl.call('set', 'a', 3)
362 tcl.call('set', 'b', 6)
363 def check(expr, expected):
364 result = tcl.exprboolean(expr)
365 self.assertEqual(result, expected)
366 self.assertIsInstance(result, int)
367 self.assertNotIsInstance(result, bool)
368
369 self.assertRaises(TypeError, tcl.exprboolean)
370 self.assertRaises(TypeError, tcl.exprboolean, '8.2', '+6')
371 self.assertRaises(TypeError, tcl.exprboolean, b'8.2 + 6')
372 self.assertRaises(TclError, tcl.exprboolean, 'spam')
373 check('', False)
374 for value in ('0', 'false', 'no', 'off'):
375 check(value, False)
376 check('"%s"' % value, False)
377 check('{%s}' % value, False)
378 for value in ('1', 'true', 'yes', 'on'):
379 check(value, True)
380 check('"%s"' % value, True)
381 check('{%s}' % value, True)
382 check('8.2 + 6', True)
383 check('3.1 + $a', True)
384 check('2 + "$a.$b"', True)
385 check('4*[llength "6 2"]', True)
386 check('{word one} < "word $a"', False)
387 check('4*2 < 7', False)
388 check('hypot($a, 4)', True)
389 check('5 / 4', True)
390 check('5 / 4.0', True)
391 check('5 / ( [string length "abcd"] + 0.0 )', True)
392 check('20.0/5.0', True)
393 check('"0x03" > "2"', True)
394 check('[string length "a\xbd\u20ac"]', True)
395 check(r'[string length "a\xbd\u20ac"]', True)
396 self.assertRaises(TclError, tcl.exprboolean, '"abc"')
397 check('2**64', True)
398
399 def test_booleans(self):
400 tcl = self.interp
401 def check(expr, expected):
402 result = tcl.call('expr', expr)
403 if tcl.wantobjects():
404 self.assertEqual(result, expected)
405 self.assertIsInstance(result, int)
406 else:
407 self.assertIn(result, (expr, str(int(expected))))
408 self.assertIsInstance(result, str)
409 check('true', True)
410 check('yes', True)
411 check('on', True)
412 check('false', False)
413 check('no', False)
414 check('off', False)
415 check('1 < 2', True)
416 check('1 > 2', False)
417
418 def test_expr_bignum(self):
419 tcl = self.interp
420 for i in self.get_integers():
421 result = tcl.call('expr', str(i))
422 if self.wantobjects:
423 self.assertEqual(result, i)
424 self.assertIsInstance(result, int)
425 else:
426 self.assertEqual(result, str(i))
427 self.assertIsInstance(result, str)
428
429 def test_passing_values(self):
430 def passValue(value):
431 return self.interp.call('set', '_', value)
432
433 self.assertEqual(passValue(True), True if self.wantobjects else '1')
434 self.assertEqual(passValue(False), False if self.wantobjects else '0')
435 self.assertEqual(passValue('string'), 'string')
436 self.assertEqual(passValue('string\u20ac'), 'string\u20ac')
437 self.assertEqual(passValue('string\U0001f4bb'), 'string\U0001f4bb')
438 self.assertEqual(passValue('str\x00ing'), 'str\x00ing')
439 self.assertEqual(passValue('str\x00ing\xbd'), 'str\x00ing\xbd')
440 self.assertEqual(passValue('str\x00ing\u20ac'), 'str\x00ing\u20ac')
441 self.assertEqual(passValue('str\x00ing\U0001f4bb'),
442 'str\x00ing\U0001f4bb')
443 if sys.platform != 'win32':
444 self.assertEqual(passValue('<\udce2\udc82\udcac>'),
445 '<\u20ac>')
446 self.assertEqual(passValue('<\udced\udca0\udcbd\udced\udcb2\udcbb>'),
447 '<\U0001f4bb>')
448 self.assertEqual(passValue(b'str\x00ing'),
449 b'str\x00ing' if self.wantobjects else 'str\x00ing')
450 self.assertEqual(passValue(b'str\xc0\x80ing'),
451 b'str\xc0\x80ing' if self.wantobjects else 'str\xc0\x80ing')
452 self.assertEqual(passValue(b'str\xbding'),
453 b'str\xbding' if self.wantobjects else 'str\xbding')
454 for i in self.get_integers():
455 self.assertEqual(passValue(i), i if self.wantobjects else str(i))
456 for f in (0.0, 1.0, -1.0, 1/3,
457 sys.float_info.min, sys.float_info.max,
458 -sys.float_info.min, -sys.float_info.max):
459 if self.wantobjects:
460 self.assertEqual(passValue(f), f)
461 else:
462 self.assertEqual(float(passValue(f)), f)
463 if self.wantobjects:
464 f = passValue(float('nan'))
465 self.assertNotEqual(f, f)
466 self.assertEqual(passValue(float('inf')), float('inf'))
467 self.assertEqual(passValue(-float('inf')), -float('inf'))
468 else:
469 self.assertEqual(float(passValue(float('inf'))), float('inf'))
470 self.assertEqual(float(passValue(-float('inf'))), -float('inf'))
471 # XXX NaN representation can be not parsable by float()
472 self.assertEqual(passValue((1, '2', (3.4,))),
473 (1, '2', (3.4,)) if self.wantobjects else '1 2 3.4')
474 self.assertEqual(passValue(['a', ['b', 'c']]),
475 ('a', ('b', 'c')) if self.wantobjects else 'a {b c}')
476
477 def test_user_command(self):
478 result = None
479 def testfunc(arg):
480 nonlocal result
481 result = arg
482 return arg
483 self.interp.createcommand('testfunc', testfunc)
484 self.addCleanup(self.interp.tk.deletecommand, 'testfunc')
485 def check(value, expected=None, *, eq=self.assertEqual):
486 if expected is None:
487 expected = value
488 nonlocal result
489 result = None
490 r = self.interp.call('testfunc', value)
491 self.assertIsInstance(result, str)
492 eq(result, expected)
493 self.assertIsInstance(r, str)
494 eq(r, expected)
495 def float_eq(actual, expected):
496 self.assertAlmostEqual(float(actual), expected,
497 delta=abs(expected) * 1e-10)
498
499 check(True, '1')
500 check(False, '0')
501 check('string')
502 check('string\xbd')
503 check('string\u20ac')
504 check('string\U0001f4bb')
505 if sys.platform != 'win32':
506 check('<\udce2\udc82\udcac>', '<\u20ac>')
507 check('<\udced\udca0\udcbd\udced\udcb2\udcbb>', '<\U0001f4bb>')
508 check('')
509 check(b'string', 'string')
510 check(b'string\xe2\x82\xac', 'string\xe2\x82\xac')
511 check(b'string\xbd', 'string\xbd')
512 check(b'', '')
513 check('str\x00ing')
514 check('str\x00ing\xbd')
515 check('str\x00ing\u20ac')
516 check(b'str\x00ing', 'str\x00ing')
517 check(b'str\xc0\x80ing', 'str\xc0\x80ing')
518 check(b'str\xc0\x80ing\xe2\x82\xac', 'str\xc0\x80ing\xe2\x82\xac')
519 for i in self.get_integers():
520 check(i, str(i))
521 for f in (0.0, 1.0, -1.0):
522 check(f, repr(f))
523 for f in (1/3.0, sys.float_info.min, sys.float_info.max,
524 -sys.float_info.min, -sys.float_info.max):
525 check(f, eq=float_eq)
526 check(float('inf'), eq=float_eq)
527 check(-float('inf'), eq=float_eq)
528 # XXX NaN representation can be not parsable by float()
529 check((), '')
530 check((1, (2,), (3, 4), '5 6', ()), '1 2 {3 4} {5 6} {}')
531 check([1, [2,], [3, 4], '5 6', []], '1 2 {3 4} {5 6} {}')
532
533 def test_splitlist(self):
534 splitlist = self.interp.tk.splitlist
535 call = self.interp.tk.call
536 self.assertRaises(TypeError, splitlist)
537 self.assertRaises(TypeError, splitlist, 'a', 'b')
538 self.assertRaises(TypeError, splitlist, 2)
539 testcases = [
540 ('2', ('2',)),
541 ('', ()),
542 ('{}', ('',)),
543 ('""', ('',)),
544 ('a\n b\t\r c\n ', ('a', 'b', 'c')),
545 (b'a\n b\t\r c\n ', ('a', 'b', 'c')),
546 ('a \u20ac', ('a', '\u20ac')),
547 ('a \U0001f4bb', ('a', '\U0001f4bb')),
548 (b'a \xe2\x82\xac', ('a', '\u20ac')),
549 (b'a \xf0\x9f\x92\xbb', ('a', '\U0001f4bb')),
550 (b'a \xed\xa0\xbd\xed\xb2\xbb', ('a', '\U0001f4bb')),
551 (b'a\xc0\x80b c\xc0\x80d', ('a\x00b', 'c\x00d')),
552 ('a {b c}', ('a', 'b c')),
553 (r'a b\ c', ('a', 'b c')),
554 (('a', 'b c'), ('a', 'b c')),
555 ('a 2', ('a', '2')),
556 (('a', 2), ('a', 2)),
557 ('a 3.4', ('a', '3.4')),
558 (('a', 3.4), ('a', 3.4)),
559 ((), ()),
560 ([], ()),
561 (['a', ['b', 'c']], ('a', ['b', 'c'])),
562 (call('list', 1, '2', (3.4,)),
563 (1, '2', (3.4,)) if self.wantobjects else
564 ('1', '2', '3.4')),
565 ]
566 if not self.wantobjects:
567 expected = ('12', '\u20ac', '\xe2\x82\xac', '3.4')
568 else:
569 expected = (12, '\u20ac', b'\xe2\x82\xac', (3.4,))
570 testcases += [
571 (call('dict', 'create', 12, '\u20ac', b'\xe2\x82\xac', (3.4,)),
572 expected),
573 ]
574 dbg_info = ('want objects? %s, Tcl version: %s, Tcl patchlevel: %s'
575 % (self.wantobjects, tcl_version, self.interp.info_patchlevel()))
576 for arg, res in testcases:
577 self.assertEqual(splitlist(arg), res,
578 'arg=%a, %s' % (arg, dbg_info))
579 self.assertRaises(TclError, splitlist, '{')
580
581 def test_splitdict(self):
582 splitdict = tkinter._splitdict
583 tcl = self.interp.tk
584
585 arg = '-a {1 2 3} -something foo status {}'
586 self.assertEqual(splitdict(tcl, arg, False),
587 {'-a': '1 2 3', '-something': 'foo', 'status': ''})
588 self.assertEqual(splitdict(tcl, arg),
589 {'a': '1 2 3', 'something': 'foo', 'status': ''})
590
591 arg = ('-a', (1, 2, 3), '-something', 'foo', 'status', '{}')
592 self.assertEqual(splitdict(tcl, arg, False),
593 {'-a': (1, 2, 3), '-something': 'foo', 'status': '{}'})
594 self.assertEqual(splitdict(tcl, arg),
595 {'a': (1, 2, 3), 'something': 'foo', 'status': '{}'})
596
597 self.assertRaises(RuntimeError, splitdict, tcl, '-a b -c ')
598 self.assertRaises(RuntimeError, splitdict, tcl, ('-a', 'b', '-c'))
599
600 arg = tcl.call('list',
601 '-a', (1, 2, 3), '-something', 'foo', 'status', ())
602 self.assertEqual(splitdict(tcl, arg),
603 {'a': (1, 2, 3) if self.wantobjects else '1 2 3',
604 'something': 'foo', 'status': ''})
605
606 arg = tcl.call('dict', 'create',
607 '-a', (1, 2, 3), '-something', 'foo', 'status', ())
608 if not self.wantobjects:
609 expected = {'a': '1 2 3', 'something': 'foo', 'status': ''}
610 else:
611 expected = {'a': (1, 2, 3), 'something': 'foo', 'status': ''}
612 self.assertEqual(splitdict(tcl, arg), expected)
613
614 def test_join(self):
615 join = tkinter._join
616 tcl = self.interp.tk
617 def unpack(s):
618 return tcl.call('lindex', s, 0)
619 def check(value):
620 self.assertEqual(unpack(join([value])), value)
621 self.assertEqual(unpack(join([value, 0])), value)
622 self.assertEqual(unpack(unpack(join([[value]]))), value)
623 self.assertEqual(unpack(unpack(join([[value, 0]]))), value)
624 self.assertEqual(unpack(unpack(join([[value], 0]))), value)
625 self.assertEqual(unpack(unpack(join([[value, 0], 0]))), value)
626 check('')
627 check('spam')
628 check('sp am')
629 check('sp\tam')
630 check('sp\nam')
631 check(' \t\n')
632 check('{spam}')
633 check('{sp am}')
634 check('"spam"')
635 check('"sp am"')
636 check('{"spam"}')
637 check('"{spam}"')
638 check('sp\\am')
639 check('"sp\\am"')
640 check('"{}" "{}"')
641 check('"\\')
642 check('"{')
643 check('"}')
644 check('\n\\')
645 check('\n{')
646 check('\n}')
647 check('\\\n')
648 check('{\n')
649 check('}\n')
650
651 @support.cpython_only
652 def test_new_tcl_obj(self):
653 support.check_disallow_instantiation(self, _tkinter.Tcl_Obj)
654 support.check_disallow_instantiation(self, _tkinter.TkttType)
655 support.check_disallow_instantiation(self, _tkinter.TkappType)
656
657 class ESC[4;38;5;81mBigmemTclTest(ESC[4;38;5;149munittestESC[4;38;5;149m.ESC[4;38;5;149mTestCase):
658
659 def setUp(self):
660 self.interp = Tcl()
661
662 @support.cpython_only
663 @unittest.skipUnless(INT_MAX < PY_SSIZE_T_MAX, "needs UINT_MAX < SIZE_MAX")
664 @support.bigmemtest(size=INT_MAX + 1, memuse=5, dry_run=False)
665 def test_huge_string_call(self, size):
666 value = ' ' * size
667 self.assertRaises(OverflowError, self.interp.call, 'string', 'index', value, 0)
668
669 @support.cpython_only
670 @unittest.skipUnless(INT_MAX < PY_SSIZE_T_MAX, "needs UINT_MAX < SIZE_MAX")
671 @support.bigmemtest(size=INT_MAX + 1, memuse=2, dry_run=False)
672 def test_huge_string_builtins(self, size):
673 tk = self.interp.tk
674 value = '1' + ' ' * size
675 self.assertRaises(OverflowError, tk.getint, value)
676 self.assertRaises(OverflowError, tk.getdouble, value)
677 self.assertRaises(OverflowError, tk.getboolean, value)
678 self.assertRaises(OverflowError, tk.eval, value)
679 self.assertRaises(OverflowError, tk.evalfile, value)
680 self.assertRaises(OverflowError, tk.record, value)
681 self.assertRaises(OverflowError, tk.adderrorinfo, value)
682 self.assertRaises(OverflowError, tk.setvar, value, 'x', 'a')
683 self.assertRaises(OverflowError, tk.setvar, 'x', value, 'a')
684 self.assertRaises(OverflowError, tk.unsetvar, value)
685 self.assertRaises(OverflowError, tk.unsetvar, 'x', value)
686 self.assertRaises(OverflowError, tk.adderrorinfo, value)
687 self.assertRaises(OverflowError, tk.exprstring, value)
688 self.assertRaises(OverflowError, tk.exprlong, value)
689 self.assertRaises(OverflowError, tk.exprboolean, value)
690 self.assertRaises(OverflowError, tk.splitlist, value)
691 self.assertRaises(OverflowError, tk.createcommand, value, max)
692 self.assertRaises(OverflowError, tk.deletecommand, value)
693
694 @support.cpython_only
695 @unittest.skipUnless(INT_MAX < PY_SSIZE_T_MAX, "needs UINT_MAX < SIZE_MAX")
696 @support.bigmemtest(size=INT_MAX + 1, memuse=6, dry_run=False)
697 def test_huge_string_builtins2(self, size):
698 # These commands require larger memory for possible error messages
699 tk = self.interp.tk
700 value = '1' + ' ' * size
701 self.assertRaises(OverflowError, tk.evalfile, value)
702 self.assertRaises(OverflowError, tk.unsetvar, value)
703 self.assertRaises(OverflowError, tk.unsetvar, 'x', value)
704
705
706 def setUpModule():
707 if support.verbose:
708 tcl = Tcl()
709 print('patchlevel =', tcl.call('info', 'patchlevel'), flush=True)
710
711
712 if __name__ == "__main__":
713 unittest.main()