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