test_curses.py 11 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346
  1. #
  2. # Test script for the curses module
  3. #
  4. # This script doesn't actually display anything very coherent. but it
  5. # does call (nearly) every method and function.
  6. #
  7. # Functions not tested: {def,reset}_{shell,prog}_mode, getch(), getstr(),
  8. # init_color()
  9. # Only called, not tested: getmouse(), ungetmouse()
  10. #
  11. import os
  12. import sys
  13. import tempfile
  14. import unittest
  15. from test.test_support import requires, import_module, verbose, run_unittest
  16. # Optionally test curses module. This currently requires that the
  17. # 'curses' resource be given on the regrtest command line using the -u
  18. # option. If not available, nothing after this line will be executed.
  19. requires('curses')
  20. # If either of these don't exist, skip the tests.
  21. curses = import_module('curses')
  22. import_module('curses.panel')
  23. import_module('curses.ascii')
  24. def requires_curses_func(name):
  25. return unittest.skipUnless(hasattr(curses, name),
  26. 'requires curses.%s' % name)
  27. term = os.environ.get('TERM')
  28. # If newterm was supported we could use it instead of initscr and not exit
  29. @unittest.skipIf(not term or term == 'unknown',
  30. "$TERM=%r, calling initscr() may cause exit" % term)
  31. @unittest.skipIf(sys.platform == "cygwin",
  32. "cygwin's curses mostly just hangs")
  33. class TestCurses(unittest.TestCase):
  34. @classmethod
  35. def setUpClass(cls):
  36. if not sys.__stdout__.isatty():
  37. # Temporary skip tests on non-tty
  38. raise unittest.SkipTest('sys.__stdout__ is not a tty')
  39. cls.tmp = tempfile.TemporaryFile()
  40. fd = cls.tmp.fileno()
  41. else:
  42. cls.tmp = None
  43. fd = sys.__stdout__.fileno()
  44. # testing setupterm() inside initscr/endwin
  45. # causes terminal breakage
  46. curses.setupterm(fd=fd)
  47. @classmethod
  48. def tearDownClass(cls):
  49. if cls.tmp:
  50. cls.tmp.close()
  51. del cls.tmp
  52. def setUp(self):
  53. if verbose:
  54. # just to make the test output a little more readable
  55. print()
  56. self.stdscr = curses.initscr()
  57. curses.savetty()
  58. def tearDown(self):
  59. curses.resetty()
  60. curses.endwin()
  61. def test_window_funcs(self):
  62. "Test the methods of windows"
  63. stdscr = self.stdscr
  64. win = curses.newwin(10,10)
  65. win = curses.newwin(5,5, 5,5)
  66. win2 = curses.newwin(15,15, 5,5)
  67. for meth in [stdscr.addch, stdscr.addstr]:
  68. for args in [('a'), ('a', curses.A_BOLD),
  69. (4,4, 'a'), (5,5, 'a', curses.A_BOLD)]:
  70. meth(*args)
  71. for meth in [stdscr.box, stdscr.clear, stdscr.clrtobot,
  72. stdscr.clrtoeol, stdscr.cursyncup, stdscr.delch,
  73. stdscr.deleteln, stdscr.erase, stdscr.getbegyx,
  74. stdscr.getbkgd, stdscr.getkey, stdscr.getmaxyx,
  75. stdscr.getparyx, stdscr.getyx, stdscr.inch,
  76. stdscr.insertln, stdscr.instr, stdscr.is_wintouched,
  77. win.noutrefresh, stdscr.redrawwin, stdscr.refresh,
  78. stdscr.standout, stdscr.standend, stdscr.syncdown,
  79. stdscr.syncup, stdscr.touchwin, stdscr.untouchwin]:
  80. meth()
  81. stdscr.addnstr('1234', 3)
  82. stdscr.addnstr('1234', 3, curses.A_BOLD)
  83. stdscr.addnstr(4,4, '1234', 3)
  84. stdscr.addnstr(5,5, '1234', 3, curses.A_BOLD)
  85. stdscr.attron(curses.A_BOLD)
  86. stdscr.attroff(curses.A_BOLD)
  87. stdscr.attrset(curses.A_BOLD)
  88. stdscr.bkgd(' ')
  89. stdscr.bkgd(' ', curses.A_REVERSE)
  90. stdscr.bkgdset(' ')
  91. stdscr.bkgdset(' ', curses.A_REVERSE)
  92. win.border(65, 66, 67, 68,
  93. 69, 70, 71, 72)
  94. win.border('|', '!', '-', '_',
  95. '+', '\\', '#', '/')
  96. with self.assertRaises(TypeError,
  97. msg="Expected win.border() to raise TypeError"):
  98. win.border(65, 66, 67, 68,
  99. 69, [], 71, 72)
  100. stdscr.clearok(1)
  101. win4 = stdscr.derwin(2,2)
  102. win4 = stdscr.derwin(1,1, 5,5)
  103. win4.mvderwin(9,9)
  104. stdscr.echochar('a')
  105. stdscr.echochar('a', curses.A_BOLD)
  106. stdscr.hline('-', 5)
  107. stdscr.hline('-', 5, curses.A_BOLD)
  108. stdscr.hline(1,1,'-', 5)
  109. stdscr.hline(1,1,'-', 5, curses.A_BOLD)
  110. stdscr.idcok(1)
  111. stdscr.idlok(1)
  112. stdscr.immedok(1)
  113. stdscr.insch('c')
  114. stdscr.insdelln(1)
  115. stdscr.insnstr('abc', 3)
  116. stdscr.insnstr('abc', 3, curses.A_BOLD)
  117. stdscr.insnstr(5, 5, 'abc', 3)
  118. stdscr.insnstr(5, 5, 'abc', 3, curses.A_BOLD)
  119. stdscr.insstr('def')
  120. stdscr.insstr('def', curses.A_BOLD)
  121. stdscr.insstr(5, 5, 'def')
  122. stdscr.insstr(5, 5, 'def', curses.A_BOLD)
  123. stdscr.is_linetouched(0)
  124. stdscr.keypad(1)
  125. stdscr.leaveok(1)
  126. stdscr.move(3,3)
  127. win.mvwin(2,2)
  128. stdscr.nodelay(1)
  129. stdscr.notimeout(1)
  130. win2.overlay(win)
  131. win2.overwrite(win)
  132. win2.overlay(win, 1, 2, 2, 1, 3, 3)
  133. win2.overwrite(win, 1, 2, 2, 1, 3, 3)
  134. stdscr.redrawln(1,2)
  135. stdscr.scrollok(1)
  136. stdscr.scroll()
  137. stdscr.scroll(2)
  138. stdscr.scroll(-3)
  139. stdscr.move(12, 2)
  140. stdscr.setscrreg(10,15)
  141. win3 = stdscr.subwin(10,10)
  142. win3 = stdscr.subwin(10,10, 5,5)
  143. stdscr.syncok(1)
  144. stdscr.timeout(5)
  145. stdscr.touchline(5,5)
  146. stdscr.touchline(5,5,0)
  147. stdscr.vline('a', 3)
  148. stdscr.vline('a', 3, curses.A_STANDOUT)
  149. stdscr.chgat(5, 2, 3, curses.A_BLINK)
  150. stdscr.chgat(3, curses.A_BOLD)
  151. stdscr.chgat(5, 8, curses.A_UNDERLINE)
  152. stdscr.chgat(curses.A_BLINK)
  153. stdscr.refresh()
  154. stdscr.vline(1,1, 'a', 3)
  155. stdscr.vline(1,1, 'a', 3, curses.A_STANDOUT)
  156. if hasattr(curses, 'resize'):
  157. stdscr.resize()
  158. if hasattr(curses, 'enclose'):
  159. stdscr.enclose()
  160. def test_module_funcs(self):
  161. "Test module-level functions"
  162. for func in [curses.baudrate, curses.beep, curses.can_change_color,
  163. curses.cbreak, curses.def_prog_mode, curses.doupdate,
  164. curses.filter, curses.flash, curses.flushinp,
  165. curses.has_colors, curses.has_ic, curses.has_il,
  166. curses.isendwin, curses.killchar, curses.longname,
  167. curses.nocbreak, curses.noecho, curses.nonl,
  168. curses.noqiflush, curses.noraw,
  169. curses.reset_prog_mode, curses.termattrs,
  170. curses.termname, curses.erasechar, curses.getsyx]:
  171. func()
  172. # Functions that actually need arguments
  173. if curses.tigetstr("cnorm"):
  174. curses.curs_set(1)
  175. curses.delay_output(1)
  176. curses.echo() ; curses.echo(1)
  177. with tempfile.TemporaryFile() as f:
  178. self.stdscr.putwin(f)
  179. f.seek(0)
  180. curses.getwin(f)
  181. curses.halfdelay(1)
  182. curses.intrflush(1)
  183. curses.meta(1)
  184. curses.napms(100)
  185. curses.newpad(50,50)
  186. win = curses.newwin(5,5)
  187. win = curses.newwin(5,5, 1,1)
  188. curses.nl() ; curses.nl(1)
  189. curses.putp(b'abc')
  190. curses.qiflush()
  191. curses.raw() ; curses.raw(1)
  192. curses.setsyx(5,5)
  193. curses.tigetflag('hc')
  194. curses.tigetnum('co')
  195. curses.tigetstr('cr')
  196. curses.tparm(b'cr')
  197. curses.typeahead(sys.__stdin__.fileno())
  198. curses.unctrl('a')
  199. curses.ungetch('a')
  200. curses.use_env(1)
  201. # Functions only available on a few platforms
  202. def test_colors_funcs(self):
  203. if not curses.has_colors():
  204. self.skip('requires colors support')
  205. curses.start_color()
  206. curses.init_pair(2, 1,1)
  207. curses.color_content(1)
  208. curses.color_pair(2)
  209. curses.pair_content(curses.COLOR_PAIRS - 1)
  210. curses.pair_number(0)
  211. if hasattr(curses, 'use_default_colors'):
  212. curses.use_default_colors()
  213. @requires_curses_func('keyname')
  214. def test_keyname(self):
  215. curses.keyname(13)
  216. @requires_curses_func('has_key')
  217. def test_has_key(self):
  218. curses.has_key(13)
  219. @requires_curses_func('getmouse')
  220. def test_getmouse(self):
  221. (availmask, oldmask) = curses.mousemask(curses.BUTTON1_PRESSED)
  222. if availmask == 0:
  223. self.skip('mouse stuff not available')
  224. curses.mouseinterval(10)
  225. # just verify these don't cause errors
  226. curses.ungetmouse(0, 0, 0, 0, curses.BUTTON1_PRESSED)
  227. m = curses.getmouse()
  228. def test_userptr_without_set(self):
  229. w = curses.newwin(10, 10)
  230. p = curses.panel.new_panel(w)
  231. # try to access userptr() before calling set_userptr() -- segfaults
  232. with self.assertRaises(curses.panel.error,
  233. msg='userptr should fail since not set'):
  234. p.userptr()
  235. def test_userptr_memory_leak(self):
  236. w = curses.newwin(10, 10)
  237. p = curses.panel.new_panel(w)
  238. obj = object()
  239. nrefs = sys.getrefcount(obj)
  240. for i in range(100):
  241. p.set_userptr(obj)
  242. p.set_userptr(None)
  243. self.assertEqual(sys.getrefcount(obj), nrefs,
  244. "set_userptr leaked references")
  245. def test_userptr_segfault(self):
  246. panel = curses.panel.new_panel(self.stdscr)
  247. class A:
  248. def __del__(self):
  249. panel.set_userptr(None)
  250. panel.set_userptr(A())
  251. panel.set_userptr(None)
  252. def test_new_curses_panel(self):
  253. panel = curses.panel.new_panel(self.stdscr)
  254. self.assertRaises(TypeError, type(panel))
  255. @requires_curses_func('is_term_resized')
  256. def test_is_term_resized(self):
  257. curses.is_term_resized(*self.stdscr.getmaxyx())
  258. @requires_curses_func('resize_term')
  259. def test_resize_term(self):
  260. curses.resize_term(*self.stdscr.getmaxyx())
  261. @requires_curses_func('resizeterm')
  262. def test_resizeterm(self):
  263. stdscr = self.stdscr
  264. lines, cols = curses.LINES, curses.COLS
  265. new_lines = lines - 1
  266. new_cols = cols + 1
  267. curses.resizeterm(new_lines, new_cols)
  268. self.assertEqual(curses.LINES, new_lines)
  269. self.assertEqual(curses.COLS, new_cols)
  270. def test_issue6243(self):
  271. curses.ungetch(1025)
  272. self.stdscr.getkey()
  273. def test_issue10570(self):
  274. b = curses.tparm(curses.tigetstr("cup"), 5, 3)
  275. self.assertIs(type(b), bytes)
  276. class TestAscii(unittest.TestCase):
  277. def test_unctrl(self):
  278. unctrl = curses.ascii.unctrl
  279. self.assertEqual(unctrl('a'), 'a')
  280. self.assertEqual(unctrl('A'), 'A')
  281. self.assertEqual(unctrl(';'), ';')
  282. self.assertEqual(unctrl(' '), ' ')
  283. self.assertEqual(unctrl('\x7f'), '^?')
  284. self.assertEqual(unctrl('\n'), '^J')
  285. self.assertEqual(unctrl('\0'), '^@')
  286. # Meta-bit characters
  287. self.assertEqual(unctrl('\x8a'), '!^J')
  288. self.assertEqual(unctrl('\xc1'), '!A')
  289. def test_main():
  290. run_unittest(TestCurses, TestAscii)
  291. if __name__ == "__main__":
  292. unittest.main()