Show More
@@ -60,9 +60,9 b' import nosepatch # monkeypatch nose' | |||||
60 |
|
60 | |||
61 | # We already have python3-compliant code for parametric tests |
|
61 | # We already have python3-compliant code for parametric tests | |
62 | if sys.version[0]=='2': |
|
62 | if sys.version[0]=='2': | |
63 | from _paramtestpy2 import parametric |
|
63 | from _paramtestpy2 import parametric, ParametricTestCase | |
64 | else: |
|
64 | else: | |
65 | from _paramtestpy3 import parametric |
|
65 | from _paramtestpy3 import parametric, ParametricTestCase | |
66 |
|
66 | |||
67 | # Expose the unittest-driven decorators |
|
67 | # Expose the unittest-driven decorators | |
68 | from ipunittest import ipdoctest, ipdocstring |
|
68 | from ipunittest import ipdoctest, ipdocstring |
@@ -105,6 +105,65 b" if sys.platform == 'win32' and readline.have_readline:" | |||||
105 | Term = IOTerm(cout=readline._outputfile,cerr=readline._outputfile) |
|
105 | Term = IOTerm(cout=readline._outputfile,cerr=readline._outputfile) | |
106 |
|
106 | |||
107 |
|
107 | |||
|
108 | class Tee(object): | |||
|
109 | """A class to duplicate an output stream to stdout/err. | |||
|
110 | ||||
|
111 | This works in a manner very similar to the Unix 'tee' command. | |||
|
112 | ||||
|
113 | When the object is closed or deleted, it closes the original file given to | |||
|
114 | it for duplication. | |||
|
115 | """ | |||
|
116 | # Inspired by: | |||
|
117 | # http://mail.python.org/pipermail/python-list/2007-May/442737.html | |||
|
118 | ||||
|
119 | def __init__(self, file, mode=None, channel='stdout'): | |||
|
120 | """Construct a new Tee object. | |||
|
121 | ||||
|
122 | Parameters | |||
|
123 | ---------- | |||
|
124 | file : filename or open filehandle (writable) | |||
|
125 | File that will be duplicated | |||
|
126 | ||||
|
127 | mode : optional, valid mode for open(). | |||
|
128 | If a filename was give, open with this mode. | |||
|
129 | ||||
|
130 | channel : str, one of ['stdout', 'stderr'] | |||
|
131 | """ | |||
|
132 | if channel not in ['stdout', 'stderr']: | |||
|
133 | raise ValueError('Invalid channel spec %s' % channel) | |||
|
134 | ||||
|
135 | if hasattr(file, 'write') and hasattr(file, 'seek'): | |||
|
136 | self.file = file | |||
|
137 | else: | |||
|
138 | self.file = open(name, mode) | |||
|
139 | self.channel = channel | |||
|
140 | self.ostream = getattr(sys, channel) | |||
|
141 | setattr(sys, channel, self) | |||
|
142 | self._closed = False | |||
|
143 | ||||
|
144 | def close(self): | |||
|
145 | """Close the file and restore the channel.""" | |||
|
146 | self.flush() | |||
|
147 | setattr(sys, self.channel, self.ostream) | |||
|
148 | self.file.close() | |||
|
149 | self._closed = True | |||
|
150 | ||||
|
151 | def write(self, data): | |||
|
152 | """Write data to both channels.""" | |||
|
153 | self.file.write(data) | |||
|
154 | self.ostream.write(data) | |||
|
155 | self.ostream.flush() | |||
|
156 | ||||
|
157 | def flush(self): | |||
|
158 | """Flush both channels.""" | |||
|
159 | self.file.flush() | |||
|
160 | self.ostream.flush() | |||
|
161 | ||||
|
162 | def __del__(self): | |||
|
163 | if not self._closed: | |||
|
164 | self.close() | |||
|
165 | ||||
|
166 | ||||
108 | #**************************************************************************** |
|
167 | #**************************************************************************** | |
109 | # Generic warning/error printer, used by everything else |
|
168 | # Generic warning/error printer, used by everything else | |
110 | def warn(msg,level=2,exit_val=1): |
|
169 | def warn(msg,level=2,exit_val=1): |
@@ -20,7 +20,9 b' import os' | |||||
20 | import shutil |
|
20 | import shutil | |
21 | import sys |
|
21 | import sys | |
22 | import tempfile |
|
22 | import tempfile | |
|
23 | import unittest | |||
23 |
|
24 | |||
|
25 | from cStringIO import StringIO | |||
24 | from os.path import join, abspath, split |
|
26 | from os.path import join, abspath, split | |
25 |
|
27 | |||
26 | # third-party |
|
28 | # third-party | |
@@ -32,6 +34,7 b' from nose.tools import raises' | |||||
32 | # Our own |
|
34 | # Our own | |
33 | import IPython |
|
35 | import IPython | |
34 | from IPython.utils import genutils |
|
36 | from IPython.utils import genutils | |
|
37 | from IPython.testing import decorators as dec | |||
35 | from IPython.testing.decorators import skipif, skip_if_not_win32 |
|
38 | from IPython.testing.decorators import skipif, skip_if_not_win32 | |
36 |
|
39 | |||
37 | # Platform-dependent imports |
|
40 | # Platform-dependent imports | |
@@ -107,7 +110,7 b' def teardown_environment():' | |||||
107 | (wreg.OpenKey, wreg.QueryValueEx,) = platformstuff |
|
110 | (wreg.OpenKey, wreg.QueryValueEx,) = platformstuff | |
108 |
|
111 | |||
109 | # Build decorator that uses the setup_environment/setup_environment |
|
112 | # Build decorator that uses the setup_environment/setup_environment | |
110 |
with_en |
|
113 | with_environment = with_setup(setup_environment, teardown_environment) | |
111 |
|
114 | |||
112 |
|
115 | |||
113 | # |
|
116 | # | |
@@ -115,7 +118,7 b' with_enivronment = with_setup(setup_environment, teardown_environment)' | |||||
115 | # |
|
118 | # | |
116 |
|
119 | |||
117 | @skip_if_not_win32 |
|
120 | @skip_if_not_win32 | |
118 |
@with_en |
|
121 | @with_environment | |
119 | def test_get_home_dir_1(): |
|
122 | def test_get_home_dir_1(): | |
120 | """Testcase for py2exe logic, un-compressed lib |
|
123 | """Testcase for py2exe logic, un-compressed lib | |
121 | """ |
|
124 | """ | |
@@ -128,7 +131,7 b' def test_get_home_dir_1():' | |||||
128 | nt.assert_equal(home_dir, abspath(HOME_TEST_DIR)) |
|
131 | nt.assert_equal(home_dir, abspath(HOME_TEST_DIR)) | |
129 |
|
132 | |||
130 | @skip_if_not_win32 |
|
133 | @skip_if_not_win32 | |
131 |
@with_en |
|
134 | @with_environment | |
132 | def test_get_home_dir_2(): |
|
135 | def test_get_home_dir_2(): | |
133 | """Testcase for py2exe logic, compressed lib |
|
136 | """Testcase for py2exe logic, compressed lib | |
134 | """ |
|
137 | """ | |
@@ -139,14 +142,14 b' def test_get_home_dir_2():' | |||||
139 | home_dir = genutils.get_home_dir() |
|
142 | home_dir = genutils.get_home_dir() | |
140 | nt.assert_equal(home_dir, abspath(HOME_TEST_DIR).lower()) |
|
143 | nt.assert_equal(home_dir, abspath(HOME_TEST_DIR).lower()) | |
141 |
|
144 | |||
142 |
@with_en |
|
145 | @with_environment | |
143 | def test_get_home_dir_3(): |
|
146 | def test_get_home_dir_3(): | |
144 | """Testcase $HOME is set, then use its value as home directory.""" |
|
147 | """Testcase $HOME is set, then use its value as home directory.""" | |
145 | env["HOME"] = HOME_TEST_DIR |
|
148 | env["HOME"] = HOME_TEST_DIR | |
146 | home_dir = genutils.get_home_dir() |
|
149 | home_dir = genutils.get_home_dir() | |
147 | nt.assert_equal(home_dir, env["HOME"]) |
|
150 | nt.assert_equal(home_dir, env["HOME"]) | |
148 |
|
151 | |||
149 |
@with_en |
|
152 | @with_environment | |
150 | def test_get_home_dir_4(): |
|
153 | def test_get_home_dir_4(): | |
151 | """Testcase $HOME is not set, os=='poix'. |
|
154 | """Testcase $HOME is not set, os=='poix'. | |
152 | This should fail with HomeDirError""" |
|
155 | This should fail with HomeDirError""" | |
@@ -156,7 +159,7 b' def test_get_home_dir_4():' | |||||
156 | nt.assert_raises(genutils.HomeDirError, genutils.get_home_dir) |
|
159 | nt.assert_raises(genutils.HomeDirError, genutils.get_home_dir) | |
157 |
|
160 | |||
158 | @skip_if_not_win32 |
|
161 | @skip_if_not_win32 | |
159 |
@with_en |
|
162 | @with_environment | |
160 | def test_get_home_dir_5(): |
|
163 | def test_get_home_dir_5(): | |
161 | """Testcase $HOME is not set, os=='nt' |
|
164 | """Testcase $HOME is not set, os=='nt' | |
162 | env['HOMEDRIVE'],env['HOMEPATH'] points to path.""" |
|
165 | env['HOMEDRIVE'],env['HOMEPATH'] points to path.""" | |
@@ -169,7 +172,7 b' def test_get_home_dir_5():' | |||||
169 | nt.assert_equal(home_dir, abspath(HOME_TEST_DIR)) |
|
172 | nt.assert_equal(home_dir, abspath(HOME_TEST_DIR)) | |
170 |
|
173 | |||
171 | @skip_if_not_win32 |
|
174 | @skip_if_not_win32 | |
172 |
@with_en |
|
175 | @with_environment | |
173 | def test_get_home_dir_6(): |
|
176 | def test_get_home_dir_6(): | |
174 | """Testcase $HOME is not set, os=='nt' |
|
177 | """Testcase $HOME is not set, os=='nt' | |
175 | env['HOMEDRIVE'],env['HOMEPATH'] do not point to path. |
|
178 | env['HOMEDRIVE'],env['HOMEPATH'] do not point to path. | |
@@ -186,7 +189,7 b' def test_get_home_dir_6():' | |||||
186 |
|
189 | |||
187 | # Should we stub wreg fully so we can run the test on all platforms? |
|
190 | # Should we stub wreg fully so we can run the test on all platforms? | |
188 | @skip_if_not_win32 |
|
191 | @skip_if_not_win32 | |
189 |
@with_en |
|
192 | @with_environment | |
190 | def test_get_home_dir_7(): |
|
193 | def test_get_home_dir_7(): | |
191 | """Testcase $HOME is not set, os=='nt' |
|
194 | """Testcase $HOME is not set, os=='nt' | |
192 | env['HOMEDRIVE'],env['HOMEPATH'], env['USERPROFILE'] missing |
|
195 | env['HOMEDRIVE'],env['HOMEPATH'], env['USERPROFILE'] missing | |
@@ -214,7 +217,7 b' def test_get_home_dir_7():' | |||||
214 | # Tests for get_ipython_dir |
|
217 | # Tests for get_ipython_dir | |
215 | # |
|
218 | # | |
216 |
|
219 | |||
217 |
@with_en |
|
220 | @with_environment | |
218 | def test_get_ipython_dir_1(): |
|
221 | def test_get_ipython_dir_1(): | |
219 | """test_get_ipython_dir_1, Testcase to see if we can call get_ipython_dir without Exceptions.""" |
|
222 | """test_get_ipython_dir_1, Testcase to see if we can call get_ipython_dir without Exceptions.""" | |
220 | env['IPYTHONDIR'] = "someplace/.ipython" |
|
223 | env['IPYTHONDIR'] = "someplace/.ipython" | |
@@ -222,7 +225,7 b' def test_get_ipython_dir_1():' | |||||
222 | nt.assert_equal(ipdir, "someplace/.ipython") |
|
225 | nt.assert_equal(ipdir, "someplace/.ipython") | |
223 |
|
226 | |||
224 |
|
227 | |||
225 |
@with_en |
|
228 | @with_environment | |
226 | def test_get_ipython_dir_2(): |
|
229 | def test_get_ipython_dir_2(): | |
227 | """test_get_ipython_dir_2, Testcase to see if we can call get_ipython_dir without Exceptions.""" |
|
230 | """test_get_ipython_dir_2, Testcase to see if we can call get_ipython_dir without Exceptions.""" | |
228 | genutils.get_home_dir = lambda : "someplace" |
|
231 | genutils.get_home_dir = lambda : "someplace" | |
@@ -283,3 +286,38 b' def test_filefind():' | |||||
283 | def test_get_ipython_package_dir(): |
|
286 | def test_get_ipython_package_dir(): | |
284 | ipdir = genutils.get_ipython_package_dir() |
|
287 | ipdir = genutils.get_ipython_package_dir() | |
285 | nt.assert_true(os.path.isdir(ipdir)) |
|
288 | nt.assert_true(os.path.isdir(ipdir)) | |
|
289 | ||||
|
290 | ||||
|
291 | def test_tee_simple(): | |||
|
292 | "Very simple check with stdout only" | |||
|
293 | chan = StringIO() | |||
|
294 | text = 'Hello' | |||
|
295 | tee = genutils.Tee(chan, channel='stdout') | |||
|
296 | print >> chan, text, | |||
|
297 | nt.assert_equal(chan.getvalue(), text) | |||
|
298 | ||||
|
299 | ||||
|
300 | class TeeTestCase(dec.ParametricTestCase): | |||
|
301 | ||||
|
302 | def tchan(self, channel, check='close'): | |||
|
303 | trap = StringIO() | |||
|
304 | chan = StringIO() | |||
|
305 | text = 'Hello' | |||
|
306 | ||||
|
307 | std_ori = getattr(sys, channel) | |||
|
308 | setattr(sys, channel, trap) | |||
|
309 | ||||
|
310 | tee = genutils.Tee(chan, channel=channel) | |||
|
311 | print >> chan, text, | |||
|
312 | setattr(sys, channel, std_ori) | |||
|
313 | trap_val = trap.getvalue() | |||
|
314 | nt.assert_equals(chan.getvalue(), text) | |||
|
315 | if check=='close': | |||
|
316 | tee.close() | |||
|
317 | else: | |||
|
318 | del tee | |||
|
319 | ||||
|
320 | def test(self): | |||
|
321 | for chan in ['stdout', 'stderr']: | |||
|
322 | for check in ['close', 'del']: | |||
|
323 | yield self.tchan(chan, check) |
General Comments 0
You need to be logged in to leave comments.
Login now