blob: 09738c8a41c942746ea8e77079fe1c34487f8907 [file] [log] [blame]
Andrew M. Kuchling2158df02001-10-22 15:26:09 +00001#
2# Test script for the curses module
3#
4# This script doesn't actually display anything very coherent. but it
Zachary Warebaf45c52014-10-17 13:59:18 -05005# does call (nearly) every method and function.
Andrew M. Kuchling2158df02001-10-22 15:26:09 +00006#
7# Functions not tested: {def,reset}_{shell,prog}_mode, getch(), getstr(),
Neal Norwitz88bbd732006-01-10 07:05:44 +00008# init_color()
9# Only called, not tested: getmouse(), ungetmouse()
Andrew M. Kuchling2158df02001-10-22 15:26:09 +000010#
11
Zachary Warebaf45c52014-10-17 13:59:18 -050012import os
Serhiy Storchaka514f9732016-06-18 22:08:11 +030013import string
Zachary Warebaf45c52014-10-17 13:59:18 -050014import sys
15import tempfile
16import unittest
17
Victor Stinner19f68302017-10-31 03:14:01 -070018from test.support import requires, import_module, verbose, SaveSignals
Andrew M. Kuchling2158df02001-10-22 15:26:09 +000019
20# Optionally test curses module. This currently requires that the
21# 'curses' resource be given on the regrtest command line using the -u
22# option. If not available, nothing after this line will be executed.
Larry Hastings9147a962014-05-04 04:41:18 -070023import inspect
Neal Norwitz9f39f682006-01-06 04:18:21 +000024requires('curses')
25
R. David Murraya21e4ca2009-03-31 23:16:50 +000026# If either of these don't exist, skip the tests.
27curses = import_module('curses')
Serhiy Storchaka0eb39e72016-05-21 21:36:11 +030028import_module('curses.ascii')
Serhiy Storchakabdf9e0e2016-12-28 10:16:06 +020029import_module('curses.textpad')
Serhiy Storchakabaac01e2017-10-31 13:56:44 +020030try:
31 import curses.panel
32except ImportError:
33 pass
R. David Murraya21e4ca2009-03-31 23:16:50 +000034
Serhiy Storchaka0eb39e72016-05-21 21:36:11 +030035def requires_curses_func(name):
36 return unittest.skipUnless(hasattr(curses, name),
37 'requires curses.%s' % name)
Mark Dickinson945e2422010-02-21 13:42:03 +000038
Serhiy Storchaka0eb39e72016-05-21 21:36:11 +030039term = os.environ.get('TERM')
40
41# If newterm was supported we could use it instead of initscr and not exit
42@unittest.skipIf(not term or term == 'unknown',
Zachary Warebaf45c52014-10-17 13:59:18 -050043 "$TERM=%r, calling initscr() may cause exit" % term)
44@unittest.skipIf(sys.platform == "cygwin",
45 "cygwin's curses mostly just hangs")
46class TestCurses(unittest.TestCase):
Serhiy Storchaka0eb39e72016-05-21 21:36:11 +030047
Zachary Warebaf45c52014-10-17 13:59:18 -050048 @classmethod
49 def setUpClass(cls):
Serhiy Storchaka0eb39e72016-05-21 21:36:11 +030050 if not sys.__stdout__.isatty():
Serhiy Storchaka53a00352016-05-22 18:16:20 +030051 # Temporary skip tests on non-tty
Serhiy Storchaka0a91e432016-05-22 18:23:36 +030052 raise unittest.SkipTest('sys.__stdout__ is not a tty')
Serhiy Storchaka0eb39e72016-05-21 21:36:11 +030053 cls.tmp = tempfile.TemporaryFile()
54 fd = cls.tmp.fileno()
55 else:
56 cls.tmp = None
57 fd = sys.__stdout__.fileno()
58 # testing setupterm() inside initscr/endwin
59 # causes terminal breakage
60 curses.setupterm(fd=fd)
61
62 @classmethod
63 def tearDownClass(cls):
64 if cls.tmp:
65 cls.tmp.close()
66 del cls.tmp
Andrew M. Kuchling2158df02001-10-22 15:26:09 +000067
Zachary Warebaf45c52014-10-17 13:59:18 -050068 def setUp(self):
Victor Stinner19f68302017-10-31 03:14:01 -070069 self.save_signals = SaveSignals()
70 self.save_signals.save()
Zachary Warebaf45c52014-10-17 13:59:18 -050071 if verbose:
72 # just to make the test output a little more readable
73 print()
74 self.stdscr = curses.initscr()
75 curses.savetty()
Thomas Wouters49fd7fa2006-04-21 10:40:58 +000076
Zachary Warebaf45c52014-10-17 13:59:18 -050077 def tearDown(self):
Andrew M. Kuchling2158df02001-10-22 15:26:09 +000078 curses.resetty()
Andrew M. Kuchling2158df02001-10-22 15:26:09 +000079 curses.endwin()
Victor Stinner19f68302017-10-31 03:14:01 -070080 self.save_signals.restore()
Zachary Warebaf45c52014-10-17 13:59:18 -050081
82 def test_window_funcs(self):
83 "Test the methods of windows"
84 stdscr = self.stdscr
85 win = curses.newwin(10,10)
86 win = curses.newwin(5,5, 5,5)
87 win2 = curses.newwin(15,15, 5,5)
88
89 for meth in [stdscr.addch, stdscr.addstr]:
Serhiy Storchakaf7eae0a2017-06-28 08:30:06 +030090 for args in [('a',), ('a', curses.A_BOLD),
Zachary Warebaf45c52014-10-17 13:59:18 -050091 (4,4, 'a'), (5,5, 'a', curses.A_BOLD)]:
Serhiy Storchaka0eb39e72016-05-21 21:36:11 +030092 with self.subTest(meth=meth.__qualname__, args=args):
93 meth(*args)
Zachary Warebaf45c52014-10-17 13:59:18 -050094
Serhiy Storchaka4f469c02017-11-01 20:48:49 +020095 for meth in [stdscr.clear, stdscr.clrtobot,
Zachary Warebaf45c52014-10-17 13:59:18 -050096 stdscr.clrtoeol, stdscr.cursyncup, stdscr.delch,
97 stdscr.deleteln, stdscr.erase, stdscr.getbegyx,
98 stdscr.getbkgd, stdscr.getkey, stdscr.getmaxyx,
99 stdscr.getparyx, stdscr.getyx, stdscr.inch,
100 stdscr.insertln, stdscr.instr, stdscr.is_wintouched,
101 win.noutrefresh, stdscr.redrawwin, stdscr.refresh,
102 stdscr.standout, stdscr.standend, stdscr.syncdown,
103 stdscr.syncup, stdscr.touchwin, stdscr.untouchwin]:
Serhiy Storchaka0eb39e72016-05-21 21:36:11 +0300104 with self.subTest(meth=meth.__qualname__):
105 meth()
Zachary Warebaf45c52014-10-17 13:59:18 -0500106
107 stdscr.addnstr('1234', 3)
108 stdscr.addnstr('1234', 3, curses.A_BOLD)
109 stdscr.addnstr(4,4, '1234', 3)
110 stdscr.addnstr(5,5, '1234', 3, curses.A_BOLD)
111
112 stdscr.attron(curses.A_BOLD)
113 stdscr.attroff(curses.A_BOLD)
114 stdscr.attrset(curses.A_BOLD)
115 stdscr.bkgd(' ')
116 stdscr.bkgd(' ', curses.A_REVERSE)
117 stdscr.bkgdset(' ')
118 stdscr.bkgdset(' ', curses.A_REVERSE)
119
120 win.border(65, 66, 67, 68,
121 69, 70, 71, 72)
122 win.border('|', '!', '-', '_',
123 '+', '\\', '#', '/')
124 with self.assertRaises(TypeError,
125 msg="Expected win.border() to raise TypeError"):
126 win.border(65, 66, 67, 68,
127 69, [], 71, 72)
128
Serhiy Storchaka4f469c02017-11-01 20:48:49 +0200129 win.box(65, 67)
130 win.box('!', '_')
131 win.box(b':', b'~')
132 self.assertRaises(TypeError, win.box, 65, 66, 67)
133 self.assertRaises(TypeError, win.box, 65)
134 win.box()
135
Zachary Warebaf45c52014-10-17 13:59:18 -0500136 stdscr.clearok(1)
137
138 win4 = stdscr.derwin(2,2)
139 win4 = stdscr.derwin(1,1, 5,5)
140 win4.mvderwin(9,9)
141
142 stdscr.echochar('a')
143 stdscr.echochar('a', curses.A_BOLD)
144 stdscr.hline('-', 5)
145 stdscr.hline('-', 5, curses.A_BOLD)
146 stdscr.hline(1,1,'-', 5)
147 stdscr.hline(1,1,'-', 5, curses.A_BOLD)
148
149 stdscr.idcok(1)
150 stdscr.idlok(1)
Serhiy Storchakabaac01e2017-10-31 13:56:44 +0200151 if hasattr(stdscr, 'immedok'):
152 stdscr.immedok(1)
Serhiy Storchaka894ebd02017-11-01 14:34:20 +0200153 stdscr.immedok(0)
Zachary Warebaf45c52014-10-17 13:59:18 -0500154 stdscr.insch('c')
155 stdscr.insdelln(1)
156 stdscr.insnstr('abc', 3)
157 stdscr.insnstr('abc', 3, curses.A_BOLD)
158 stdscr.insnstr(5, 5, 'abc', 3)
159 stdscr.insnstr(5, 5, 'abc', 3, curses.A_BOLD)
160
161 stdscr.insstr('def')
162 stdscr.insstr('def', curses.A_BOLD)
163 stdscr.insstr(5, 5, 'def')
164 stdscr.insstr(5, 5, 'def', curses.A_BOLD)
165 stdscr.is_linetouched(0)
166 stdscr.keypad(1)
167 stdscr.leaveok(1)
168 stdscr.move(3,3)
169 win.mvwin(2,2)
170 stdscr.nodelay(1)
171 stdscr.notimeout(1)
172 win2.overlay(win)
173 win2.overwrite(win)
174 win2.overlay(win, 1, 2, 2, 1, 3, 3)
175 win2.overwrite(win, 1, 2, 2, 1, 3, 3)
176 stdscr.redrawln(1,2)
177
178 stdscr.scrollok(1)
179 stdscr.scroll()
180 stdscr.scroll(2)
181 stdscr.scroll(-3)
182
183 stdscr.move(12, 2)
184 stdscr.setscrreg(10,15)
185 win3 = stdscr.subwin(10,10)
186 win3 = stdscr.subwin(10,10, 5,5)
Serhiy Storchaka894ebd02017-11-01 14:34:20 +0200187 if hasattr(stdscr, 'syncok') and not sys.platform.startswith("sunos"):
Serhiy Storchakabaac01e2017-10-31 13:56:44 +0200188 stdscr.syncok(1)
Zachary Warebaf45c52014-10-17 13:59:18 -0500189 stdscr.timeout(5)
190 stdscr.touchline(5,5)
191 stdscr.touchline(5,5,0)
192 stdscr.vline('a', 3)
193 stdscr.vline('a', 3, curses.A_STANDOUT)
Serhiy Storchaka894ebd02017-11-01 14:34:20 +0200194 if hasattr(stdscr, 'chgat'):
195 stdscr.chgat(5, 2, 3, curses.A_BLINK)
196 stdscr.chgat(3, curses.A_BOLD)
197 stdscr.chgat(5, 8, curses.A_UNDERLINE)
198 stdscr.chgat(curses.A_BLINK)
Zachary Warebaf45c52014-10-17 13:59:18 -0500199 stdscr.refresh()
200
201 stdscr.vline(1,1, 'a', 3)
202 stdscr.vline(1,1, 'a', 3, curses.A_STANDOUT)
203
Serhiy Storchaka894ebd02017-11-01 14:34:20 +0200204 if hasattr(stdscr, 'resize'):
205 stdscr.resize(25, 80)
206 if hasattr(stdscr, 'enclose'):
207 stdscr.enclose(10, 10)
Zachary Warebaf45c52014-10-17 13:59:18 -0500208
Benjamin Peterson40a77c32016-08-13 18:15:28 -0700209 self.assertRaises(ValueError, stdscr.getstr, -400)
210 self.assertRaises(ValueError, stdscr.getstr, 2, 3, -400)
Benjamin Peterson432ea4f2016-08-15 21:40:14 -0700211 self.assertRaises(ValueError, stdscr.instr, -2)
212 self.assertRaises(ValueError, stdscr.instr, 2, 3, -2)
Benjamin Peterson40a77c32016-08-13 18:15:28 -0700213
Serhiy Storchakaf7eae0a2017-06-28 08:30:06 +0300214 def test_embedded_null_chars(self):
215 # reject embedded null bytes and characters
216 stdscr = self.stdscr
217 for arg in ['a', b'a']:
218 with self.subTest(arg=arg):
219 self.assertRaises(ValueError, stdscr.addstr, 'a\0')
220 self.assertRaises(ValueError, stdscr.addnstr, 'a\0', 1)
221 self.assertRaises(ValueError, stdscr.insstr, 'a\0')
222 self.assertRaises(ValueError, stdscr.insnstr, 'a\0', 1)
Zachary Warebaf45c52014-10-17 13:59:18 -0500223
224 def test_module_funcs(self):
225 "Test module-level functions"
Zachary Warebaf45c52014-10-17 13:59:18 -0500226 for func in [curses.baudrate, curses.beep, curses.can_change_color,
227 curses.cbreak, curses.def_prog_mode, curses.doupdate,
Serhiy Storchakabaac01e2017-10-31 13:56:44 +0200228 curses.flash, curses.flushinp,
Zachary Warebaf45c52014-10-17 13:59:18 -0500229 curses.has_colors, curses.has_ic, curses.has_il,
230 curses.isendwin, curses.killchar, curses.longname,
231 curses.nocbreak, curses.noecho, curses.nonl,
232 curses.noqiflush, curses.noraw,
233 curses.reset_prog_mode, curses.termattrs,
Serhiy Storchakabaac01e2017-10-31 13:56:44 +0200234 curses.termname, curses.erasechar]:
Serhiy Storchaka0eb39e72016-05-21 21:36:11 +0300235 with self.subTest(func=func.__qualname__):
236 func()
Serhiy Storchakabaac01e2017-10-31 13:56:44 +0200237 if hasattr(curses, 'filter'):
238 curses.filter()
239 if hasattr(curses, 'getsyx'):
240 curses.getsyx()
Zachary Warebaf45c52014-10-17 13:59:18 -0500241
242 # Functions that actually need arguments
243 if curses.tigetstr("cnorm"):
244 curses.curs_set(1)
245 curses.delay_output(1)
246 curses.echo() ; curses.echo(1)
247
Serhiy Storchaka0eb39e72016-05-21 21:36:11 +0300248 with tempfile.TemporaryFile() as f:
249 self.stdscr.putwin(f)
250 f.seek(0)
251 curses.getwin(f)
Zachary Warebaf45c52014-10-17 13:59:18 -0500252
253 curses.halfdelay(1)
254 curses.intrflush(1)
255 curses.meta(1)
256 curses.napms(100)
257 curses.newpad(50,50)
258 win = curses.newwin(5,5)
259 win = curses.newwin(5,5, 1,1)
260 curses.nl() ; curses.nl(1)
261 curses.putp(b'abc')
262 curses.qiflush()
263 curses.raw() ; curses.raw(1)
Serhiy Storchakabaac01e2017-10-31 13:56:44 +0200264 if hasattr(curses, 'setsyx'):
265 curses.setsyx(5,5)
Zachary Warebaf45c52014-10-17 13:59:18 -0500266 curses.tigetflag('hc')
267 curses.tigetnum('co')
268 curses.tigetstr('cr')
269 curses.tparm(b'cr')
Serhiy Storchakabaac01e2017-10-31 13:56:44 +0200270 if hasattr(curses, 'typeahead'):
271 curses.typeahead(sys.__stdin__.fileno())
Zachary Warebaf45c52014-10-17 13:59:18 -0500272 curses.unctrl('a')
273 curses.ungetch('a')
Serhiy Storchakabaac01e2017-10-31 13:56:44 +0200274 if hasattr(curses, 'use_env'):
275 curses.use_env(1)
Zachary Warebaf45c52014-10-17 13:59:18 -0500276
Serhiy Storchaka0eb39e72016-05-21 21:36:11 +0300277 # Functions only available on a few platforms
278 def test_colors_funcs(self):
279 if not curses.has_colors():
Xavier de Gaye645bc802017-01-06 09:50:27 +0100280 self.skipTest('requires colors support')
Serhiy Storchaka0eb39e72016-05-21 21:36:11 +0300281 curses.start_color()
282 curses.init_pair(2, 1,1)
283 curses.color_content(1)
284 curses.color_pair(2)
285 curses.pair_content(curses.COLOR_PAIRS - 1)
286 curses.pair_number(0)
Zachary Warebaf45c52014-10-17 13:59:18 -0500287
Serhiy Storchaka0eb39e72016-05-21 21:36:11 +0300288 if hasattr(curses, 'use_default_colors'):
289 curses.use_default_colors()
Zachary Warebaf45c52014-10-17 13:59:18 -0500290
Serhiy Storchaka0eb39e72016-05-21 21:36:11 +0300291 @requires_curses_func('keyname')
292 def test_keyname(self):
293 curses.keyname(13)
Zachary Warebaf45c52014-10-17 13:59:18 -0500294
Serhiy Storchaka0eb39e72016-05-21 21:36:11 +0300295 @requires_curses_func('has_key')
296 def test_has_key(self):
297 curses.has_key(13)
Zachary Warebaf45c52014-10-17 13:59:18 -0500298
Serhiy Storchaka0eb39e72016-05-21 21:36:11 +0300299 @requires_curses_func('getmouse')
300 def test_getmouse(self):
301 (availmask, oldmask) = curses.mousemask(curses.BUTTON1_PRESSED)
302 if availmask == 0:
Xavier de Gaye645bc802017-01-06 09:50:27 +0100303 self.skipTest('mouse stuff not available')
Serhiy Storchaka0eb39e72016-05-21 21:36:11 +0300304 curses.mouseinterval(10)
305 # just verify these don't cause errors
306 curses.ungetmouse(0, 0, 0, 0, curses.BUTTON1_PRESSED)
307 m = curses.getmouse()
Zachary Warebaf45c52014-10-17 13:59:18 -0500308
Serhiy Storchakabaac01e2017-10-31 13:56:44 +0200309 @requires_curses_func('panel')
Zachary Warebaf45c52014-10-17 13:59:18 -0500310 def test_userptr_without_set(self):
311 w = curses.newwin(10, 10)
312 p = curses.panel.new_panel(w)
313 # try to access userptr() before calling set_userptr() -- segfaults
314 with self.assertRaises(curses.panel.error,
315 msg='userptr should fail since not set'):
316 p.userptr()
317
Serhiy Storchakabaac01e2017-10-31 13:56:44 +0200318 @requires_curses_func('panel')
Zachary Warebaf45c52014-10-17 13:59:18 -0500319 def test_userptr_memory_leak(self):
320 w = curses.newwin(10, 10)
321 p = curses.panel.new_panel(w)
322 obj = object()
323 nrefs = sys.getrefcount(obj)
324 for i in range(100):
325 p.set_userptr(obj)
326
327 p.set_userptr(None)
328 self.assertEqual(sys.getrefcount(obj), nrefs,
329 "set_userptr leaked references")
330
Serhiy Storchakabaac01e2017-10-31 13:56:44 +0200331 @requires_curses_func('panel')
Zachary Warebaf45c52014-10-17 13:59:18 -0500332 def test_userptr_segfault(self):
Serhiy Storchakaa7723d82017-11-03 20:29:33 +0200333 w = curses.newwin(10, 10)
334 panel = curses.panel.new_panel(w)
Zachary Warebaf45c52014-10-17 13:59:18 -0500335 class A:
336 def __del__(self):
337 panel.set_userptr(None)
338 panel.set_userptr(A())
339 panel.set_userptr(None)
340
Serhiy Storchakabaac01e2017-10-31 13:56:44 +0200341 @requires_curses_func('panel')
Serhiy Storchakae3f1b092016-05-08 20:46:22 +0300342 def test_new_curses_panel(self):
Serhiy Storchakaa7723d82017-11-03 20:29:33 +0200343 w = curses.newwin(10, 10)
344 panel = curses.panel.new_panel(w)
Serhiy Storchakae3f1b092016-05-08 20:46:22 +0300345 self.assertRaises(TypeError, type(panel))
346
Serhiy Storchaka0eb39e72016-05-21 21:36:11 +0300347 @requires_curses_func('is_term_resized')
348 def test_is_term_resized(self):
349 curses.is_term_resized(*self.stdscr.getmaxyx())
350
351 @requires_curses_func('resize_term')
Zachary Warebaf45c52014-10-17 13:59:18 -0500352 def test_resize_term(self):
Serhiy Storchaka0eb39e72016-05-21 21:36:11 +0300353 curses.resize_term(*self.stdscr.getmaxyx())
354
355 @requires_curses_func('resizeterm')
356 def test_resizeterm(self):
357 stdscr = self.stdscr
Zachary Warebaf45c52014-10-17 13:59:18 -0500358 lines, cols = curses.LINES, curses.COLS
359 new_lines = lines - 1
360 new_cols = cols + 1
361 curses.resizeterm(new_lines, new_cols)
362
363 self.assertEqual(curses.LINES, new_lines)
364 self.assertEqual(curses.COLS, new_cols)
365
366 def test_issue6243(self):
367 curses.ungetch(1025)
368 self.stdscr.getkey()
369
Serhiy Storchaka0eb39e72016-05-21 21:36:11 +0300370 @requires_curses_func('unget_wch')
Serhiy Storchakab232df92018-10-30 13:22:42 +0200371 @unittest.skipIf(getattr(curses, 'ncurses_version', (99,)) < (5, 8),
372 "unget_wch is broken in ncurses 5.7 and earlier")
Zachary Warebaf45c52014-10-17 13:59:18 -0500373 def test_unget_wch(self):
374 stdscr = self.stdscr
375 encoding = stdscr.encoding
376 for ch in ('a', '\xe9', '\u20ac', '\U0010FFFF'):
377 try:
378 ch.encode(encoding)
379 except UnicodeEncodeError:
380 continue
381 try:
382 curses.unget_wch(ch)
383 except Exception as err:
384 self.fail("unget_wch(%a) failed with encoding %s: %s"
385 % (ch, stdscr.encoding, err))
386 read = stdscr.get_wch()
387 self.assertEqual(read, ch)
388
389 code = ord(ch)
390 curses.unget_wch(code)
391 read = stdscr.get_wch()
392 self.assertEqual(read, ch)
393
394 def test_issue10570(self):
395 b = curses.tparm(curses.tigetstr("cup"), 5, 3)
396 self.assertIs(type(b), bytes)
Zachary Warebaf45c52014-10-17 13:59:18 -0500397
398 def test_encoding(self):
399 stdscr = self.stdscr
400 import codecs
401 encoding = stdscr.encoding
402 codecs.lookup(encoding)
Zachary Warebaf45c52014-10-17 13:59:18 -0500403 with self.assertRaises(TypeError):
404 stdscr.encoding = 10
Zachary Warebaf45c52014-10-17 13:59:18 -0500405 stdscr.encoding = encoding
406 with self.assertRaises(TypeError):
407 del stdscr.encoding
408
409 def test_issue21088(self):
410 stdscr = self.stdscr
411 #
412 # http://bugs.python.org/issue21088
413 #
414 # the bug:
415 # when converting curses.window.addch to Argument Clinic
416 # the first two parameters were switched.
417
418 # if someday we can represent the signature of addch
419 # we will need to rewrite this test.
420 try:
421 signature = inspect.signature(stdscr.addch)
422 self.assertFalse(signature)
423 except ValueError:
424 # not generating a signature is fine.
425 pass
426
427 # So. No signature for addch.
428 # But Argument Clinic gave us a human-readable equivalent
429 # as the first line of the docstring. So we parse that,
430 # and ensure that the parameters appear in the correct order.
431 # Since this is parsing output from Argument Clinic, we can
432 # be reasonably certain the generated parsing code will be
433 # correct too.
434 human_readable_signature = stdscr.addch.__doc__.split("\n")[0]
Serhiy Storchaka0eb39e72016-05-21 21:36:11 +0300435 self.assertIn("[y, x,]", human_readable_signature)
436
Serhiy Storchakabdf9e0e2016-12-28 10:16:06 +0200437 def test_issue13051(self):
438 stdscr = self.stdscr
Serhiy Storchaka894ebd02017-11-01 14:34:20 +0200439 if not hasattr(stdscr, 'resize'):
440 raise unittest.SkipTest('requires curses.window.resize')
Serhiy Storchakabdf9e0e2016-12-28 10:16:06 +0200441 box = curses.textpad.Textbox(stdscr, insert_mode=True)
442 lines, cols = stdscr.getmaxyx()
443 stdscr.resize(lines-2, cols-2)
444 # this may cause infinite recursion, leading to a RuntimeError
445 box._insert_printable_char('a')
446
Serhiy Storchaka0eb39e72016-05-21 21:36:11 +0300447
448class MiscTests(unittest.TestCase):
Zachary Warebaf45c52014-10-17 13:59:18 -0500449
Berker Peksag53926f12016-08-19 17:59:01 +0300450 @requires_curses_func('update_lines_cols')
Steve Dowerd2bc3892015-04-15 18:06:05 -0400451 def test_update_lines_cols(self):
452 # this doesn't actually test that LINES and COLS are updated,
453 # because we can't automate changing them. See Issue #4254 for
454 # a manual test script. We can only test that the function
455 # can be called.
456 curses.update_lines_cols()
457
Serhiy Storchakab232df92018-10-30 13:22:42 +0200458 @requires_curses_func('ncurses_version')
459 def test_ncurses_version(self):
460 v = curses.ncurses_version
461 self.assertIsInstance(v[:], tuple)
462 self.assertEqual(len(v), 3)
463 self.assertIsInstance(v[0], int)
464 self.assertIsInstance(v[1], int)
465 self.assertIsInstance(v[2], int)
466 self.assertIsInstance(v.major, int)
467 self.assertIsInstance(v.minor, int)
468 self.assertIsInstance(v.patch, int)
469 self.assertEqual(v[0], v.major)
470 self.assertEqual(v[1], v.minor)
471 self.assertEqual(v[2], v.patch)
472 self.assertGreaterEqual(v.major, 0)
473 self.assertGreaterEqual(v.minor, 0)
474 self.assertGreaterEqual(v.patch, 0)
Alexandre Vassalotti5ff02352009-07-22 21:27:53 +0000475
Serhiy Storchaka0eb39e72016-05-21 21:36:11 +0300476class TestAscii(unittest.TestCase):
477
Serhiy Storchaka514f9732016-06-18 22:08:11 +0300478 def test_controlnames(self):
479 for name in curses.ascii.controlnames:
480 self.assertTrue(hasattr(curses.ascii, name), name)
481
482 def test_ctypes(self):
483 def check(func, expected):
484 with self.subTest(ch=c, func=func):
485 self.assertEqual(func(i), expected)
486 self.assertEqual(func(c), expected)
487
488 for i in range(256):
489 c = chr(i)
490 b = bytes([i])
491 check(curses.ascii.isalnum, b.isalnum())
492 check(curses.ascii.isalpha, b.isalpha())
493 check(curses.ascii.isdigit, b.isdigit())
494 check(curses.ascii.islower, b.islower())
495 check(curses.ascii.isspace, b.isspace())
496 check(curses.ascii.isupper, b.isupper())
497
498 check(curses.ascii.isascii, i < 128)
499 check(curses.ascii.ismeta, i >= 128)
500 check(curses.ascii.isctrl, i < 32)
501 check(curses.ascii.iscntrl, i < 32 or i == 127)
502 check(curses.ascii.isblank, c in ' \t')
503 check(curses.ascii.isgraph, 32 < i <= 126)
504 check(curses.ascii.isprint, 32 <= i <= 126)
505 check(curses.ascii.ispunct, c in string.punctuation)
506 check(curses.ascii.isxdigit, c in string.hexdigits)
507
Serhiy Storchaka283de2b2016-12-28 10:04:27 +0200508 for i in (-2, -1, 256, sys.maxunicode, sys.maxunicode+1):
509 self.assertFalse(curses.ascii.isalnum(i))
510 self.assertFalse(curses.ascii.isalpha(i))
511 self.assertFalse(curses.ascii.isdigit(i))
512 self.assertFalse(curses.ascii.islower(i))
513 self.assertFalse(curses.ascii.isspace(i))
514 self.assertFalse(curses.ascii.isupper(i))
515
516 self.assertFalse(curses.ascii.isascii(i))
517 self.assertFalse(curses.ascii.isctrl(i))
518 self.assertFalse(curses.ascii.iscntrl(i))
519 self.assertFalse(curses.ascii.isblank(i))
520 self.assertFalse(curses.ascii.isgraph(i))
521 self.assertFalse(curses.ascii.isprint(i))
522 self.assertFalse(curses.ascii.ispunct(i))
523 self.assertFalse(curses.ascii.isxdigit(i))
524
525 self.assertFalse(curses.ascii.ismeta(-1))
526
Serhiy Storchaka514f9732016-06-18 22:08:11 +0300527 def test_ascii(self):
528 ascii = curses.ascii.ascii
529 self.assertEqual(ascii('\xc1'), 'A')
530 self.assertEqual(ascii('A'), 'A')
531 self.assertEqual(ascii(ord('\xc1')), ord('A'))
532
533 def test_ctrl(self):
534 ctrl = curses.ascii.ctrl
535 self.assertEqual(ctrl('J'), '\n')
536 self.assertEqual(ctrl('\n'), '\n')
537 self.assertEqual(ctrl('@'), '\0')
538 self.assertEqual(ctrl(ord('J')), ord('\n'))
539
540 def test_alt(self):
541 alt = curses.ascii.alt
542 self.assertEqual(alt('\n'), '\x8a')
543 self.assertEqual(alt('A'), '\xc1')
544 self.assertEqual(alt(ord('A')), 0xc1)
545
Serhiy Storchaka0eb39e72016-05-21 21:36:11 +0300546 def test_unctrl(self):
547 unctrl = curses.ascii.unctrl
548 self.assertEqual(unctrl('a'), 'a')
549 self.assertEqual(unctrl('A'), 'A')
550 self.assertEqual(unctrl(';'), ';')
551 self.assertEqual(unctrl(' '), ' ')
552 self.assertEqual(unctrl('\x7f'), '^?')
553 self.assertEqual(unctrl('\n'), '^J')
554 self.assertEqual(unctrl('\0'), '^@')
Serhiy Storchaka514f9732016-06-18 22:08:11 +0300555 self.assertEqual(unctrl(ord('A')), 'A')
556 self.assertEqual(unctrl(ord('\n')), '^J')
Serhiy Storchaka0eb39e72016-05-21 21:36:11 +0300557 # Meta-bit characters
558 self.assertEqual(unctrl('\x8a'), '!^J')
559 self.assertEqual(unctrl('\xc1'), '!A')
Serhiy Storchaka514f9732016-06-18 22:08:11 +0300560 self.assertEqual(unctrl(ord('\x8a')), '!^J')
561 self.assertEqual(unctrl(ord('\xc1')), '!A')
Serhiy Storchaka0eb39e72016-05-21 21:36:11 +0300562
563
Alexandre Vassalotti5ff02352009-07-22 21:27:53 +0000564if __name__ == '__main__':
Zachary Warebaf45c52014-10-17 13:59:18 -0500565 unittest.main()