##// END OF EJS Templates
Python 2.6 doesn't support `python -m IPython`...
MinRK -
Show More
@@ -1,47 +1,58 b''
1 """Tests for two-process terminal frontend
1 """Tests for two-process terminal frontend
2
2
3 Currently only has the most simple test possible, starting a console and running
3 Currently only has the most simple test possible, starting a console and running
4 a single command.
4 a single command.
5
5
6 Authors:
6 Authors:
7
7
8 * Min RK
8 * Min RK
9 """
9 """
10
10
11 #-----------------------------------------------------------------------------
11 #-----------------------------------------------------------------------------
12 # Imports
12 # Imports
13 #-----------------------------------------------------------------------------
13 #-----------------------------------------------------------------------------
14
14
15 import sys
15 import sys
16 import time
16 import time
17
17
18 import nose.tools as nt
18 import nose.tools as nt
19 from nose import SkipTest
19 from nose import SkipTest
20
20
21 from IPython.testing import decorators as dec
21 from IPython.testing import decorators as dec
22 from IPython.utils import py3compat
22 from IPython.utils import py3compat
23 from IPython.utils.process import find_cmd
24
23
25 #-----------------------------------------------------------------------------
24 #-----------------------------------------------------------------------------
26 # Test functions begin
25 # Test functions begin
27 #-----------------------------------------------------------------------------
26 #-----------------------------------------------------------------------------
28
27
29 @dec.skip_win32
28 @dec.skip_win32
30 def test_console_starts():
29 def test_console_starts():
31 """test that `ipython console` starts a terminal"""
30 """test that `ipython console` starts a terminal"""
32 from IPython.external import pexpect
31 from IPython.external import pexpect
33
32
34 p = pexpect.spawn(sys.executable, args=['-m', 'IPython', 'console', '--colors=NoColor'])
33 args = ['console', '--colors=NoColor']
34 # FIXME: remove workaround for 2.6 support
35 if sys.version_info[:2] > (2,6):
36 args = ['-m', 'IPython'] + args
37 cmd = sys.executable
38 else:
39 cmd = 'ipython'
40
41 try:
42 p = pexpect.spawn(cmd, args=args)
43 except IOError:
44 raise SkipTest("Couldn't find command %s" % cmd)
45
35 idx = p.expect([r'In \[\d+\]', pexpect.EOF], timeout=15)
46 idx = p.expect([r'In \[\d+\]', pexpect.EOF], timeout=15)
36 nt.assert_equal(idx, 0, "expected in prompt")
47 nt.assert_equal(idx, 0, "expected in prompt")
37 p.sendline('5')
48 p.sendline('5')
38 idx = p.expect([r'Out\[\d+\]: 5', pexpect.EOF], timeout=5)
49 idx = p.expect([r'Out\[\d+\]: 5', pexpect.EOF], timeout=5)
39 nt.assert_equal(idx, 0, "expected out prompt")
50 nt.assert_equal(idx, 0, "expected out prompt")
40 idx = p.expect([r'In \[\d+\]', pexpect.EOF], timeout=5)
51 idx = p.expect([r'In \[\d+\]', pexpect.EOF], timeout=5)
41 nt.assert_equal(idx, 0, "expected second in prompt")
52 nt.assert_equal(idx, 0, "expected second in prompt")
42 # send ctrl-D;ctrl-D to exit
53 # send ctrl-D;ctrl-D to exit
43 p.sendeof()
54 p.sendeof()
44 p.sendeof()
55 p.sendeof()
45 p.expect([pexpect.EOF, pexpect.TIMEOUT], timeout=5)
56 p.expect([pexpect.EOF, pexpect.TIMEOUT], timeout=5)
46 if p.isalive():
57 if p.isalive():
47 p.terminate()
58 p.terminate()
@@ -1,393 +1,397 b''
1 """Generic testing tools.
1 """Generic testing tools.
2
2
3 Authors
3 Authors
4 -------
4 -------
5 - Fernando Perez <Fernando.Perez@berkeley.edu>
5 - Fernando Perez <Fernando.Perez@berkeley.edu>
6 """
6 """
7
7
8 from __future__ import absolute_import
8 from __future__ import absolute_import
9
9
10 #-----------------------------------------------------------------------------
10 #-----------------------------------------------------------------------------
11 # Copyright (C) 2009-2011 The IPython Development Team
11 # Copyright (C) 2009-2011 The IPython Development Team
12 #
12 #
13 # Distributed under the terms of the BSD License. The full license is in
13 # Distributed under the terms of the BSD License. The full license is in
14 # the file COPYING, distributed as part of this software.
14 # the file COPYING, distributed as part of this software.
15 #-----------------------------------------------------------------------------
15 #-----------------------------------------------------------------------------
16
16
17 #-----------------------------------------------------------------------------
17 #-----------------------------------------------------------------------------
18 # Imports
18 # Imports
19 #-----------------------------------------------------------------------------
19 #-----------------------------------------------------------------------------
20
20
21 import os
21 import os
22 import pipes
22 import pipes
23 import re
23 import re
24 import sys
24 import sys
25 import tempfile
25 import tempfile
26
26
27 from contextlib import contextmanager
27 from contextlib import contextmanager
28 from io import StringIO
28 from io import StringIO
29
29
30 try:
30 try:
31 # These tools are used by parts of the runtime, so we make the nose
31 # These tools are used by parts of the runtime, so we make the nose
32 # dependency optional at this point. Nose is a hard dependency to run the
32 # dependency optional at this point. Nose is a hard dependency to run the
33 # test suite, but NOT to use ipython itself.
33 # test suite, but NOT to use ipython itself.
34 import nose.tools as nt
34 import nose.tools as nt
35 has_nose = True
35 has_nose = True
36 except ImportError:
36 except ImportError:
37 has_nose = False
37 has_nose = False
38
38
39 from IPython.config.loader import Config
39 from IPython.config.loader import Config
40 from IPython.utils.process import find_cmd, getoutputerror
40 from IPython.utils.process import find_cmd, getoutputerror
41 from IPython.utils.text import list_strings
41 from IPython.utils.text import list_strings
42 from IPython.utils.io import temp_pyfile, Tee
42 from IPython.utils.io import temp_pyfile, Tee
43 from IPython.utils import py3compat
43 from IPython.utils import py3compat
44 from IPython.utils.encoding import DEFAULT_ENCODING
44 from IPython.utils.encoding import DEFAULT_ENCODING
45
45
46 from . import decorators as dec
46 from . import decorators as dec
47 from . import skipdoctest
47 from . import skipdoctest
48
48
49 #-----------------------------------------------------------------------------
49 #-----------------------------------------------------------------------------
50 # Functions and classes
50 # Functions and classes
51 #-----------------------------------------------------------------------------
51 #-----------------------------------------------------------------------------
52
52
53 # The docstring for full_path doctests differently on win32 (different path
53 # The docstring for full_path doctests differently on win32 (different path
54 # separator) so just skip the doctest there. The example remains informative.
54 # separator) so just skip the doctest there. The example remains informative.
55 doctest_deco = skipdoctest.skip_doctest if sys.platform == 'win32' else dec.null_deco
55 doctest_deco = skipdoctest.skip_doctest if sys.platform == 'win32' else dec.null_deco
56
56
57 @doctest_deco
57 @doctest_deco
58 def full_path(startPath,files):
58 def full_path(startPath,files):
59 """Make full paths for all the listed files, based on startPath.
59 """Make full paths for all the listed files, based on startPath.
60
60
61 Only the base part of startPath is kept, since this routine is typically
61 Only the base part of startPath is kept, since this routine is typically
62 used with a script's __file__ variable as startPath. The base of startPath
62 used with a script's __file__ variable as startPath. The base of startPath
63 is then prepended to all the listed files, forming the output list.
63 is then prepended to all the listed files, forming the output list.
64
64
65 Parameters
65 Parameters
66 ----------
66 ----------
67 startPath : string
67 startPath : string
68 Initial path to use as the base for the results. This path is split
68 Initial path to use as the base for the results. This path is split
69 using os.path.split() and only its first component is kept.
69 using os.path.split() and only its first component is kept.
70
70
71 files : string or list
71 files : string or list
72 One or more files.
72 One or more files.
73
73
74 Examples
74 Examples
75 --------
75 --------
76
76
77 >>> full_path('/foo/bar.py',['a.txt','b.txt'])
77 >>> full_path('/foo/bar.py',['a.txt','b.txt'])
78 ['/foo/a.txt', '/foo/b.txt']
78 ['/foo/a.txt', '/foo/b.txt']
79
79
80 >>> full_path('/foo',['a.txt','b.txt'])
80 >>> full_path('/foo',['a.txt','b.txt'])
81 ['/a.txt', '/b.txt']
81 ['/a.txt', '/b.txt']
82
82
83 If a single file is given, the output is still a list:
83 If a single file is given, the output is still a list:
84 >>> full_path('/foo','a.txt')
84 >>> full_path('/foo','a.txt')
85 ['/a.txt']
85 ['/a.txt']
86 """
86 """
87
87
88 files = list_strings(files)
88 files = list_strings(files)
89 base = os.path.split(startPath)[0]
89 base = os.path.split(startPath)[0]
90 return [ os.path.join(base,f) for f in files ]
90 return [ os.path.join(base,f) for f in files ]
91
91
92
92
93 def parse_test_output(txt):
93 def parse_test_output(txt):
94 """Parse the output of a test run and return errors, failures.
94 """Parse the output of a test run and return errors, failures.
95
95
96 Parameters
96 Parameters
97 ----------
97 ----------
98 txt : str
98 txt : str
99 Text output of a test run, assumed to contain a line of one of the
99 Text output of a test run, assumed to contain a line of one of the
100 following forms::
100 following forms::
101
101
102 'FAILED (errors=1)'
102 'FAILED (errors=1)'
103 'FAILED (failures=1)'
103 'FAILED (failures=1)'
104 'FAILED (errors=1, failures=1)'
104 'FAILED (errors=1, failures=1)'
105
105
106 Returns
106 Returns
107 -------
107 -------
108 nerr, nfail: number of errors and failures.
108 nerr, nfail: number of errors and failures.
109 """
109 """
110
110
111 err_m = re.search(r'^FAILED \(errors=(\d+)\)', txt, re.MULTILINE)
111 err_m = re.search(r'^FAILED \(errors=(\d+)\)', txt, re.MULTILINE)
112 if err_m:
112 if err_m:
113 nerr = int(err_m.group(1))
113 nerr = int(err_m.group(1))
114 nfail = 0
114 nfail = 0
115 return nerr, nfail
115 return nerr, nfail
116
116
117 fail_m = re.search(r'^FAILED \(failures=(\d+)\)', txt, re.MULTILINE)
117 fail_m = re.search(r'^FAILED \(failures=(\d+)\)', txt, re.MULTILINE)
118 if fail_m:
118 if fail_m:
119 nerr = 0
119 nerr = 0
120 nfail = int(fail_m.group(1))
120 nfail = int(fail_m.group(1))
121 return nerr, nfail
121 return nerr, nfail
122
122
123 both_m = re.search(r'^FAILED \(errors=(\d+), failures=(\d+)\)', txt,
123 both_m = re.search(r'^FAILED \(errors=(\d+), failures=(\d+)\)', txt,
124 re.MULTILINE)
124 re.MULTILINE)
125 if both_m:
125 if both_m:
126 nerr = int(both_m.group(1))
126 nerr = int(both_m.group(1))
127 nfail = int(both_m.group(2))
127 nfail = int(both_m.group(2))
128 return nerr, nfail
128 return nerr, nfail
129
129
130 # If the input didn't match any of these forms, assume no error/failures
130 # If the input didn't match any of these forms, assume no error/failures
131 return 0, 0
131 return 0, 0
132
132
133
133
134 # So nose doesn't think this is a test
134 # So nose doesn't think this is a test
135 parse_test_output.__test__ = False
135 parse_test_output.__test__ = False
136
136
137
137
138 def default_argv():
138 def default_argv():
139 """Return a valid default argv for creating testing instances of ipython"""
139 """Return a valid default argv for creating testing instances of ipython"""
140
140
141 return ['--quick', # so no config file is loaded
141 return ['--quick', # so no config file is loaded
142 # Other defaults to minimize side effects on stdout
142 # Other defaults to minimize side effects on stdout
143 '--colors=NoColor', '--no-term-title','--no-banner',
143 '--colors=NoColor', '--no-term-title','--no-banner',
144 '--autocall=0']
144 '--autocall=0']
145
145
146
146
147 def default_config():
147 def default_config():
148 """Return a config object with good defaults for testing."""
148 """Return a config object with good defaults for testing."""
149 config = Config()
149 config = Config()
150 config.TerminalInteractiveShell.colors = 'NoColor'
150 config.TerminalInteractiveShell.colors = 'NoColor'
151 config.TerminalTerminalInteractiveShell.term_title = False,
151 config.TerminalTerminalInteractiveShell.term_title = False,
152 config.TerminalInteractiveShell.autocall = 0
152 config.TerminalInteractiveShell.autocall = 0
153 config.HistoryManager.hist_file = tempfile.mktemp(u'test_hist.sqlite')
153 config.HistoryManager.hist_file = tempfile.mktemp(u'test_hist.sqlite')
154 config.HistoryManager.db_cache_size = 10000
154 config.HistoryManager.db_cache_size = 10000
155 return config
155 return config
156
156
157
157
158 def ipexec(fname, options=None):
158 def ipexec(fname, options=None):
159 """Utility to call 'ipython filename'.
159 """Utility to call 'ipython filename'.
160
160
161 Starts IPython with a minimal and safe configuration to make startup as fast
161 Starts IPython with a minimal and safe configuration to make startup as fast
162 as possible.
162 as possible.
163
163
164 Note that this starts IPython in a subprocess!
164 Note that this starts IPython in a subprocess!
165
165
166 Parameters
166 Parameters
167 ----------
167 ----------
168 fname : str
168 fname : str
169 Name of file to be executed (should have .py or .ipy extension).
169 Name of file to be executed (should have .py or .ipy extension).
170
170
171 options : optional, list
171 options : optional, list
172 Extra command-line flags to be passed to IPython.
172 Extra command-line flags to be passed to IPython.
173
173
174 Returns
174 Returns
175 -------
175 -------
176 (stdout, stderr) of ipython subprocess.
176 (stdout, stderr) of ipython subprocess.
177 """
177 """
178 if options is None: options = []
178 if options is None: options = []
179
179
180 # For these subprocess calls, eliminate all prompt printing so we only see
180 # For these subprocess calls, eliminate all prompt printing so we only see
181 # output from script execution
181 # output from script execution
182 prompt_opts = [ '--PromptManager.in_template=""',
182 prompt_opts = [ '--PromptManager.in_template=""',
183 '--PromptManager.in2_template=""',
183 '--PromptManager.in2_template=""',
184 '--PromptManager.out_template=""'
184 '--PromptManager.out_template=""'
185 ]
185 ]
186 cmdargs = ' '.join(default_argv() + prompt_opts + options)
186 cmdargs = ' '.join(default_argv() + prompt_opts + options)
187
187
188 _ip = get_ipython()
188 _ip = get_ipython()
189 test_dir = os.path.dirname(__file__)
189 test_dir = os.path.dirname(__file__)
190
190
191 ipython_cmd = pipes.quote(sys.executable) + " -m IPython"
191 # FIXME: remove workaround for 2.6 support
192 if sys.version_info[:2] > (2,6):
193 ipython_cmd = pipes.quote(sys.executable) + " -m IPython"
194 else:
195 ipython_cmd = "ipython"
192 # Absolute path for filename
196 # Absolute path for filename
193 full_fname = os.path.join(test_dir, fname)
197 full_fname = os.path.join(test_dir, fname)
194 full_cmd = '%s %s %s' % (ipython_cmd, cmdargs, full_fname)
198 full_cmd = '%s %s %s' % (ipython_cmd, cmdargs, full_fname)
195 #print >> sys.stderr, 'FULL CMD:', full_cmd # dbg
199 #print >> sys.stderr, 'FULL CMD:', full_cmd # dbg
196 out, err = getoutputerror(full_cmd)
200 out, err = getoutputerror(full_cmd)
197 # `import readline` causes 'ESC[?1034h' to be output sometimes,
201 # `import readline` causes 'ESC[?1034h' to be output sometimes,
198 # so strip that out before doing comparisons
202 # so strip that out before doing comparisons
199 if out:
203 if out:
200 out = re.sub(r'\x1b\[[^h]+h', '', out)
204 out = re.sub(r'\x1b\[[^h]+h', '', out)
201 return out, err
205 return out, err
202
206
203
207
204 def ipexec_validate(fname, expected_out, expected_err='',
208 def ipexec_validate(fname, expected_out, expected_err='',
205 options=None):
209 options=None):
206 """Utility to call 'ipython filename' and validate output/error.
210 """Utility to call 'ipython filename' and validate output/error.
207
211
208 This function raises an AssertionError if the validation fails.
212 This function raises an AssertionError if the validation fails.
209
213
210 Note that this starts IPython in a subprocess!
214 Note that this starts IPython in a subprocess!
211
215
212 Parameters
216 Parameters
213 ----------
217 ----------
214 fname : str
218 fname : str
215 Name of the file to be executed (should have .py or .ipy extension).
219 Name of the file to be executed (should have .py or .ipy extension).
216
220
217 expected_out : str
221 expected_out : str
218 Expected stdout of the process.
222 Expected stdout of the process.
219
223
220 expected_err : optional, str
224 expected_err : optional, str
221 Expected stderr of the process.
225 Expected stderr of the process.
222
226
223 options : optional, list
227 options : optional, list
224 Extra command-line flags to be passed to IPython.
228 Extra command-line flags to be passed to IPython.
225
229
226 Returns
230 Returns
227 -------
231 -------
228 None
232 None
229 """
233 """
230
234
231 import nose.tools as nt
235 import nose.tools as nt
232
236
233 out, err = ipexec(fname, options)
237 out, err = ipexec(fname, options)
234 #print 'OUT', out # dbg
238 #print 'OUT', out # dbg
235 #print 'ERR', err # dbg
239 #print 'ERR', err # dbg
236 # If there are any errors, we must check those befor stdout, as they may be
240 # If there are any errors, we must check those befor stdout, as they may be
237 # more informative than simply having an empty stdout.
241 # more informative than simply having an empty stdout.
238 if err:
242 if err:
239 if expected_err:
243 if expected_err:
240 nt.assert_equal("\n".join(err.strip().splitlines()), "\n".join(expected_err.strip().splitlines()))
244 nt.assert_equal("\n".join(err.strip().splitlines()), "\n".join(expected_err.strip().splitlines()))
241 else:
245 else:
242 raise ValueError('Running file %r produced error: %r' %
246 raise ValueError('Running file %r produced error: %r' %
243 (fname, err))
247 (fname, err))
244 # If no errors or output on stderr was expected, match stdout
248 # If no errors or output on stderr was expected, match stdout
245 nt.assert_equal("\n".join(out.strip().splitlines()), "\n".join(expected_out.strip().splitlines()))
249 nt.assert_equal("\n".join(out.strip().splitlines()), "\n".join(expected_out.strip().splitlines()))
246
250
247
251
248 class TempFileMixin(object):
252 class TempFileMixin(object):
249 """Utility class to create temporary Python/IPython files.
253 """Utility class to create temporary Python/IPython files.
250
254
251 Meant as a mixin class for test cases."""
255 Meant as a mixin class for test cases."""
252
256
253 def mktmp(self, src, ext='.py'):
257 def mktmp(self, src, ext='.py'):
254 """Make a valid python temp file."""
258 """Make a valid python temp file."""
255 fname, f = temp_pyfile(src, ext)
259 fname, f = temp_pyfile(src, ext)
256 self.tmpfile = f
260 self.tmpfile = f
257 self.fname = fname
261 self.fname = fname
258
262
259 def tearDown(self):
263 def tearDown(self):
260 if hasattr(self, 'tmpfile'):
264 if hasattr(self, 'tmpfile'):
261 # If the tmpfile wasn't made because of skipped tests, like in
265 # If the tmpfile wasn't made because of skipped tests, like in
262 # win32, there's nothing to cleanup.
266 # win32, there's nothing to cleanup.
263 self.tmpfile.close()
267 self.tmpfile.close()
264 try:
268 try:
265 os.unlink(self.fname)
269 os.unlink(self.fname)
266 except:
270 except:
267 # On Windows, even though we close the file, we still can't
271 # On Windows, even though we close the file, we still can't
268 # delete it. I have no clue why
272 # delete it. I have no clue why
269 pass
273 pass
270
274
271 pair_fail_msg = ("Testing {0}\n\n"
275 pair_fail_msg = ("Testing {0}\n\n"
272 "In:\n"
276 "In:\n"
273 " {1!r}\n"
277 " {1!r}\n"
274 "Expected:\n"
278 "Expected:\n"
275 " {2!r}\n"
279 " {2!r}\n"
276 "Got:\n"
280 "Got:\n"
277 " {3!r}\n")
281 " {3!r}\n")
278 def check_pairs(func, pairs):
282 def check_pairs(func, pairs):
279 """Utility function for the common case of checking a function with a
283 """Utility function for the common case of checking a function with a
280 sequence of input/output pairs.
284 sequence of input/output pairs.
281
285
282 Parameters
286 Parameters
283 ----------
287 ----------
284 func : callable
288 func : callable
285 The function to be tested. Should accept a single argument.
289 The function to be tested. Should accept a single argument.
286 pairs : iterable
290 pairs : iterable
287 A list of (input, expected_output) tuples.
291 A list of (input, expected_output) tuples.
288
292
289 Returns
293 Returns
290 -------
294 -------
291 None. Raises an AssertionError if any output does not match the expected
295 None. Raises an AssertionError if any output does not match the expected
292 value.
296 value.
293 """
297 """
294 name = getattr(func, "func_name", getattr(func, "__name__", "<unknown>"))
298 name = getattr(func, "func_name", getattr(func, "__name__", "<unknown>"))
295 for inp, expected in pairs:
299 for inp, expected in pairs:
296 out = func(inp)
300 out = func(inp)
297 assert out == expected, pair_fail_msg.format(name, inp, expected, out)
301 assert out == expected, pair_fail_msg.format(name, inp, expected, out)
298
302
299
303
300 if py3compat.PY3:
304 if py3compat.PY3:
301 MyStringIO = StringIO
305 MyStringIO = StringIO
302 else:
306 else:
303 # In Python 2, stdout/stderr can have either bytes or unicode written to them,
307 # In Python 2, stdout/stderr can have either bytes or unicode written to them,
304 # so we need a class that can handle both.
308 # so we need a class that can handle both.
305 class MyStringIO(StringIO):
309 class MyStringIO(StringIO):
306 def write(self, s):
310 def write(self, s):
307 s = py3compat.cast_unicode(s, encoding=DEFAULT_ENCODING)
311 s = py3compat.cast_unicode(s, encoding=DEFAULT_ENCODING)
308 super(MyStringIO, self).write(s)
312 super(MyStringIO, self).write(s)
309
313
310 notprinted_msg = """Did not find {0!r} in printed output (on {1}):
314 notprinted_msg = """Did not find {0!r} in printed output (on {1}):
311 -------
315 -------
312 {2!s}
316 {2!s}
313 -------
317 -------
314 """
318 """
315
319
316 class AssertPrints(object):
320 class AssertPrints(object):
317 """Context manager for testing that code prints certain text.
321 """Context manager for testing that code prints certain text.
318
322
319 Examples
323 Examples
320 --------
324 --------
321 >>> with AssertPrints("abc", suppress=False):
325 >>> with AssertPrints("abc", suppress=False):
322 ... print "abcd"
326 ... print "abcd"
323 ... print "def"
327 ... print "def"
324 ...
328 ...
325 abcd
329 abcd
326 def
330 def
327 """
331 """
328 def __init__(self, s, channel='stdout', suppress=True):
332 def __init__(self, s, channel='stdout', suppress=True):
329 self.s = s
333 self.s = s
330 self.channel = channel
334 self.channel = channel
331 self.suppress = suppress
335 self.suppress = suppress
332
336
333 def __enter__(self):
337 def __enter__(self):
334 self.orig_stream = getattr(sys, self.channel)
338 self.orig_stream = getattr(sys, self.channel)
335 self.buffer = MyStringIO()
339 self.buffer = MyStringIO()
336 self.tee = Tee(self.buffer, channel=self.channel)
340 self.tee = Tee(self.buffer, channel=self.channel)
337 setattr(sys, self.channel, self.buffer if self.suppress else self.tee)
341 setattr(sys, self.channel, self.buffer if self.suppress else self.tee)
338
342
339 def __exit__(self, etype, value, traceback):
343 def __exit__(self, etype, value, traceback):
340 self.tee.flush()
344 self.tee.flush()
341 setattr(sys, self.channel, self.orig_stream)
345 setattr(sys, self.channel, self.orig_stream)
342 printed = self.buffer.getvalue()
346 printed = self.buffer.getvalue()
343 assert self.s in printed, notprinted_msg.format(self.s, self.channel, printed)
347 assert self.s in printed, notprinted_msg.format(self.s, self.channel, printed)
344 return False
348 return False
345
349
346 printed_msg = """Found {0!r} in printed output (on {1}):
350 printed_msg = """Found {0!r} in printed output (on {1}):
347 -------
351 -------
348 {2!s}
352 {2!s}
349 -------
353 -------
350 """
354 """
351
355
352 class AssertNotPrints(AssertPrints):
356 class AssertNotPrints(AssertPrints):
353 """Context manager for checking that certain output *isn't* produced.
357 """Context manager for checking that certain output *isn't* produced.
354
358
355 Counterpart of AssertPrints"""
359 Counterpart of AssertPrints"""
356 def __exit__(self, etype, value, traceback):
360 def __exit__(self, etype, value, traceback):
357 self.tee.flush()
361 self.tee.flush()
358 setattr(sys, self.channel, self.orig_stream)
362 setattr(sys, self.channel, self.orig_stream)
359 printed = self.buffer.getvalue()
363 printed = self.buffer.getvalue()
360 assert self.s not in printed, printed_msg.format(self.s, self.channel, printed)
364 assert self.s not in printed, printed_msg.format(self.s, self.channel, printed)
361 return False
365 return False
362
366
363 @contextmanager
367 @contextmanager
364 def mute_warn():
368 def mute_warn():
365 from IPython.utils import warn
369 from IPython.utils import warn
366 save_warn = warn.warn
370 save_warn = warn.warn
367 warn.warn = lambda *a, **kw: None
371 warn.warn = lambda *a, **kw: None
368 try:
372 try:
369 yield
373 yield
370 finally:
374 finally:
371 warn.warn = save_warn
375 warn.warn = save_warn
372
376
373 @contextmanager
377 @contextmanager
374 def make_tempfile(name):
378 def make_tempfile(name):
375 """ Create an empty, named, temporary file for the duration of the context.
379 """ Create an empty, named, temporary file for the duration of the context.
376 """
380 """
377 f = open(name, 'w')
381 f = open(name, 'w')
378 f.close()
382 f.close()
379 try:
383 try:
380 yield
384 yield
381 finally:
385 finally:
382 os.unlink(name)
386 os.unlink(name)
383
387
384
388
385 @contextmanager
389 @contextmanager
386 def monkeypatch(obj, name, attr):
390 def monkeypatch(obj, name, attr):
387 """
391 """
388 Context manager to replace attribute named `name` in `obj` with `attr`.
392 Context manager to replace attribute named `name` in `obj` with `attr`.
389 """
393 """
390 orig = getattr(obj, name)
394 orig = getattr(obj, name)
391 setattr(obj, name, attr)
395 setattr(obj, name, attr)
392 yield
396 yield
393 setattr(obj, name, orig)
397 setattr(obj, name, orig)
General Comments 0
You need to be logged in to leave comments. Login now