(root)/
Python-3.12.0/
Lib/
test/
test_tcl.py
       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()