##// END OF EJS Templates
Properly cleanup Tee, which reveals some resource leakage....
Matthias Bussonnier -
Show More
@@ -1,93 +1,93 b''
1 # encoding: utf-8
1 # encoding: utf-8
2 """Tests for io.py"""
2 """Tests for io.py"""
3
3
4 # Copyright (c) IPython Development Team.
4 # Copyright (c) IPython Development Team.
5 # Distributed under the terms of the Modified BSD License.
5 # Distributed under the terms of the Modified BSD License.
6
6
7
7
8 import io as stdlib_io
8 import io as stdlib_io
9 import os.path
9 import os.path
10 import stat
10 import stat
11 import sys
11 import sys
12 from io import StringIO
12 from io import StringIO
13
13
14 from subprocess import Popen, PIPE
14 from subprocess import Popen, PIPE
15 import unittest
15 import unittest
16
16
17 import nose.tools as nt
17 import nose.tools as nt
18
18
19 from IPython.testing.decorators import skipif, skip_win32
19 from IPython.testing.decorators import skipif, skip_win32
20 from IPython.utils.io import IOStream, Tee, capture_output
20 from IPython.utils.io import IOStream, Tee, capture_output
21 from IPython.utils.tempdir import TemporaryDirectory
21 from IPython.utils.tempdir import TemporaryDirectory
22
22
23
23
24 def test_tee_simple():
24 def test_tee_simple():
25 "Very simple check with stdout only"
25 "Very simple check with stdout only"
26 chan = StringIO()
26 chan = StringIO()
27 text = 'Hello'
27 text = 'Hello'
28 tee = Tee(chan, channel='stdout')
28 tee = Tee(chan, channel='stdout')
29 print(text, file=chan)
29 print(text, file=chan)
30 nt.assert_equal(chan.getvalue(), text+"\n")
30 nt.assert_equal(chan.getvalue(), text+"\n")
31
31
32
32
33 class TeeTestCase(unittest.TestCase):
33 class TeeTestCase(unittest.TestCase):
34
34
35 def tchan(self, channel, check='close'):
35 def tchan(self, channel):
36 trap = StringIO()
36 trap = StringIO()
37 chan = StringIO()
37 chan = StringIO()
38 text = 'Hello'
38 text = 'Hello'
39
39
40 std_ori = getattr(sys, channel)
40 std_ori = getattr(sys, channel)
41 setattr(sys, channel, trap)
41 setattr(sys, channel, trap)
42
42
43 tee = Tee(chan, channel=channel)
43 tee = Tee(chan, channel=channel)
44
44 print(text, end='', file=chan)
45 print(text, end='', file=chan)
45 setattr(sys, channel, std_ori)
46 trap_val = trap.getvalue()
46 trap_val = trap.getvalue()
47 nt.assert_equal(chan.getvalue(), text)
47 nt.assert_equal(chan.getvalue(), text)
48 if check=='close':
48
49 tee.close()
49 tee.close()
50 else:
50
51 del tee
51 setattr(sys, channel, std_ori)
52 assert getattr(sys, channel) == std_ori
52
53
53 def test(self):
54 def test(self):
54 for chan in ['stdout', 'stderr']:
55 for chan in ['stdout', 'stderr']:
55 for check in ['close', 'del']:
56 self.tchan(chan)
56 self.tchan(chan, check)
57
57
58 def test_io_init():
58 def test_io_init():
59 """Test that io.stdin/out/err exist at startup"""
59 """Test that io.stdin/out/err exist at startup"""
60 for name in ('stdin', 'stdout', 'stderr'):
60 for name in ('stdin', 'stdout', 'stderr'):
61 cmd = "from IPython.utils import io;print(io.%s.__class__)"%name
61 cmd = "from IPython.utils import io;print(io.%s.__class__)"%name
62 p = Popen([sys.executable, '-c', cmd],
62 with Popen([sys.executable, '-c', cmd], stdout=PIPE) as p:
63 stdout=PIPE)
63 p.wait()
64 p.wait()
64 classname = p.stdout.read().strip().decode('ascii')
65 classname = p.stdout.read().strip().decode('ascii')
66 # __class__ is a reference to the class object in Python 3, so we can't
65 # __class__ is a reference to the class object in Python 3, so we can't
67 # just test for string equality.
66 # just test for string equality.
68 assert 'IPython.utils.io.IOStream' in classname, classname
67 assert 'IPython.utils.io.IOStream' in classname, classname
69
68
70 def test_IOStream_init():
69 def test_IOStream_init():
71 """IOStream initializes from a file-like object missing attributes. """
70 """IOStream initializes from a file-like object missing attributes. """
72 # Cause a failure from getattr and dir(). (Issue #6386)
71 # Cause a failure from getattr and dir(). (Issue #6386)
73 class BadStringIO(StringIO):
72 class BadStringIO(StringIO):
74 def __dir__(self):
73 def __dir__(self):
75 attrs = super(StringIO, self).__dir__()
74 attrs = super(StringIO, self).__dir__()
76 attrs.append('name')
75 attrs.append('name')
77 return attrs
76 return attrs
78
77
79 iostream = IOStream(BadStringIO())
78 iostream = IOStream(BadStringIO())
80 iostream.write('hi, bad iostream\n')
79 iostream.write('hi, bad iostream\n')
81 assert not hasattr(iostream, 'name')
80 assert not hasattr(iostream, 'name')
81 iostream.close()
82
82
83 def test_capture_output():
83 def test_capture_output():
84 """capture_output() context works"""
84 """capture_output() context works"""
85
85
86 with capture_output() as io:
86 with capture_output() as io:
87 print('hi, stdout')
87 print('hi, stdout')
88 print('hi, stderr', file=sys.stderr)
88 print('hi, stderr', file=sys.stderr)
89
89
90 nt.assert_equal(io.stdout, 'hi, stdout\n')
90 nt.assert_equal(io.stdout, 'hi, stdout\n')
91 nt.assert_equal(io.stderr, 'hi, stderr\n')
91 nt.assert_equal(io.stderr, 'hi, stderr\n')
92
92
93
93
General Comments 0
You need to be logged in to leave comments. Login now