• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1import unittest
2import re
3import sys
4import os
5from test import test_support
6from subprocess import Popen, PIPE
7
8# Skip this test if the _tkinter module wasn't built.
9_tkinter = test_support.import_module('_tkinter')
10
11import Tkinter as tkinter
12from Tkinter import Tcl
13from _tkinter import TclError
14
15try:
16    from _testcapi import INT_MAX, PY_SSIZE_T_MAX
17except ImportError:
18    INT_MAX = PY_SSIZE_T_MAX = sys.maxsize
19
20tcl_version = tuple(map(int, _tkinter.TCL_VERSION.split('.')))
21
22_tk_patchlevel = None
23def get_tk_patchlevel():
24    global _tk_patchlevel
25    if _tk_patchlevel is None:
26        tcl = Tcl()
27        patchlevel = tcl.call('info', 'patchlevel')
28        m = re.match(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
36    return _tk_patchlevel
37
38
39class TkinterTest(unittest.TestCase):
40
41    def testFlattenLen(self):
42        # flatten(<object with no length>)
43        self.assertRaises(TypeError, _tkinter._flatten, True)
44
45
46class TclTest(unittest.TestCase):
47
48    def setUp(self):
49        self.interp = Tcl()
50        self.wantobjects = self.interp.tk.wantobjects()
51
52    def testEval(self):
53        tcl = self.interp
54        tcl.eval('set a 1')
55        self.assertEqual(tcl.eval('set a'),'1')
56
57    def testEvalException(self):
58        tcl = self.interp
59        self.assertRaises(TclError,tcl.eval,'set a')
60
61    def testEvalException2(self):
62        tcl = self.interp
63        self.assertRaises(TclError,tcl.eval,'this is wrong')
64
65    def testCall(self):
66        tcl = self.interp
67        tcl.call('set','a','1')
68        self.assertEqual(tcl.call('set','a'),'1')
69
70    def testCallException(self):
71        tcl = self.interp
72        self.assertRaises(TclError,tcl.call,'set','a')
73
74    def testCallException2(self):
75        tcl = self.interp
76        self.assertRaises(TclError,tcl.call,'this','is','wrong')
77
78    def testSetVar(self):
79        tcl = self.interp
80        tcl.setvar('a','1')
81        self.assertEqual(tcl.eval('set a'),'1')
82
83    def testSetVarArray(self):
84        tcl = self.interp
85        tcl.setvar('a(1)','1')
86        self.assertEqual(tcl.eval('set a(1)'),'1')
87
88    def testGetVar(self):
89        tcl = self.interp
90        tcl.eval('set a 1')
91        self.assertEqual(tcl.getvar('a'),'1')
92
93    def testGetVarArray(self):
94        tcl = self.interp
95        tcl.eval('set a(1) 1')
96        self.assertEqual(tcl.getvar('a(1)'),'1')
97
98    def testGetVarException(self):
99        tcl = self.interp
100        self.assertRaises(TclError,tcl.getvar,'a')
101
102    def testGetVarArrayException(self):
103        tcl = self.interp
104        self.assertRaises(TclError,tcl.getvar,'a(1)')
105
106    def testUnsetVar(self):
107        tcl = self.interp
108        tcl.setvar('a',1)
109        self.assertEqual(tcl.eval('info exists a'),'1')
110        tcl.unsetvar('a')
111        self.assertEqual(tcl.eval('info exists a'),'0')
112
113    def testUnsetVarArray(self):
114        tcl = self.interp
115        tcl.setvar('a(1)',1)
116        tcl.setvar('a(2)',2)
117        self.assertEqual(tcl.eval('info exists a(1)'),'1')
118        self.assertEqual(tcl.eval('info exists a(2)'),'1')
119        tcl.unsetvar('a(1)')
120        self.assertEqual(tcl.eval('info exists a(1)'),'0')
121        self.assertEqual(tcl.eval('info exists a(2)'),'1')
122
123    def testUnsetVarException(self):
124        tcl = self.interp
125        self.assertRaises(TclError,tcl.unsetvar,'a')
126
127    def get_integers(self):
128        integers = (0, 1, -1, 2**31-1, -2**31)
129        if tcl_version >= (8, 4):  # wideInt was added in Tcl 8.4
130            integers += (2**31, -2**31-1, 2**63-1, -2**63)
131        # bignum was added in Tcl 8.5, but its support is able only since 8.5.8
132        if (get_tk_patchlevel() >= (8, 6, 0, 'final') or
133            (8, 5, 8) <= get_tk_patchlevel() < (8, 6)):
134            integers += (2**63, -2**63-1, 2**1000, -2**1000)
135        return integers
136
137    def test_getint(self):
138        tcl = self.interp.tk
139        for i in self.get_integers():
140            result = tcl.getint(' %d ' % i)
141            self.assertEqual(result, i)
142            self.assertIsInstance(result, type(int(result)))
143            if tcl_version >= (8, 5):
144                self.assertEqual(tcl.getint(' {:#o} '.format(i)), i)
145            self.assertEqual(tcl.getint(' %#o ' % i), i)
146            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))
149        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, 42.0)
153        self.assertRaises(TclError, tcl.getint, 'a')
154        self.assertRaises((TypeError, ValueError, TclError),
155                          tcl.getint, '42\0')
156        if test_support.have_unicode:
157            self.assertEqual(tcl.getint(unicode('42')), 42)
158            self.assertRaises((UnicodeEncodeError, ValueError, TclError),
159                              tcl.getint, '42' + unichr(0xd800))
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)
166        self.assertRaises(TypeError, tcl.getdouble)
167        self.assertRaises(TypeError, tcl.getdouble, '42.5', '10')
168        self.assertRaises(TypeError, tcl.getdouble, 42)
169        self.assertRaises(TclError, tcl.getdouble, 'a')
170        self.assertRaises((TypeError, ValueError, TclError),
171                          tcl.getdouble, '42.5\0')
172        if test_support.have_unicode:
173            self.assertEqual(tcl.getdouble(unicode('42.5')), 42.5)
174            self.assertRaises((UnicodeEncodeError, ValueError, TclError),
175                              tcl.getdouble, '42.5' + unichr(0xd800))
176
177    def test_getboolean(self):
178        tcl = self.interp.tk
179        self.assertIs(tcl.getboolean('on'), True)
180        self.assertIs(tcl.getboolean('1'), True)
181        self.assertIs(tcl.getboolean(u'on'), True)
182        self.assertIs(tcl.getboolean(u'1'), True)
183        self.assertIs(tcl.getboolean(42), True)
184        self.assertIs(tcl.getboolean(0), False)
185        self.assertIs(tcl.getboolean(42L), True)
186        self.assertIs(tcl.getboolean(0L), False)
187        self.assertRaises(TypeError, tcl.getboolean)
188        self.assertRaises(TypeError, tcl.getboolean, 'on', '1')
189        self.assertRaises(TypeError, tcl.getboolean, 1.0)
190        self.assertRaises(TclError, tcl.getboolean, 'a')
191        self.assertRaises((TypeError, ValueError, TclError),
192                          tcl.getboolean, 'on\0')
193        if test_support.have_unicode:
194            self.assertIs(tcl.getboolean(unicode('on')), True)
195            self.assertRaises((UnicodeEncodeError, ValueError, TclError),
196                              tcl.getboolean, 'on' + unichr(0xd800))
197
198    def testEvalFile(self):
199        tcl = self.interp
200        filename = "testEvalFile.tcl"
201        fd = open(filename,'w')
202        script = """set a 1
203        set b 2
204        set c [ expr $a + $b ]
205        """
206        fd.write(script)
207        fd.close()
208        tcl.evalfile(filename)
209        os.remove(filename)
210        self.assertEqual(tcl.eval('set a'),'1')
211        self.assertEqual(tcl.eval('set b'),'2')
212        self.assertEqual(tcl.eval('set c'),'3')
213
214    def test_evalfile_null_in_result(self):
215        tcl = self.interp
216        with open(test_support.TESTFN, 'wb') as f:
217            self.addCleanup(test_support.unlink, test_support.TESTFN)
218            f.write("""
219            set a "a\0b"
220            set b "a\\0b"
221            """)
222        tcl.evalfile(test_support.TESTFN)
223        self.assertEqual(tcl.eval('set a'), 'a\xc0\x80b')
224        self.assertEqual(tcl.eval('set b'), 'a\xc0\x80b')
225
226    def testEvalFileException(self):
227        tcl = self.interp
228        filename = "doesnotexists"
229        try:
230            os.remove(filename)
231        except Exception,e:
232            pass
233        self.assertRaises(TclError,tcl.evalfile,filename)
234
235    def testPackageRequireException(self):
236        tcl = self.interp
237        self.assertRaises(TclError,tcl.eval,'package require DNE')
238
239    @unittest.skipUnless(sys.platform == 'win32', "only applies to Windows")
240    def testLoadWithUNC(self):
241        # Build a UNC path from the regular path.
242        # Something like
243        #   \\%COMPUTERNAME%\c$\python27\python.exe
244
245        fullname = os.path.abspath(sys.executable)
246        if fullname[1] != ':':
247            self.skipTest('unusable path: %r' % fullname)
248        unc_name = r'\\%s\%s$\%s' % (os.environ['COMPUTERNAME'],
249                                    fullname[0],
250                                    fullname[3:])
251
252        with test_support.EnvironmentVarGuard() as env:
253            env.unset("TCL_LIBRARY")
254            cmd = '%s -c "import Tkinter; print Tkinter"' % (unc_name,)
255
256            try:
257                p = Popen(cmd, stdout=PIPE, stderr=PIPE)
258            except WindowsError as e:
259                if e.winerror == 5 or e.winerror == 2:
260                    self.skipTest('Not permitted to start the child process')
261                else:
262                    raise
263
264            out_data, err_data = p.communicate()
265
266            msg = '\n\n'.join(['"Tkinter.py" not in output',
267                               'Command:', cmd,
268                               'stdout:', out_data,
269                               'stderr:', err_data])
270
271            self.assertIn('Tkinter.py', out_data, msg)
272
273            self.assertEqual(p.wait(), 0, 'Non-zero exit code')
274
275
276    def test_exprstring(self):
277        tcl = self.interp
278        tcl.call('set', 'a', 3)
279        tcl.call('set', 'b', 6)
280        def check(expr, expected):
281            result = tcl.exprstring(expr)
282            self.assertEqual(result, expected)
283            self.assertIsInstance(result, str)
284
285        self.assertRaises(TypeError, tcl.exprstring)
286        self.assertRaises(TypeError, tcl.exprstring, '8.2', '+6')
287        self.assertRaises(TclError, tcl.exprstring, 'spam')
288        check('', '0')
289        check('8.2 + 6', '14.2')
290        check('3.1 + $a', '6.1')
291        check('2 + "$a.$b"', '5.6')
292        check('4*[llength "6 2"]', '8')
293        check('{word one} < "word $a"', '0')
294        check('4*2 < 7', '0')
295        check('hypot($a, 4)', '5.0')
296        check('5 / 4', '1')
297        check('5 / 4.0', '1.25')
298        check('5 / ( [string length "abcd"] + 0.0 )', '1.25')
299        check('20.0/5.0', '4.0')
300        check('"0x03" > "2"', '1')
301        check('[string length "a\xc2\xbd\xe2\x82\xac"]', '3')
302        check(r'[string length "a\xbd\u20ac"]', '3')
303        check('"abc"', 'abc')
304        check('"a\xc2\xbd\xe2\x82\xac"', 'a\xc2\xbd\xe2\x82\xac')
305        check(r'"a\xbd\u20ac"', 'a\xc2\xbd\xe2\x82\xac')
306        check(r'"a\0b"', 'a\xc0\x80b')
307        if tcl_version >= (8, 5):  # bignum was added in Tcl 8.5
308            check('2**64', str(2**64))
309
310    def test_exprdouble(self):
311        tcl = self.interp
312        tcl.call('set', 'a', 3)
313        tcl.call('set', 'b', 6)
314        def check(expr, expected):
315            result = tcl.exprdouble(expr)
316            self.assertEqual(result, expected)
317            self.assertIsInstance(result, float)
318
319        self.assertRaises(TypeError, tcl.exprdouble)
320        self.assertRaises(TypeError, tcl.exprdouble, '8.2', '+6')
321        self.assertRaises(TclError, tcl.exprdouble, 'spam')
322        check('', 0.0)
323        check('8.2 + 6', 14.2)
324        check('3.1 + $a', 6.1)
325        check('2 + "$a.$b"', 5.6)
326        check('4*[llength "6 2"]', 8.0)
327        check('{word one} < "word $a"', 0.0)
328        check('4*2 < 7', 0.0)
329        check('hypot($a, 4)', 5.0)
330        check('5 / 4', 1.0)
331        check('5 / 4.0', 1.25)
332        check('5 / ( [string length "abcd"] + 0.0 )', 1.25)
333        check('20.0/5.0', 4.0)
334        check('"0x03" > "2"', 1.0)
335        check('[string length "a\xc2\xbd\xe2\x82\xac"]', 3.0)
336        check(r'[string length "a\xbd\u20ac"]', 3.0)
337        self.assertRaises(TclError, tcl.exprdouble, '"abc"')
338        if tcl_version >= (8, 5):  # bignum was added in Tcl 8.5
339            check('2**64', float(2**64))
340
341    def test_exprlong(self):
342        tcl = self.interp
343        tcl.call('set', 'a', 3)
344        tcl.call('set', 'b', 6)
345        def check(expr, expected):
346            result = tcl.exprlong(expr)
347            self.assertEqual(result, expected)
348            self.assertIsInstance(result, int)
349
350        self.assertRaises(TypeError, tcl.exprlong)
351        self.assertRaises(TypeError, tcl.exprlong, '8.2', '+6')
352        self.assertRaises(TclError, tcl.exprlong, 'spam')
353        check('', 0)
354        check('8.2 + 6', 14)
355        check('3.1 + $a', 6)
356        check('2 + "$a.$b"', 5)
357        check('4*[llength "6 2"]', 8)
358        check('{word one} < "word $a"', 0)
359        check('4*2 < 7', 0)
360        check('hypot($a, 4)', 5)
361        check('5 / 4', 1)
362        check('5 / 4.0', 1)
363        check('5 / ( [string length "abcd"] + 0.0 )', 1)
364        check('20.0/5.0', 4)
365        check('"0x03" > "2"', 1)
366        check('[string length "a\xc2\xbd\xe2\x82\xac"]', 3)
367        check(r'[string length "a\xbd\u20ac"]', 3)
368        self.assertRaises(TclError, tcl.exprlong, '"abc"')
369        if tcl_version >= (8, 5):  # bignum was added in Tcl 8.5
370            self.assertRaises(TclError, tcl.exprlong, '2**64')
371
372    def test_exprboolean(self):
373        tcl = self.interp
374        tcl.call('set', 'a', 3)
375        tcl.call('set', 'b', 6)
376        def check(expr, expected):
377            result = tcl.exprboolean(expr)
378            self.assertEqual(result, expected)
379            self.assertIsInstance(result, int)
380            self.assertNotIsInstance(result, bool)
381
382        self.assertRaises(TypeError, tcl.exprboolean)
383        self.assertRaises(TypeError, tcl.exprboolean, '8.2', '+6')
384        self.assertRaises(TclError, tcl.exprboolean, 'spam')
385        check('', False)
386        for value in ('0', 'false', 'no', 'off'):
387            check(value, False)
388            check('"%s"' % value, False)
389            check('{%s}' % value, False)
390        for value in ('1', 'true', 'yes', 'on'):
391            check(value, True)
392            check('"%s"' % value, True)
393            check('{%s}' % value, True)
394        check('8.2 + 6', True)
395        check('3.1 + $a', True)
396        check('2 + "$a.$b"', True)
397        check('4*[llength "6 2"]', True)
398        check('{word one} < "word $a"', False)
399        check('4*2 < 7', False)
400        check('hypot($a, 4)', True)
401        check('5 / 4', True)
402        check('5 / 4.0', True)
403        check('5 / ( [string length "abcd"] + 0.0 )', True)
404        check('20.0/5.0', True)
405        check('"0x03" > "2"', True)
406        check('[string length "a\xc2\xbd\xe2\x82\xac"]', True)
407        check(r'[string length "a\xbd\u20ac"]', True)
408        self.assertRaises(TclError, tcl.exprboolean, '"abc"')
409        if tcl_version >= (8, 5):  # bignum was added in Tcl 8.5
410            check('2**64', True)
411
412    @unittest.skipUnless(tcl_version >= (8, 5), 'requires Tcl version >= 8.5')
413    def test_booleans(self):
414        tcl = self.interp
415        def check(expr, expected):
416            result = tcl.call('expr', expr)
417            if tcl.wantobjects():
418                self.assertEqual(result, expected)
419                self.assertIsInstance(result, int)
420            else:
421                self.assertIn(result, (expr, str(int(expected))))
422                self.assertIsInstance(result, str)
423        check('true', True)
424        check('yes', True)
425        check('on', True)
426        check('false', False)
427        check('no', False)
428        check('off', False)
429        check('1 < 2', True)
430        check('1 > 2', False)
431
432    def test_expr_bignum(self):
433        tcl = self.interp
434        for i in self.get_integers():
435            result = tcl.call('expr', str(i))
436            if self.wantobjects:
437                self.assertEqual(result, i)
438                self.assertIsInstance(result, (int, long))
439                if abs(result) < 2**31:
440                    self.assertIsInstance(result, int)
441            else:
442                self.assertEqual(result, str(i))
443                self.assertIsInstance(result, str)
444        if tcl_version < (8, 5):  # bignum was added in Tcl 8.5
445            self.assertRaises(TclError, tcl.call, 'expr', str(2**1000))
446
447    def test_passing_values(self):
448        def passValue(value):
449            return self.interp.call('set', '_', value)
450
451        self.assertEqual(passValue(True), True if self.wantobjects else '1')
452        self.assertEqual(passValue(False), False if self.wantobjects else '0')
453        self.assertEqual(passValue('string'), 'string')
454        self.assertEqual(passValue('string\xbd'), 'string\xbd')
455        self.assertEqual(passValue('string\xe2\x82\xac'), u'string\u20ac')
456        self.assertEqual(passValue(u'string'), u'string')
457        self.assertEqual(passValue(u'string\xbd'), u'string\xbd')
458        self.assertEqual(passValue(u'string\u20ac'), u'string\u20ac')
459        self.assertEqual(passValue('str\x00ing'), 'str\x00ing')
460        self.assertEqual(passValue('str\xc0\x80ing'), 'str\x00ing')
461        self.assertEqual(passValue(u'str\x00ing'), u'str\x00ing')
462        self.assertEqual(passValue(u'str\x00ing\xbd'), u'str\x00ing\xbd')
463        self.assertEqual(passValue(u'str\x00ing\u20ac'), u'str\x00ing\u20ac')
464        for i in self.get_integers():
465            self.assertEqual(passValue(i), i if self.wantobjects else str(i))
466        if tcl_version < (8, 5):  # bignum was added in Tcl 8.5
467            self.assertEqual(passValue(2**1000), str(2**1000))
468        for f in (0.0, 1.0, -1.0, 1//3, 1/3.0,
469                  sys.float_info.min, sys.float_info.max,
470                  -sys.float_info.min, -sys.float_info.max):
471            if self.wantobjects:
472                self.assertEqual(passValue(f), f)
473            else:
474                self.assertEqual(float(passValue(f)), f)
475        if self.wantobjects:
476            f = passValue(float('nan'))
477            self.assertNotEqual(f, f)
478            self.assertEqual(passValue(float('inf')), float('inf'))
479            self.assertEqual(passValue(-float('inf')), -float('inf'))
480        else:
481            self.assertEqual(float(passValue(float('inf'))), float('inf'))
482            self.assertEqual(float(passValue(-float('inf'))), -float('inf'))
483            # XXX NaN representation can be not parsable by float()
484        self.assertEqual(passValue((1, '2', (3.4,))),
485                         (1, '2', (3.4,)) if self.wantobjects else '1 2 3.4')
486
487    def test_user_command(self):
488        result = []
489        def testfunc(arg):
490            result.append(arg)
491            return arg
492        self.interp.createcommand('testfunc', testfunc)
493        self.addCleanup(self.interp.tk.deletecommand, 'testfunc')
494        def check(value, expected=None, eq=self.assertEqual):
495            if expected is None:
496                expected = value
497            del result[:]
498            r = self.interp.call('testfunc', value)
499            self.assertEqual(len(result), 1)
500            self.assertIsInstance(result[0], (str, unicode))
501            eq(result[0], expected)
502            self.assertIsInstance(r, (str, unicode))
503            eq(r, expected)
504        def float_eq(actual, expected):
505            self.assertAlmostEqual(float(actual), expected,
506                                   delta=abs(expected) * 1e-10)
507
508        check(True, '1')
509        check(False, '0')
510        check('string')
511        check('string\xbd')
512        check('string\xe2\x82\xac', u'string\u20ac')
513        check('')
514        check(u'string')
515        check(u'string\xbd')
516        check(u'string\u20ac')
517        check(u'')
518        check('str\xc0\x80ing', u'str\x00ing')
519        check('str\xc0\x80ing\xe2\x82\xac', u'str\x00ing\u20ac')
520        check(u'str\x00ing')
521        check(u'str\x00ing\xbd')
522        check(u'str\x00ing\u20ac')
523        for i in self.get_integers():
524            check(i, str(i))
525        if tcl_version < (8, 5):  # bignum was added in Tcl 8.5
526            check(2**1000, str(2**1000))
527        for f in (0.0, 1.0, -1.0):
528            check(f, repr(f))
529        for f in (1/3.0, sys.float_info.min, sys.float_info.max,
530                  -sys.float_info.min, -sys.float_info.max):
531            check(f, eq=float_eq)
532        check(float('inf'), eq=float_eq)
533        check(-float('inf'), eq=float_eq)
534        # XXX NaN representation can be not parsable by float()
535        check((), '')
536        check((1, (2,), (3, 4), '5 6', ()), '1 2 {3 4} {5 6} {}')
537
538    def test_splitlist(self):
539        splitlist = self.interp.tk.splitlist
540        call = self.interp.tk.call
541        self.assertRaises(TypeError, splitlist)
542        self.assertRaises(TypeError, splitlist, 'a', 'b')
543        self.assertRaises(TypeError, splitlist, 2)
544        testcases = [
545            ('2', ('2',)),
546            ('', ()),
547            ('{}', ('',)),
548            ('""', ('',)),
549            ('a\n b\t\r c\n ', ('a', 'b', 'c')),
550            (u'a\n b\t\r c\n ', ('a', 'b', 'c')),
551            ('a \xe2\x82\xac', ('a', '\xe2\x82\xac')),
552            (u'a \u20ac', ('a', '\xe2\x82\xac')),
553            ('a\xc0\x80b c\xc0\x80d', ('a\xc0\x80b', 'c\xc0\x80d')),
554            ('a {b c}', ('a', 'b c')),
555            (r'a b\ c', ('a', 'b c')),
556            (('a', 'b c'), ('a', 'b c')),
557            ('a 2', ('a', '2')),
558            (('a', 2), ('a', 2)),
559            ('a 3.4', ('a', '3.4')),
560            (('a', 3.4), ('a', 3.4)),
561            ((), ()),
562            (call('list', 1, '2', (3.4,)),
563                (1, '2', (3.4,)) if self.wantobjects else
564                ('1', '2', '3.4')),
565        ]
566        if tcl_version >= (8, 5):
567            if not self.wantobjects:
568                expected = ('12', '\xe2\x82\xac', '\xe2\x82\xac', '3.4')
569            elif get_tk_patchlevel() < (8, 5, 5):
570                # Before 8.5.5 dicts were converted to lists through string
571                expected = ('12', u'\u20ac', u'\u20ac', '3.4')
572            else:
573                expected = (12, u'\u20ac', u'\u20ac', (3.4,))
574            testcases += [
575                (call('dict', 'create', 12, u'\u20ac', '\xe2\x82\xac', (3.4,)),
576                    expected),
577            ]
578        for arg, res in testcases:
579            self.assertEqual(splitlist(arg), res)
580        self.assertRaises(TclError, splitlist, '{')
581
582    def test_split(self):
583        split = self.interp.tk.split
584        call = self.interp.tk.call
585        self.assertRaises(TypeError, split)
586        self.assertRaises(TypeError, split, 'a', 'b')
587        self.assertRaises(TypeError, split, 2)
588        testcases = [
589            ('2', '2'),
590            ('', ''),
591            ('{}', ''),
592            ('""', ''),
593            ('{', '{'),
594            ('a\n b\t\r c\n ', ('a', 'b', 'c')),
595            (u'a\n b\t\r c\n ', ('a', 'b', 'c')),
596            ('a \xe2\x82\xac', ('a', '\xe2\x82\xac')),
597            (u'a \u20ac', ('a', '\xe2\x82\xac')),
598            ('a\xc0\x80b', 'a\xc0\x80b'),
599            ('a\xc0\x80b c\xc0\x80d', ('a\xc0\x80b', 'c\xc0\x80d')),
600            ('a {b c}', ('a', ('b', 'c'))),
601            (r'a b\ c', ('a', ('b', 'c'))),
602            (('a', 'b c'), ('a', ('b', 'c'))),
603            (('a', u'b c'), ('a', ('b', 'c'))),
604            ('a 2', ('a', '2')),
605            (('a', 2), ('a', 2)),
606            ('a 3.4', ('a', '3.4')),
607            (('a', 3.4), ('a', 3.4)),
608            (('a', (2, 3.4)), ('a', (2, 3.4))),
609            ((), ()),
610            (call('list', 1, '2', (3.4,)),
611                (1, '2', (3.4,)) if self.wantobjects else
612                ('1', '2', '3.4')),
613        ]
614        if tcl_version >= (8, 5):
615            if not self.wantobjects:
616                expected = ('12', '\xe2\x82\xac', '\xe2\x82\xac', '3.4')
617            elif get_tk_patchlevel() < (8, 5, 5):
618                # Before 8.5.5 dicts were converted to lists through string
619                expected = ('12', u'\u20ac', u'\u20ac', '3.4')
620            else:
621                expected = (12, u'\u20ac', u'\u20ac', (3.4,))
622            testcases += [
623                (call('dict', 'create', 12, u'\u20ac', '\xe2\x82\xac', (3.4,)),
624                    expected),
625            ]
626        for arg, res in testcases:
627            self.assertEqual(split(arg), res)
628
629    def test_splitdict(self):
630        splitdict = tkinter._splitdict
631        tcl = self.interp.tk
632
633        arg = '-a {1 2 3} -something foo status {}'
634        self.assertEqual(splitdict(tcl, arg, False),
635            {'-a': '1 2 3', '-something': 'foo', 'status': ''})
636        self.assertEqual(splitdict(tcl, arg),
637            {'a': '1 2 3', 'something': 'foo', 'status': ''})
638
639        arg = ('-a', (1, 2, 3), '-something', 'foo', 'status', '{}')
640        self.assertEqual(splitdict(tcl, arg, False),
641            {'-a': (1, 2, 3), '-something': 'foo', 'status': '{}'})
642        self.assertEqual(splitdict(tcl, arg),
643            {'a': (1, 2, 3), 'something': 'foo', 'status': '{}'})
644
645        self.assertRaises(RuntimeError, splitdict, tcl, '-a b -c ')
646        self.assertRaises(RuntimeError, splitdict, tcl, ('-a', 'b', '-c'))
647
648        arg = tcl.call('list',
649                        '-a', (1, 2, 3), '-something', 'foo', 'status', ())
650        self.assertEqual(splitdict(tcl, arg),
651            {'a': (1, 2, 3) if self.wantobjects else '1 2 3',
652             'something': 'foo', 'status': ''})
653
654        if tcl_version >= (8, 5):
655            arg = tcl.call('dict', 'create',
656                           '-a', (1, 2, 3), '-something', 'foo', 'status', ())
657            if not self.wantobjects or get_tk_patchlevel() < (8, 5, 5):
658                # Before 8.5.5 dicts were converted to lists through string
659                expected = {'a': '1 2 3', 'something': 'foo', 'status': ''}
660            else:
661                expected = {'a': (1, 2, 3), 'something': 'foo', 'status': ''}
662            self.assertEqual(splitdict(tcl, arg), expected)
663
664    def test_join(self):
665        join = tkinter._join
666        tcl = self.interp.tk
667        def unpack(s):
668            return tcl.call('lindex', s, 0)
669        def check(value):
670            self.assertEqual(unpack(join([value])), value)
671            self.assertEqual(unpack(join([value, 0])), value)
672            self.assertEqual(unpack(unpack(join([[value]]))), value)
673            self.assertEqual(unpack(unpack(join([[value, 0]]))), value)
674            self.assertEqual(unpack(unpack(join([[value], 0]))), value)
675            self.assertEqual(unpack(unpack(join([[value, 0], 0]))), value)
676        check('')
677        check('spam')
678        check('sp am')
679        check('sp\tam')
680        check('sp\nam')
681        check(' \t\n')
682        check('{spam}')
683        check('{sp am}')
684        check('"spam"')
685        check('"sp am"')
686        check('{"spam"}')
687        check('"{spam}"')
688        check('sp\\am')
689        check('"sp\\am"')
690        check('"{}" "{}"')
691        check('"\\')
692        check('"{')
693        check('"}')
694        check('\n\\')
695        check('\n{')
696        check('\n}')
697        check('\\\n')
698        check('{\n')
699        check('}\n')
700
701
702character_size = 4 if sys.maxunicode > 0xFFFF else 2
703
704class BigmemTclTest(unittest.TestCase):
705
706    def setUp(self):
707        self.interp = Tcl()
708
709    @test_support.cpython_only
710    @unittest.skipUnless(INT_MAX < PY_SSIZE_T_MAX, "needs UINT_MAX < SIZE_MAX")
711    @test_support.precisionbigmemtest(size=INT_MAX + 1, memuse=5, dry_run=False)
712    def test_huge_string_call(self, size):
713        value = ' ' * size
714        self.assertRaises(OverflowError, self.interp.call, 'set', '_', value)
715
716    @test_support.cpython_only
717    @unittest.skipUnless(test_support.have_unicode, 'requires unicode support')
718    @unittest.skipUnless(INT_MAX < PY_SSIZE_T_MAX, "needs UINT_MAX < SIZE_MAX")
719    @test_support.precisionbigmemtest(size=INT_MAX + 1,
720                                      memuse=2*character_size + 2,
721                                      dry_run=False)
722    def test_huge_unicode_call(self, size):
723        value = unicode(' ') * size
724        self.assertRaises(OverflowError, self.interp.call, 'set', '_', value)
725
726
727    @test_support.cpython_only
728    @unittest.skipUnless(INT_MAX < PY_SSIZE_T_MAX, "needs UINT_MAX < SIZE_MAX")
729    @test_support.precisionbigmemtest(size=INT_MAX + 1, memuse=9, dry_run=False)
730    def test_huge_string_builtins(self, size):
731        value = '1' + ' ' * size
732        self.check_huge_string_builtins(value)
733
734    @test_support.cpython_only
735    @unittest.skipUnless(test_support.have_unicode, 'requires unicode support')
736    @unittest.skipUnless(INT_MAX < PY_SSIZE_T_MAX, "needs UINT_MAX < SIZE_MAX")
737    @test_support.precisionbigmemtest(size=INT_MAX + 1,
738                                      memuse=2*character_size + 7,
739                                      dry_run=False)
740    def test_huge_unicode_builtins(self, size):
741        value = unicode('1' + ' ' * size)
742        self.check_huge_string_builtins(value)
743
744    def check_huge_string_builtins(self, value):
745        tk = self.interp.tk
746        self.assertRaises(OverflowError, tk.getint, value)
747        self.assertRaises(OverflowError, tk.getdouble, value)
748        self.assertRaises(OverflowError, tk.getboolean, value)
749        self.assertRaises(OverflowError, tk.eval, value)
750        self.assertRaises(OverflowError, tk.evalfile, value)
751        self.assertRaises(OverflowError, tk.record, value)
752        self.assertRaises(OverflowError, tk.adderrorinfo, value)
753        self.assertRaises(OverflowError, tk.setvar, value, 'x', 'a')
754        self.assertRaises(OverflowError, tk.setvar, 'x', value, 'a')
755        self.assertRaises(OverflowError, tk.unsetvar, value)
756        self.assertRaises(OverflowError, tk.unsetvar, 'x', value)
757        self.assertRaises(OverflowError, tk.exprstring, value)
758        self.assertRaises(OverflowError, tk.exprlong, value)
759        self.assertRaises(OverflowError, tk.exprboolean, value)
760        self.assertRaises(OverflowError, tk.splitlist, value)
761        self.assertRaises(OverflowError, tk.split, value)
762        self.assertRaises(OverflowError, tk.createcommand, value, max)
763        self.assertRaises(OverflowError, tk.deletecommand, value)
764
765
766def setUpModule():
767    if test_support.verbose:
768        tcl = Tcl()
769        print 'patchlevel =', tcl.call('info', 'patchlevel')
770
771
772def test_main():
773    test_support.run_unittest(TclTest, TkinterTest, BigmemTclTest)
774
775if __name__ == "__main__":
776    test_main()
777