blob: 5e619d13836d2608d467bd56e78a3076183b591c [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)
Anthony Sottileb32cb972019-10-31 02:13:48 -0700264 curses.set_escdelay(25)
265 self.assertEqual(curses.get_escdelay(), 25)
266 curses.set_tabsize(4)
267 self.assertEqual(curses.get_tabsize(), 4)
Serhiy Storchakabaac01e2017-10-31 13:56:44 +0200268 if hasattr(curses, 'setsyx'):
269 curses.setsyx(5,5)
Zachary Warebaf45c52014-10-17 13:59:18 -0500270 curses.tigetflag('hc')
271 curses.tigetnum('co')
272 curses.tigetstr('cr')
273 curses.tparm(b'cr')
Serhiy Storchakabaac01e2017-10-31 13:56:44 +0200274 if hasattr(curses, 'typeahead'):
275 curses.typeahead(sys.__stdin__.fileno())
Zachary Warebaf45c52014-10-17 13:59:18 -0500276 curses.unctrl('a')
277 curses.ungetch('a')
Serhiy Storchakabaac01e2017-10-31 13:56:44 +0200278 if hasattr(curses, 'use_env'):
279 curses.use_env(1)
Zachary Warebaf45c52014-10-17 13:59:18 -0500280
Serhiy Storchaka0eb39e72016-05-21 21:36:11 +0300281 # Functions only available on a few platforms
282 def test_colors_funcs(self):
283 if not curses.has_colors():
Xavier de Gaye645bc802017-01-06 09:50:27 +0100284 self.skipTest('requires colors support')
Serhiy Storchaka0eb39e72016-05-21 21:36:11 +0300285 curses.start_color()
286 curses.init_pair(2, 1,1)
287 curses.color_content(1)
288 curses.color_pair(2)
289 curses.pair_content(curses.COLOR_PAIRS - 1)
290 curses.pair_number(0)
Zachary Warebaf45c52014-10-17 13:59:18 -0500291
Serhiy Storchaka0eb39e72016-05-21 21:36:11 +0300292 if hasattr(curses, 'use_default_colors'):
293 curses.use_default_colors()
Zachary Warebaf45c52014-10-17 13:59:18 -0500294
Serhiy Storchaka0eb39e72016-05-21 21:36:11 +0300295 @requires_curses_func('keyname')
296 def test_keyname(self):
297 curses.keyname(13)
Zachary Warebaf45c52014-10-17 13:59:18 -0500298
Serhiy Storchaka0eb39e72016-05-21 21:36:11 +0300299 @requires_curses_func('has_key')
300 def test_has_key(self):
301 curses.has_key(13)
Zachary Warebaf45c52014-10-17 13:59:18 -0500302
Serhiy Storchaka0eb39e72016-05-21 21:36:11 +0300303 @requires_curses_func('getmouse')
304 def test_getmouse(self):
305 (availmask, oldmask) = curses.mousemask(curses.BUTTON1_PRESSED)
306 if availmask == 0:
Xavier de Gaye645bc802017-01-06 09:50:27 +0100307 self.skipTest('mouse stuff not available')
Serhiy Storchaka0eb39e72016-05-21 21:36:11 +0300308 curses.mouseinterval(10)
309 # just verify these don't cause errors
310 curses.ungetmouse(0, 0, 0, 0, curses.BUTTON1_PRESSED)
311 m = curses.getmouse()
Zachary Warebaf45c52014-10-17 13:59:18 -0500312
Serhiy Storchakabaac01e2017-10-31 13:56:44 +0200313 @requires_curses_func('panel')
Zachary Warebaf45c52014-10-17 13:59:18 -0500314 def test_userptr_without_set(self):
315 w = curses.newwin(10, 10)
316 p = curses.panel.new_panel(w)
317 # try to access userptr() before calling set_userptr() -- segfaults
318 with self.assertRaises(curses.panel.error,
319 msg='userptr should fail since not set'):
320 p.userptr()
321
Serhiy Storchakabaac01e2017-10-31 13:56:44 +0200322 @requires_curses_func('panel')
Zachary Warebaf45c52014-10-17 13:59:18 -0500323 def test_userptr_memory_leak(self):
324 w = curses.newwin(10, 10)
325 p = curses.panel.new_panel(w)
326 obj = object()
327 nrefs = sys.getrefcount(obj)
328 for i in range(100):
329 p.set_userptr(obj)
330
331 p.set_userptr(None)
332 self.assertEqual(sys.getrefcount(obj), nrefs,
333 "set_userptr leaked references")
334
Serhiy Storchakabaac01e2017-10-31 13:56:44 +0200335 @requires_curses_func('panel')
Zachary Warebaf45c52014-10-17 13:59:18 -0500336 def test_userptr_segfault(self):
Serhiy Storchakaa7723d82017-11-03 20:29:33 +0200337 w = curses.newwin(10, 10)
338 panel = curses.panel.new_panel(w)
Zachary Warebaf45c52014-10-17 13:59:18 -0500339 class A:
340 def __del__(self):
341 panel.set_userptr(None)
342 panel.set_userptr(A())
343 panel.set_userptr(None)
344
Serhiy Storchakabaac01e2017-10-31 13:56:44 +0200345 @requires_curses_func('panel')
Serhiy Storchakae3f1b092016-05-08 20:46:22 +0300346 def test_new_curses_panel(self):
Serhiy Storchakaa7723d82017-11-03 20:29:33 +0200347 w = curses.newwin(10, 10)
348 panel = curses.panel.new_panel(w)
Serhiy Storchakae3f1b092016-05-08 20:46:22 +0300349 self.assertRaises(TypeError, type(panel))
350
Serhiy Storchaka0eb39e72016-05-21 21:36:11 +0300351 @requires_curses_func('is_term_resized')
352 def test_is_term_resized(self):
353 curses.is_term_resized(*self.stdscr.getmaxyx())
354
355 @requires_curses_func('resize_term')
Zachary Warebaf45c52014-10-17 13:59:18 -0500356 def test_resize_term(self):
Serhiy Storchaka0eb39e72016-05-21 21:36:11 +0300357 curses.resize_term(*self.stdscr.getmaxyx())
358
359 @requires_curses_func('resizeterm')
360 def test_resizeterm(self):
361 stdscr = self.stdscr
Zachary Warebaf45c52014-10-17 13:59:18 -0500362 lines, cols = curses.LINES, curses.COLS
363 new_lines = lines - 1
364 new_cols = cols + 1
365 curses.resizeterm(new_lines, new_cols)
366
367 self.assertEqual(curses.LINES, new_lines)
368 self.assertEqual(curses.COLS, new_cols)
369
370 def test_issue6243(self):
371 curses.ungetch(1025)
372 self.stdscr.getkey()
373
Serhiy Storchaka0eb39e72016-05-21 21:36:11 +0300374 @requires_curses_func('unget_wch')
Serhiy Storchakab232df92018-10-30 13:22:42 +0200375 @unittest.skipIf(getattr(curses, 'ncurses_version', (99,)) < (5, 8),
376 "unget_wch is broken in ncurses 5.7 and earlier")
Zachary Warebaf45c52014-10-17 13:59:18 -0500377 def test_unget_wch(self):
378 stdscr = self.stdscr
379 encoding = stdscr.encoding
380 for ch in ('a', '\xe9', '\u20ac', '\U0010FFFF'):
381 try:
382 ch.encode(encoding)
383 except UnicodeEncodeError:
384 continue
385 try:
386 curses.unget_wch(ch)
387 except Exception as err:
388 self.fail("unget_wch(%a) failed with encoding %s: %s"
389 % (ch, stdscr.encoding, err))
390 read = stdscr.get_wch()
391 self.assertEqual(read, ch)
392
393 code = ord(ch)
394 curses.unget_wch(code)
395 read = stdscr.get_wch()
396 self.assertEqual(read, ch)
397
398 def test_issue10570(self):
399 b = curses.tparm(curses.tigetstr("cup"), 5, 3)
400 self.assertIs(type(b), bytes)
Zachary Warebaf45c52014-10-17 13:59:18 -0500401
402 def test_encoding(self):
403 stdscr = self.stdscr
404 import codecs
405 encoding = stdscr.encoding
406 codecs.lookup(encoding)
Zachary Warebaf45c52014-10-17 13:59:18 -0500407 with self.assertRaises(TypeError):
408 stdscr.encoding = 10
Zachary Warebaf45c52014-10-17 13:59:18 -0500409 stdscr.encoding = encoding
410 with self.assertRaises(TypeError):
411 del stdscr.encoding
412
413 def test_issue21088(self):
414 stdscr = self.stdscr
415 #
416 # http://bugs.python.org/issue21088
417 #
418 # the bug:
419 # when converting curses.window.addch to Argument Clinic
420 # the first two parameters were switched.
421
422 # if someday we can represent the signature of addch
423 # we will need to rewrite this test.
424 try:
425 signature = inspect.signature(stdscr.addch)
426 self.assertFalse(signature)
427 except ValueError:
428 # not generating a signature is fine.
429 pass
430
431 # So. No signature for addch.
432 # But Argument Clinic gave us a human-readable equivalent
433 # as the first line of the docstring. So we parse that,
434 # and ensure that the parameters appear in the correct order.
435 # Since this is parsing output from Argument Clinic, we can
436 # be reasonably certain the generated parsing code will be
437 # correct too.
438 human_readable_signature = stdscr.addch.__doc__.split("\n")[0]
Serhiy Storchaka0eb39e72016-05-21 21:36:11 +0300439 self.assertIn("[y, x,]", human_readable_signature)
440
Serhiy Storchakabdf9e0e2016-12-28 10:16:06 +0200441 def test_issue13051(self):
442 stdscr = self.stdscr
Serhiy Storchaka894ebd02017-11-01 14:34:20 +0200443 if not hasattr(stdscr, 'resize'):
444 raise unittest.SkipTest('requires curses.window.resize')
Serhiy Storchakabdf9e0e2016-12-28 10:16:06 +0200445 box = curses.textpad.Textbox(stdscr, insert_mode=True)
446 lines, cols = stdscr.getmaxyx()
447 stdscr.resize(lines-2, cols-2)
448 # this may cause infinite recursion, leading to a RuntimeError
449 box._insert_printable_char('a')
450
Serhiy Storchaka0eb39e72016-05-21 21:36:11 +0300451
452class MiscTests(unittest.TestCase):
Zachary Warebaf45c52014-10-17 13:59:18 -0500453
Berker Peksag53926f12016-08-19 17:59:01 +0300454 @requires_curses_func('update_lines_cols')
Steve Dowerd2bc3892015-04-15 18:06:05 -0400455 def test_update_lines_cols(self):
456 # this doesn't actually test that LINES and COLS are updated,
457 # because we can't automate changing them. See Issue #4254 for
458 # a manual test script. We can only test that the function
459 # can be called.
460 curses.update_lines_cols()
461
Serhiy Storchakab232df92018-10-30 13:22:42 +0200462 @requires_curses_func('ncurses_version')
463 def test_ncurses_version(self):
464 v = curses.ncurses_version
465 self.assertIsInstance(v[:], tuple)
466 self.assertEqual(len(v), 3)
467 self.assertIsInstance(v[0], int)
468 self.assertIsInstance(v[1], int)
469 self.assertIsInstance(v[2], int)
470 self.assertIsInstance(v.major, int)
471 self.assertIsInstance(v.minor, int)
472 self.assertIsInstance(v.patch, int)
473 self.assertEqual(v[0], v.major)
474 self.assertEqual(v[1], v.minor)
475 self.assertEqual(v[2], v.patch)
476 self.assertGreaterEqual(v.major, 0)
477 self.assertGreaterEqual(v.minor, 0)
478 self.assertGreaterEqual(v.patch, 0)
Alexandre Vassalotti5ff02352009-07-22 21:27:53 +0000479
Serhiy Storchaka0eb39e72016-05-21 21:36:11 +0300480class TestAscii(unittest.TestCase):
481
Serhiy Storchaka514f9732016-06-18 22:08:11 +0300482 def test_controlnames(self):
483 for name in curses.ascii.controlnames:
484 self.assertTrue(hasattr(curses.ascii, name), name)
485
486 def test_ctypes(self):
487 def check(func, expected):
488 with self.subTest(ch=c, func=func):
489 self.assertEqual(func(i), expected)
490 self.assertEqual(func(c), expected)
491
492 for i in range(256):
493 c = chr(i)
494 b = bytes([i])
495 check(curses.ascii.isalnum, b.isalnum())
496 check(curses.ascii.isalpha, b.isalpha())
497 check(curses.ascii.isdigit, b.isdigit())
498 check(curses.ascii.islower, b.islower())
499 check(curses.ascii.isspace, b.isspace())
500 check(curses.ascii.isupper, b.isupper())
501
502 check(curses.ascii.isascii, i < 128)
503 check(curses.ascii.ismeta, i >= 128)
504 check(curses.ascii.isctrl, i < 32)
505 check(curses.ascii.iscntrl, i < 32 or i == 127)
506 check(curses.ascii.isblank, c in ' \t')
507 check(curses.ascii.isgraph, 32 < i <= 126)
508 check(curses.ascii.isprint, 32 <= i <= 126)
509 check(curses.ascii.ispunct, c in string.punctuation)
510 check(curses.ascii.isxdigit, c in string.hexdigits)
511
Serhiy Storchaka283de2b2016-12-28 10:04:27 +0200512 for i in (-2, -1, 256, sys.maxunicode, sys.maxunicode+1):
513 self.assertFalse(curses.ascii.isalnum(i))
514 self.assertFalse(curses.ascii.isalpha(i))
515 self.assertFalse(curses.ascii.isdigit(i))
516 self.assertFalse(curses.ascii.islower(i))
517 self.assertFalse(curses.ascii.isspace(i))
518 self.assertFalse(curses.ascii.isupper(i))
519
520 self.assertFalse(curses.ascii.isascii(i))
521 self.assertFalse(curses.ascii.isctrl(i))
522 self.assertFalse(curses.ascii.iscntrl(i))
523 self.assertFalse(curses.ascii.isblank(i))
524 self.assertFalse(curses.ascii.isgraph(i))
525 self.assertFalse(curses.ascii.isprint(i))
526 self.assertFalse(curses.ascii.ispunct(i))
527 self.assertFalse(curses.ascii.isxdigit(i))
528
529 self.assertFalse(curses.ascii.ismeta(-1))
530
Serhiy Storchaka514f9732016-06-18 22:08:11 +0300531 def test_ascii(self):
532 ascii = curses.ascii.ascii
533 self.assertEqual(ascii('\xc1'), 'A')
534 self.assertEqual(ascii('A'), 'A')
535 self.assertEqual(ascii(ord('\xc1')), ord('A'))
536
537 def test_ctrl(self):
538 ctrl = curses.ascii.ctrl
539 self.assertEqual(ctrl('J'), '\n')
540 self.assertEqual(ctrl('\n'), '\n')
541 self.assertEqual(ctrl('@'), '\0')
542 self.assertEqual(ctrl(ord('J')), ord('\n'))
543
544 def test_alt(self):
545 alt = curses.ascii.alt
546 self.assertEqual(alt('\n'), '\x8a')
547 self.assertEqual(alt('A'), '\xc1')
548 self.assertEqual(alt(ord('A')), 0xc1)
549
Serhiy Storchaka0eb39e72016-05-21 21:36:11 +0300550 def test_unctrl(self):
551 unctrl = curses.ascii.unctrl
552 self.assertEqual(unctrl('a'), 'a')
553 self.assertEqual(unctrl('A'), 'A')
554 self.assertEqual(unctrl(';'), ';')
555 self.assertEqual(unctrl(' '), ' ')
556 self.assertEqual(unctrl('\x7f'), '^?')
557 self.assertEqual(unctrl('\n'), '^J')
558 self.assertEqual(unctrl('\0'), '^@')
Serhiy Storchaka514f9732016-06-18 22:08:11 +0300559 self.assertEqual(unctrl(ord('A')), 'A')
560 self.assertEqual(unctrl(ord('\n')), '^J')
Serhiy Storchaka0eb39e72016-05-21 21:36:11 +0300561 # Meta-bit characters
562 self.assertEqual(unctrl('\x8a'), '!^J')
563 self.assertEqual(unctrl('\xc1'), '!A')
Serhiy Storchaka514f9732016-06-18 22:08:11 +0300564 self.assertEqual(unctrl(ord('\x8a')), '!^J')
565 self.assertEqual(unctrl(ord('\xc1')), '!A')
Serhiy Storchaka0eb39e72016-05-21 21:36:11 +0300566
567
Alexandre Vassalotti5ff02352009-07-22 21:27:53 +0000568if __name__ == '__main__':
Zachary Warebaf45c52014-10-17 13:59:18 -0500569 unittest.main()