• 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:
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
665character_size = 4 if sys.maxunicode > 0xFFFF else 2
666
667class BigmemTclTest(unittest.TestCase):
668
669    def setUp(self):
670        self.interp = Tcl()
671
672    @test_support.cpython_only
673    @unittest.skipUnless(INT_MAX < PY_SSIZE_T_MAX, "needs UINT_MAX < SIZE_MAX")
674    @test_support.precisionbigmemtest(size=INT_MAX + 1, memuse=5, dry_run=False)
675    def test_huge_string_call(self, size):
676        value = ' ' * size
677        self.assertRaises(OverflowError, self.interp.call, 'set', '_', value)
678
679    @test_support.cpython_only
680    @unittest.skipUnless(test_support.have_unicode, 'requires unicode support')
681    @unittest.skipUnless(INT_MAX < PY_SSIZE_T_MAX, "needs UINT_MAX < SIZE_MAX")
682    @test_support.precisionbigmemtest(size=INT_MAX + 1,
683                                      memuse=2*character_size + 2,
684                                      dry_run=False)
685    def test_huge_unicode_call(self, size):
686        value = unicode(' ') * size
687        self.assertRaises(OverflowError, self.interp.call, 'set', '_', value)
688
689
690    @test_support.cpython_only
691    @unittest.skipUnless(INT_MAX < PY_SSIZE_T_MAX, "needs UINT_MAX < SIZE_MAX")
692    @test_support.precisionbigmemtest(size=INT_MAX + 1, memuse=9, dry_run=False)
693    def test_huge_string_builtins(self, size):
694        value = '1' + ' ' * size
695        self.check_huge_string_builtins(value)
696
697    @test_support.cpython_only
698    @unittest.skipUnless(test_support.have_unicode, 'requires unicode support')
699    @unittest.skipUnless(INT_MAX < PY_SSIZE_T_MAX, "needs UINT_MAX < SIZE_MAX")
700    @test_support.precisionbigmemtest(size=INT_MAX + 1,
701                                      memuse=2*character_size + 7,
702                                      dry_run=False)
703    def test_huge_unicode_builtins(self, size):
704        value = unicode('1' + ' ' * size)
705        self.check_huge_string_builtins(value)
706
707    def check_huge_string_builtins(self, value):
708        self.assertRaises(OverflowError, self.interp.tk.getint, value)
709        self.assertRaises(OverflowError, self.interp.tk.getdouble, value)
710        self.assertRaises(OverflowError, self.interp.tk.getboolean, value)
711        self.assertRaises(OverflowError, self.interp.eval, value)
712        self.assertRaises(OverflowError, self.interp.evalfile, value)
713        self.assertRaises(OverflowError, self.interp.record, value)
714        self.assertRaises(OverflowError, self.interp.adderrorinfo, value)
715        self.assertRaises(OverflowError, self.interp.setvar, value, 'x', 'a')
716        self.assertRaises(OverflowError, self.interp.setvar, 'x', value, 'a')
717        self.assertRaises(OverflowError, self.interp.unsetvar, value)
718        self.assertRaises(OverflowError, self.interp.unsetvar, 'x', value)
719        self.assertRaises(OverflowError, self.interp.adderrorinfo, value)
720        self.assertRaises(OverflowError, self.interp.exprstring, value)
721        self.assertRaises(OverflowError, self.interp.exprlong, value)
722        self.assertRaises(OverflowError, self.interp.exprboolean, value)
723        self.assertRaises(OverflowError, self.interp.splitlist, value)
724        self.assertRaises(OverflowError, self.interp.split, value)
725        self.assertRaises(OverflowError, self.interp.createcommand, value, max)
726        self.assertRaises(OverflowError, self.interp.deletecommand, value)
727
728
729def setUpModule():
730    if test_support.verbose:
731        tcl = Tcl()
732        print 'patchlevel =', tcl.call('info', 'patchlevel')
733
734
735def test_main():
736    test_support.run_unittest(TclTest, TkinterTest, BigmemTclTest)
737
738if __name__ == "__main__":
739    test_main()
740