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