@@ -47,37 +47,57 @@ class TestCurses(unittest.TestCase):
47
47
48
48
@classmethod
49
49
def setUpClass (cls ):
50
- if not sys .__stdout__ .isatty ():
51
- # Temporary skip tests on non-tty
52
- raise unittest .SkipTest ('sys.__stdout__ is not a tty' )
53
- cls .tmp = tempfile .TemporaryFile ()
54
- fd = cls .tmp .fileno ()
55
- else :
56
- cls .tmp = None
57
- fd = sys .__stdout__ .fileno ()
58
50
# testing setupterm() inside initscr/endwin
59
51
# 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
52
+ stdout_fd = sys .__stdout__ .fileno ()
53
+ curses .setupterm (fd = stdout_fd )
67
54
68
55
def setUp (self ):
56
+ self .isatty = True
57
+ self .output = sys .__stdout__
58
+ stdout_fd = sys .__stdout__ .fileno ()
59
+ if not sys .__stdout__ .isatty ():
60
+ # initstr() unconditionally uses C stdout.
61
+ # If it is redirected to file or pipe, try to attach it
62
+ # to terminal.
63
+ # First, save a copy of the file descriptor of stdout, so it
64
+ # can be restored after finishing the test.
65
+ dup_fd = os .dup (stdout_fd )
66
+ self .addCleanup (os .close , dup_fd )
67
+ self .addCleanup (os .dup2 , dup_fd , stdout_fd )
68
+
69
+ if sys .__stderr__ .isatty ():
70
+ # If stderr is connected to terminal, use it.
71
+ tmp = sys .__stderr__
72
+ self .output = sys .__stderr__
73
+ else :
74
+ try :
75
+ # Try to open the terminal device.
76
+ tmp = open ('/dev/tty' , 'wb' , buffering = 0 )
77
+ except OSError :
78
+ # As a fallback, use regular file to write control codes.
79
+ # Some functions (like savetty) will not work, but at
80
+ # least the garbage control sequences will not be mixed
81
+ # with the testing report.
82
+ tmp = tempfile .TemporaryFile (mode = 'wb' , buffering = 0 )
83
+ self .isatty = False
84
+ self .addCleanup (tmp .close )
85
+ self .output = None
86
+ os .dup2 (tmp .fileno (), stdout_fd )
87
+
69
88
self .save_signals = SaveSignals ()
70
89
self .save_signals .save ()
71
- if verbose :
90
+ self .addCleanup (self .save_signals .restore )
91
+ if verbose and self .output is not None :
72
92
# just to make the test output a little more readable
73
- print ()
93
+ sys .stderr .flush ()
94
+ sys .stdout .flush ()
95
+ print (file = self .output , flush = True )
74
96
self .stdscr = curses .initscr ()
75
- curses .savetty ()
76
-
77
- def tearDown (self ):
78
- curses .resetty ()
79
- curses .endwin ()
80
- self .save_signals .restore ()
97
+ if self .isatty :
98
+ curses .savetty ()
99
+ self .addCleanup (curses .endwin )
100
+ self .addCleanup (curses .resetty )
81
101
82
102
def test_window_funcs (self ):
83
103
"Test the methods of windows"
@@ -95,7 +115,7 @@ def test_window_funcs(self):
95
115
for meth in [stdscr .clear , stdscr .clrtobot ,
96
116
stdscr .clrtoeol , stdscr .cursyncup , stdscr .delch ,
97
117
stdscr .deleteln , stdscr .erase , stdscr .getbegyx ,
98
- stdscr .getbkgd , stdscr .getkey , stdscr . getmaxyx ,
118
+ stdscr .getbkgd , stdscr .getmaxyx ,
99
119
stdscr .getparyx , stdscr .getyx , stdscr .inch ,
100
120
stdscr .insertln , stdscr .instr , stdscr .is_wintouched ,
101
121
win .noutrefresh , stdscr .redrawwin , stdscr .refresh ,
@@ -206,6 +226,11 @@ def test_window_funcs(self):
206
226
if hasattr (stdscr , 'enclose' ):
207
227
stdscr .enclose (10 , 10 )
208
228
229
+ with tempfile .TemporaryFile () as f :
230
+ self .stdscr .putwin (f )
231
+ f .seek (0 )
232
+ curses .getwin (f )
233
+
209
234
self .assertRaises (ValueError , stdscr .getstr , - 400 )
210
235
self .assertRaises (ValueError , stdscr .getstr , 2 , 3 , - 400 )
211
236
self .assertRaises (ValueError , stdscr .instr , - 2 )
@@ -224,16 +249,19 @@ def test_embedded_null_chars(self):
224
249
def test_module_funcs (self ):
225
250
"Test module-level functions"
226
251
for func in [curses .baudrate , curses .beep , curses .can_change_color ,
227
- curses .cbreak , curses .def_prog_mode , curses .doupdate ,
228
- curses .flash , curses .flushinp ,
252
+ curses .doupdate , curses .flash , curses .flushinp ,
229
253
curses .has_colors , curses .has_ic , curses .has_il ,
230
254
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 ,
234
- curses .termname , curses .erasechar ]:
255
+ curses .noecho , curses .nonl , curses .noqiflush ,
256
+ curses .termattrs , curses .termname , curses .erasechar ]:
235
257
with self .subTest (func = func .__qualname__ ):
236
258
func ()
259
+ if self .isatty :
260
+ for func in [curses .cbreak , curses .def_prog_mode ,
261
+ curses .nocbreak , curses .noraw ,
262
+ curses .reset_prog_mode ]:
263
+ with self .subTest (func = func .__qualname__ ):
264
+ func ()
237
265
if hasattr (curses , 'filter' ):
238
266
curses .filter ()
239
267
if hasattr (curses , 'getsyx' ):
@@ -245,13 +273,9 @@ def test_module_funcs(self):
245
273
curses .delay_output (1 )
246
274
curses .echo () ; curses .echo (1 )
247
275
248
- with tempfile .TemporaryFile () as f :
249
- self .stdscr .putwin (f )
250
- f .seek (0 )
251
- curses .getwin (f )
252
-
253
276
curses .halfdelay (1 )
254
- curses .intrflush (1 )
277
+ if self .isatty :
278
+ curses .intrflush (1 )
255
279
curses .meta (1 )
256
280
curses .napms (100 )
257
281
curses .newpad (50 ,50 )
@@ -260,7 +284,8 @@ def test_module_funcs(self):
260
284
curses .nl () ; curses .nl (1 )
261
285
curses .putp (b'abc' )
262
286
curses .qiflush ()
263
- curses .raw () ; curses .raw (1 )
287
+ if self .isatty :
288
+ curses .raw () ; curses .raw (1 )
264
289
if hasattr (curses , 'setsyx' ):
265
290
curses .setsyx (5 ,5 )
266
291
curses .tigetflag ('hc' )
@@ -282,7 +307,7 @@ def test_colors_funcs(self):
282
307
curses .init_pair (2 , 1 ,1 )
283
308
curses .color_content (1 )
284
309
curses .color_pair (2 )
285
- curses .pair_content (curses .COLOR_PAIRS - 1 )
310
+ curses .pair_content (min ( curses .COLOR_PAIRS - 1 , 0x7fff ) )
286
311
curses .pair_number (0 )
287
312
288
313
if hasattr (curses , 'use_default_colors' ):
@@ -354,7 +379,6 @@ def test_resize_term(self):
354
379
355
380
@requires_curses_func ('resizeterm' )
356
381
def test_resizeterm (self ):
357
- stdscr = self .stdscr
358
382
lines , cols = curses .LINES , curses .COLS
359
383
new_lines = lines - 1
360
384
new_cols = cols + 1
0 commit comments