test_tcl.py 27 KB

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