ยปCore Development>Code coverage>Lib/test/test_curses.py

Python code coverage for Lib/test/test_curses.py

#countcontent
1n/a#
2n/a# Test script for the curses module
3n/a#
4n/a# This script doesn't actually display anything very coherent. but it
5n/a# does call (nearly) every method and function.
6n/a#
7n/a# Functions not tested: {def,reset}_{shell,prog}_mode, getch(), getstr(),
8n/a# init_color()
9n/a# Only called, not tested: getmouse(), ungetmouse()
10n/a#
11n/a
12n/aimport os
13n/aimport string
14n/aimport sys
15n/aimport tempfile
16n/aimport unittest
17n/a
18n/afrom test.support import requires, import_module, verbose
19n/a
20n/a# Optionally test curses module. This currently requires that the
21n/a# 'curses' resource be given on the regrtest command line using the -u
22n/a# option. If not available, nothing after this line will be executed.
23n/aimport inspect
24n/arequires('curses')
25n/a
26n/a# If either of these don't exist, skip the tests.
27n/acurses = import_module('curses')
28n/aimport_module('curses.panel')
29n/aimport_module('curses.ascii')
30n/aimport_module('curses.textpad')
31n/a
32n/adef requires_curses_func(name):
33n/a return unittest.skipUnless(hasattr(curses, name),
34n/a 'requires curses.%s' % name)
35n/a
36n/aterm = os.environ.get('TERM')
37n/a
38n/a# If newterm was supported we could use it instead of initscr and not exit
39n/a@unittest.skipIf(not term or term == 'unknown',
40n/a "$TERM=%r, calling initscr() may cause exit" % term)
41n/a@unittest.skipIf(sys.platform == "cygwin",
42n/a "cygwin's curses mostly just hangs")
43n/aclass TestCurses(unittest.TestCase):
44n/a
45n/a @classmethod
46n/a def setUpClass(cls):
47n/a if not sys.__stdout__.isatty():
48n/a # Temporary skip tests on non-tty
49n/a raise unittest.SkipTest('sys.__stdout__ is not a tty')
50n/a cls.tmp = tempfile.TemporaryFile()
51n/a fd = cls.tmp.fileno()
52n/a else:
53n/a cls.tmp = None
54n/a fd = sys.__stdout__.fileno()
55n/a # testing setupterm() inside initscr/endwin
56n/a # causes terminal breakage
57n/a curses.setupterm(fd=fd)
58n/a
59n/a @classmethod
60n/a def tearDownClass(cls):
61n/a if cls.tmp:
62n/a cls.tmp.close()
63n/a del cls.tmp
64n/a
65n/a def setUp(self):
66n/a if verbose:
67n/a # just to make the test output a little more readable
68n/a print()
69n/a self.stdscr = curses.initscr()
70n/a curses.savetty()
71n/a
72n/a def tearDown(self):
73n/a curses.resetty()
74n/a curses.endwin()
75n/a
76n/a def test_window_funcs(self):
77n/a "Test the methods of windows"
78n/a stdscr = self.stdscr
79n/a win = curses.newwin(10,10)
80n/a win = curses.newwin(5,5, 5,5)
81n/a win2 = curses.newwin(15,15, 5,5)
82n/a
83n/a for meth in [stdscr.addch, stdscr.addstr]:
84n/a for args in [('a'), ('a', curses.A_BOLD),
85n/a (4,4, 'a'), (5,5, 'a', curses.A_BOLD)]:
86n/a with self.subTest(meth=meth.__qualname__, args=args):
87n/a meth(*args)
88n/a
89n/a for meth in [stdscr.box, stdscr.clear, stdscr.clrtobot,
90n/a stdscr.clrtoeol, stdscr.cursyncup, stdscr.delch,
91n/a stdscr.deleteln, stdscr.erase, stdscr.getbegyx,
92n/a stdscr.getbkgd, stdscr.getkey, stdscr.getmaxyx,
93n/a stdscr.getparyx, stdscr.getyx, stdscr.inch,
94n/a stdscr.insertln, stdscr.instr, stdscr.is_wintouched,
95n/a win.noutrefresh, stdscr.redrawwin, stdscr.refresh,
96n/a stdscr.standout, stdscr.standend, stdscr.syncdown,
97n/a stdscr.syncup, stdscr.touchwin, stdscr.untouchwin]:
98n/a with self.subTest(meth=meth.__qualname__):
99n/a meth()
100n/a
101n/a stdscr.addnstr('1234', 3)
102n/a stdscr.addnstr('1234', 3, curses.A_BOLD)
103n/a stdscr.addnstr(4,4, '1234', 3)
104n/a stdscr.addnstr(5,5, '1234', 3, curses.A_BOLD)
105n/a
106n/a stdscr.attron(curses.A_BOLD)
107n/a stdscr.attroff(curses.A_BOLD)
108n/a stdscr.attrset(curses.A_BOLD)
109n/a stdscr.bkgd(' ')
110n/a stdscr.bkgd(' ', curses.A_REVERSE)
111n/a stdscr.bkgdset(' ')
112n/a stdscr.bkgdset(' ', curses.A_REVERSE)
113n/a
114n/a win.border(65, 66, 67, 68,
115n/a 69, 70, 71, 72)
116n/a win.border('|', '!', '-', '_',
117n/a '+', '\\', '#', '/')
118n/a with self.assertRaises(TypeError,
119n/a msg="Expected win.border() to raise TypeError"):
120n/a win.border(65, 66, 67, 68,
121n/a 69, [], 71, 72)
122n/a
123n/a stdscr.clearok(1)
124n/a
125n/a win4 = stdscr.derwin(2,2)
126n/a win4 = stdscr.derwin(1,1, 5,5)
127n/a win4.mvderwin(9,9)
128n/a
129n/a stdscr.echochar('a')
130n/a stdscr.echochar('a', curses.A_BOLD)
131n/a stdscr.hline('-', 5)
132n/a stdscr.hline('-', 5, curses.A_BOLD)
133n/a stdscr.hline(1,1,'-', 5)
134n/a stdscr.hline(1,1,'-', 5, curses.A_BOLD)
135n/a
136n/a stdscr.idcok(1)
137n/a stdscr.idlok(1)
138n/a stdscr.immedok(1)
139n/a stdscr.insch('c')
140n/a stdscr.insdelln(1)
141n/a stdscr.insnstr('abc', 3)
142n/a stdscr.insnstr('abc', 3, curses.A_BOLD)
143n/a stdscr.insnstr(5, 5, 'abc', 3)
144n/a stdscr.insnstr(5, 5, 'abc', 3, curses.A_BOLD)
145n/a
146n/a stdscr.insstr('def')
147n/a stdscr.insstr('def', curses.A_BOLD)
148n/a stdscr.insstr(5, 5, 'def')
149n/a stdscr.insstr(5, 5, 'def', curses.A_BOLD)
150n/a stdscr.is_linetouched(0)
151n/a stdscr.keypad(1)
152n/a stdscr.leaveok(1)
153n/a stdscr.move(3,3)
154n/a win.mvwin(2,2)
155n/a stdscr.nodelay(1)
156n/a stdscr.notimeout(1)
157n/a win2.overlay(win)
158n/a win2.overwrite(win)
159n/a win2.overlay(win, 1, 2, 2, 1, 3, 3)
160n/a win2.overwrite(win, 1, 2, 2, 1, 3, 3)
161n/a stdscr.redrawln(1,2)
162n/a
163n/a stdscr.scrollok(1)
164n/a stdscr.scroll()
165n/a stdscr.scroll(2)
166n/a stdscr.scroll(-3)
167n/a
168n/a stdscr.move(12, 2)
169n/a stdscr.setscrreg(10,15)
170n/a win3 = stdscr.subwin(10,10)
171n/a win3 = stdscr.subwin(10,10, 5,5)
172n/a stdscr.syncok(1)
173n/a stdscr.timeout(5)
174n/a stdscr.touchline(5,5)
175n/a stdscr.touchline(5,5,0)
176n/a stdscr.vline('a', 3)
177n/a stdscr.vline('a', 3, curses.A_STANDOUT)
178n/a stdscr.chgat(5, 2, 3, curses.A_BLINK)
179n/a stdscr.chgat(3, curses.A_BOLD)
180n/a stdscr.chgat(5, 8, curses.A_UNDERLINE)
181n/a stdscr.chgat(curses.A_BLINK)
182n/a stdscr.refresh()
183n/a
184n/a stdscr.vline(1,1, 'a', 3)
185n/a stdscr.vline(1,1, 'a', 3, curses.A_STANDOUT)
186n/a
187n/a if hasattr(curses, 'resize'):
188n/a stdscr.resize()
189n/a if hasattr(curses, 'enclose'):
190n/a stdscr.enclose()
191n/a
192n/a self.assertRaises(ValueError, stdscr.getstr, -400)
193n/a self.assertRaises(ValueError, stdscr.getstr, 2, 3, -400)
194n/a self.assertRaises(ValueError, stdscr.instr, -2)
195n/a self.assertRaises(ValueError, stdscr.instr, 2, 3, -2)
196n/a
197n/a
198n/a def test_module_funcs(self):
199n/a "Test module-level functions"
200n/a for func in [curses.baudrate, curses.beep, curses.can_change_color,
201n/a curses.cbreak, curses.def_prog_mode, curses.doupdate,
202n/a curses.filter, curses.flash, curses.flushinp,
203n/a curses.has_colors, curses.has_ic, curses.has_il,
204n/a curses.isendwin, curses.killchar, curses.longname,
205n/a curses.nocbreak, curses.noecho, curses.nonl,
206n/a curses.noqiflush, curses.noraw,
207n/a curses.reset_prog_mode, curses.termattrs,
208n/a curses.termname, curses.erasechar, curses.getsyx]:
209n/a with self.subTest(func=func.__qualname__):
210n/a func()
211n/a
212n/a # Functions that actually need arguments
213n/a if curses.tigetstr("cnorm"):
214n/a curses.curs_set(1)
215n/a curses.delay_output(1)
216n/a curses.echo() ; curses.echo(1)
217n/a
218n/a with tempfile.TemporaryFile() as f:
219n/a self.stdscr.putwin(f)
220n/a f.seek(0)
221n/a curses.getwin(f)
222n/a
223n/a curses.halfdelay(1)
224n/a curses.intrflush(1)
225n/a curses.meta(1)
226n/a curses.napms(100)
227n/a curses.newpad(50,50)
228n/a win = curses.newwin(5,5)
229n/a win = curses.newwin(5,5, 1,1)
230n/a curses.nl() ; curses.nl(1)
231n/a curses.putp(b'abc')
232n/a curses.qiflush()
233n/a curses.raw() ; curses.raw(1)
234n/a curses.setsyx(5,5)
235n/a curses.tigetflag('hc')
236n/a curses.tigetnum('co')
237n/a curses.tigetstr('cr')
238n/a curses.tparm(b'cr')
239n/a curses.typeahead(sys.__stdin__.fileno())
240n/a curses.unctrl('a')
241n/a curses.ungetch('a')
242n/a curses.use_env(1)
243n/a
244n/a # Functions only available on a few platforms
245n/a def test_colors_funcs(self):
246n/a if not curses.has_colors():
247n/a self.skipTest('requires colors support')
248n/a curses.start_color()
249n/a curses.init_pair(2, 1,1)
250n/a curses.color_content(1)
251n/a curses.color_pair(2)
252n/a curses.pair_content(curses.COLOR_PAIRS - 1)
253n/a curses.pair_number(0)
254n/a
255n/a if hasattr(curses, 'use_default_colors'):
256n/a curses.use_default_colors()
257n/a
258n/a @requires_curses_func('keyname')
259n/a def test_keyname(self):
260n/a curses.keyname(13)
261n/a
262n/a @requires_curses_func('has_key')
263n/a def test_has_key(self):
264n/a curses.has_key(13)
265n/a
266n/a @requires_curses_func('getmouse')
267n/a def test_getmouse(self):
268n/a (availmask, oldmask) = curses.mousemask(curses.BUTTON1_PRESSED)
269n/a if availmask == 0:
270n/a self.skipTest('mouse stuff not available')
271n/a curses.mouseinterval(10)
272n/a # just verify these don't cause errors
273n/a curses.ungetmouse(0, 0, 0, 0, curses.BUTTON1_PRESSED)
274n/a m = curses.getmouse()
275n/a
276n/a def test_userptr_without_set(self):
277n/a w = curses.newwin(10, 10)
278n/a p = curses.panel.new_panel(w)
279n/a # try to access userptr() before calling set_userptr() -- segfaults
280n/a with self.assertRaises(curses.panel.error,
281n/a msg='userptr should fail since not set'):
282n/a p.userptr()
283n/a
284n/a def test_userptr_memory_leak(self):
285n/a w = curses.newwin(10, 10)
286n/a p = curses.panel.new_panel(w)
287n/a obj = object()
288n/a nrefs = sys.getrefcount(obj)
289n/a for i in range(100):
290n/a p.set_userptr(obj)
291n/a
292n/a p.set_userptr(None)
293n/a self.assertEqual(sys.getrefcount(obj), nrefs,
294n/a "set_userptr leaked references")
295n/a
296n/a def test_userptr_segfault(self):
297n/a panel = curses.panel.new_panel(self.stdscr)
298n/a class A:
299n/a def __del__(self):
300n/a panel.set_userptr(None)
301n/a panel.set_userptr(A())
302n/a panel.set_userptr(None)
303n/a
304n/a def test_new_curses_panel(self):
305n/a panel = curses.panel.new_panel(self.stdscr)
306n/a self.assertRaises(TypeError, type(panel))
307n/a
308n/a @requires_curses_func('is_term_resized')
309n/a def test_is_term_resized(self):
310n/a curses.is_term_resized(*self.stdscr.getmaxyx())
311n/a
312n/a @requires_curses_func('resize_term')
313n/a def test_resize_term(self):
314n/a curses.resize_term(*self.stdscr.getmaxyx())
315n/a
316n/a @requires_curses_func('resizeterm')
317n/a def test_resizeterm(self):
318n/a stdscr = self.stdscr
319n/a lines, cols = curses.LINES, curses.COLS
320n/a new_lines = lines - 1
321n/a new_cols = cols + 1
322n/a curses.resizeterm(new_lines, new_cols)
323n/a
324n/a self.assertEqual(curses.LINES, new_lines)
325n/a self.assertEqual(curses.COLS, new_cols)
326n/a
327n/a def test_issue6243(self):
328n/a curses.ungetch(1025)
329n/a self.stdscr.getkey()
330n/a
331n/a @requires_curses_func('unget_wch')
332n/a def test_unget_wch(self):
333n/a stdscr = self.stdscr
334n/a encoding = stdscr.encoding
335n/a for ch in ('a', '\xe9', '\u20ac', '\U0010FFFF'):
336n/a try:
337n/a ch.encode(encoding)
338n/a except UnicodeEncodeError:
339n/a continue
340n/a try:
341n/a curses.unget_wch(ch)
342n/a except Exception as err:
343n/a self.fail("unget_wch(%a) failed with encoding %s: %s"
344n/a % (ch, stdscr.encoding, err))
345n/a read = stdscr.get_wch()
346n/a self.assertEqual(read, ch)
347n/a
348n/a code = ord(ch)
349n/a curses.unget_wch(code)
350n/a read = stdscr.get_wch()
351n/a self.assertEqual(read, ch)
352n/a
353n/a def test_issue10570(self):
354n/a b = curses.tparm(curses.tigetstr("cup"), 5, 3)
355n/a self.assertIs(type(b), bytes)
356n/a
357n/a def test_encoding(self):
358n/a stdscr = self.stdscr
359n/a import codecs
360n/a encoding = stdscr.encoding
361n/a codecs.lookup(encoding)
362n/a with self.assertRaises(TypeError):
363n/a stdscr.encoding = 10
364n/a stdscr.encoding = encoding
365n/a with self.assertRaises(TypeError):
366n/a del stdscr.encoding
367n/a
368n/a def test_issue21088(self):
369n/a stdscr = self.stdscr
370n/a #
371n/a # http://bugs.python.org/issue21088
372n/a #
373n/a # the bug:
374n/a # when converting curses.window.addch to Argument Clinic
375n/a # the first two parameters were switched.
376n/a
377n/a # if someday we can represent the signature of addch
378n/a # we will need to rewrite this test.
379n/a try:
380n/a signature = inspect.signature(stdscr.addch)
381n/a self.assertFalse(signature)
382n/a except ValueError:
383n/a # not generating a signature is fine.
384n/a pass
385n/a
386n/a # So. No signature for addch.
387n/a # But Argument Clinic gave us a human-readable equivalent
388n/a # as the first line of the docstring. So we parse that,
389n/a # and ensure that the parameters appear in the correct order.
390n/a # Since this is parsing output from Argument Clinic, we can
391n/a # be reasonably certain the generated parsing code will be
392n/a # correct too.
393n/a human_readable_signature = stdscr.addch.__doc__.split("\n")[0]
394n/a self.assertIn("[y, x,]", human_readable_signature)
395n/a
396n/a def test_issue13051(self):
397n/a stdscr = self.stdscr
398n/a box = curses.textpad.Textbox(stdscr, insert_mode=True)
399n/a lines, cols = stdscr.getmaxyx()
400n/a stdscr.resize(lines-2, cols-2)
401n/a # this may cause infinite recursion, leading to a RuntimeError
402n/a box._insert_printable_char('a')
403n/a
404n/a
405n/aclass MiscTests(unittest.TestCase):
406n/a
407n/a @requires_curses_func('update_lines_cols')
408n/a def test_update_lines_cols(self):
409n/a # this doesn't actually test that LINES and COLS are updated,
410n/a # because we can't automate changing them. See Issue #4254 for
411n/a # a manual test script. We can only test that the function
412n/a # can be called.
413n/a curses.update_lines_cols()
414n/a
415n/a
416n/aclass TestAscii(unittest.TestCase):
417n/a
418n/a def test_controlnames(self):
419n/a for name in curses.ascii.controlnames:
420n/a self.assertTrue(hasattr(curses.ascii, name), name)
421n/a
422n/a def test_ctypes(self):
423n/a def check(func, expected):
424n/a with self.subTest(ch=c, func=func):
425n/a self.assertEqual(func(i), expected)
426n/a self.assertEqual(func(c), expected)
427n/a
428n/a for i in range(256):
429n/a c = chr(i)
430n/a b = bytes([i])
431n/a check(curses.ascii.isalnum, b.isalnum())
432n/a check(curses.ascii.isalpha, b.isalpha())
433n/a check(curses.ascii.isdigit, b.isdigit())
434n/a check(curses.ascii.islower, b.islower())
435n/a check(curses.ascii.isspace, b.isspace())
436n/a check(curses.ascii.isupper, b.isupper())
437n/a
438n/a check(curses.ascii.isascii, i < 128)
439n/a check(curses.ascii.ismeta, i >= 128)
440n/a check(curses.ascii.isctrl, i < 32)
441n/a check(curses.ascii.iscntrl, i < 32 or i == 127)
442n/a check(curses.ascii.isblank, c in ' \t')
443n/a check(curses.ascii.isgraph, 32 < i <= 126)
444n/a check(curses.ascii.isprint, 32 <= i <= 126)
445n/a check(curses.ascii.ispunct, c in string.punctuation)
446n/a check(curses.ascii.isxdigit, c in string.hexdigits)
447n/a
448n/a for i in (-2, -1, 256, sys.maxunicode, sys.maxunicode+1):
449n/a self.assertFalse(curses.ascii.isalnum(i))
450n/a self.assertFalse(curses.ascii.isalpha(i))
451n/a self.assertFalse(curses.ascii.isdigit(i))
452n/a self.assertFalse(curses.ascii.islower(i))
453n/a self.assertFalse(curses.ascii.isspace(i))
454n/a self.assertFalse(curses.ascii.isupper(i))
455n/a
456n/a self.assertFalse(curses.ascii.isascii(i))
457n/a self.assertFalse(curses.ascii.isctrl(i))
458n/a self.assertFalse(curses.ascii.iscntrl(i))
459n/a self.assertFalse(curses.ascii.isblank(i))
460n/a self.assertFalse(curses.ascii.isgraph(i))
461n/a self.assertFalse(curses.ascii.isprint(i))
462n/a self.assertFalse(curses.ascii.ispunct(i))
463n/a self.assertFalse(curses.ascii.isxdigit(i))
464n/a
465n/a self.assertFalse(curses.ascii.ismeta(-1))
466n/a
467n/a def test_ascii(self):
468n/a ascii = curses.ascii.ascii
469n/a self.assertEqual(ascii('\xc1'), 'A')
470n/a self.assertEqual(ascii('A'), 'A')
471n/a self.assertEqual(ascii(ord('\xc1')), ord('A'))
472n/a
473n/a def test_ctrl(self):
474n/a ctrl = curses.ascii.ctrl
475n/a self.assertEqual(ctrl('J'), '\n')
476n/a self.assertEqual(ctrl('\n'), '\n')
477n/a self.assertEqual(ctrl('@'), '\0')
478n/a self.assertEqual(ctrl(ord('J')), ord('\n'))
479n/a
480n/a def test_alt(self):
481n/a alt = curses.ascii.alt
482n/a self.assertEqual(alt('\n'), '\x8a')
483n/a self.assertEqual(alt('A'), '\xc1')
484n/a self.assertEqual(alt(ord('A')), 0xc1)
485n/a
486n/a def test_unctrl(self):
487n/a unctrl = curses.ascii.unctrl
488n/a self.assertEqual(unctrl('a'), 'a')
489n/a self.assertEqual(unctrl('A'), 'A')
490n/a self.assertEqual(unctrl(';'), ';')
491n/a self.assertEqual(unctrl(' '), ' ')
492n/a self.assertEqual(unctrl('\x7f'), '^?')
493n/a self.assertEqual(unctrl('\n'), '^J')
494n/a self.assertEqual(unctrl('\0'), '^@')
495n/a self.assertEqual(unctrl(ord('A')), 'A')
496n/a self.assertEqual(unctrl(ord('\n')), '^J')
497n/a # Meta-bit characters
498n/a self.assertEqual(unctrl('\x8a'), '!^J')
499n/a self.assertEqual(unctrl('\xc1'), '!A')
500n/a self.assertEqual(unctrl(ord('\x8a')), '!^J')
501n/a self.assertEqual(unctrl(ord('\xc1')), '!A')
502n/a
503n/a
504n/aif __name__ == '__main__':
505n/a unittest.main()