##// END OF EJS Templates
Add AssertPrints context manager to check output from tests.
Thomas Kluyver -
Show More
@@ -1,73 +1,90 b''
1 # encoding: utf-8
1 # encoding: utf-8
2 """
2 """
3 Tests for testing.tools
3 Tests for testing.tools
4 """
4 """
5
5
6 #-----------------------------------------------------------------------------
6 #-----------------------------------------------------------------------------
7 # Copyright (C) 2008-2009 The IPython Development Team
7 # Copyright (C) 2008-2009 The IPython Development Team
8 #
8 #
9 # Distributed under the terms of the BSD License. The full license is in
9 # Distributed under the terms of the BSD License. The full license is in
10 # the file COPYING, distributed as part of this software.
10 # the file COPYING, distributed as part of this software.
11 #-----------------------------------------------------------------------------
11 #-----------------------------------------------------------------------------
12
12
13 #-----------------------------------------------------------------------------
13 #-----------------------------------------------------------------------------
14 # Imports
14 # Imports
15 #-----------------------------------------------------------------------------
15 #-----------------------------------------------------------------------------
16 from __future__ import with_statement
16 from __future__ import with_statement
17
17
18 import os
18 import os
19 import sys
19 import sys
20 import unittest
20
21
21 import nose.tools as nt
22 import nose.tools as nt
22
23
23 from IPython.testing import decorators as dec
24 from IPython.testing import decorators as dec
24 from IPython.testing import tools as tt
25 from IPython.testing import tools as tt
25
26
26 #-----------------------------------------------------------------------------
27 #-----------------------------------------------------------------------------
27 # Tests
28 # Tests
28 #-----------------------------------------------------------------------------
29 #-----------------------------------------------------------------------------
29
30
30 @dec.skip_win32
31 @dec.skip_win32
31 def test_full_path_posix():
32 def test_full_path_posix():
32 spath = '/foo/bar.py'
33 spath = '/foo/bar.py'
33 result = tt.full_path(spath,['a.txt','b.txt'])
34 result = tt.full_path(spath,['a.txt','b.txt'])
34 nt.assert_equal(result, ['/foo/a.txt', '/foo/b.txt'])
35 nt.assert_equal(result, ['/foo/a.txt', '/foo/b.txt'])
35 spath = '/foo'
36 spath = '/foo'
36 result = tt.full_path(spath,['a.txt','b.txt'])
37 result = tt.full_path(spath,['a.txt','b.txt'])
37 nt.assert_equal(result, ['/a.txt', '/b.txt'])
38 nt.assert_equal(result, ['/a.txt', '/b.txt'])
38 result = tt.full_path(spath,'a.txt')
39 result = tt.full_path(spath,'a.txt')
39 nt.assert_equal(result, ['/a.txt'])
40 nt.assert_equal(result, ['/a.txt'])
40
41
41
42
42 @dec.skip_if_not_win32
43 @dec.skip_if_not_win32
43 def test_full_path_win32():
44 def test_full_path_win32():
44 spath = 'c:\\foo\\bar.py'
45 spath = 'c:\\foo\\bar.py'
45 result = tt.full_path(spath,['a.txt','b.txt'])
46 result = tt.full_path(spath,['a.txt','b.txt'])
46 nt.assert_equal(result, ['c:\\foo\\a.txt', 'c:\\foo\\b.txt'])
47 nt.assert_equal(result, ['c:\\foo\\a.txt', 'c:\\foo\\b.txt'])
47 spath = 'c:\\foo'
48 spath = 'c:\\foo'
48 result = tt.full_path(spath,['a.txt','b.txt'])
49 result = tt.full_path(spath,['a.txt','b.txt'])
49 nt.assert_equal(result, ['c:\\a.txt', 'c:\\b.txt'])
50 nt.assert_equal(result, ['c:\\a.txt', 'c:\\b.txt'])
50 result = tt.full_path(spath,'a.txt')
51 result = tt.full_path(spath,'a.txt')
51 nt.assert_equal(result, ['c:\\a.txt'])
52 nt.assert_equal(result, ['c:\\a.txt'])
52
53
53
54
54 @dec.parametric
55 @dec.parametric
55 def test_parser():
56 def test_parser():
56 err = ("FAILED (errors=1)", 1, 0)
57 err = ("FAILED (errors=1)", 1, 0)
57 fail = ("FAILED (failures=1)", 0, 1)
58 fail = ("FAILED (failures=1)", 0, 1)
58 both = ("FAILED (errors=1, failures=1)", 1, 1)
59 both = ("FAILED (errors=1, failures=1)", 1, 1)
59 for txt, nerr, nfail in [err, fail, both]:
60 for txt, nerr, nfail in [err, fail, both]:
60 nerr1, nfail1 = tt.parse_test_output(txt)
61 nerr1, nfail1 = tt.parse_test_output(txt)
61 yield nt.assert_equal(nerr, nerr1)
62 yield nt.assert_equal(nerr, nerr1)
62 yield nt.assert_equal(nfail, nfail1)
63 yield nt.assert_equal(nfail, nfail1)
63
64
64
65
65 @dec.parametric
66 @dec.parametric
66 def test_temp_pyfile():
67 def test_temp_pyfile():
67 src = 'pass\n'
68 src = 'pass\n'
68 fname, fh = tt.temp_pyfile(src)
69 fname, fh = tt.temp_pyfile(src)
69 yield nt.assert_true(os.path.isfile(fname))
70 yield nt.assert_true(os.path.isfile(fname))
70 fh.close()
71 fh.close()
71 with open(fname) as fh2:
72 with open(fname) as fh2:
72 src2 = fh2.read()
73 src2 = fh2.read()
73 yield nt.assert_equal(src2, src)
74 yield nt.assert_equal(src2, src)
75
76 class TestAssertPrints(unittest.TestCase):
77 def test_passing(self):
78 with tt.AssertPrints("abc"):
79 print "abcd"
80 print "def"
81 print b"ghi"
82
83 def test_failing(self):
84 def func():
85 with tt.AssertPrints("abc"):
86 print "acd"
87 print "def"
88 print b"ghi"
89
90 self.assertRaises(AssertionError, func)
@@ -1,346 +1,388 b''
1 """Generic testing tools that do NOT depend on Twisted.
1 """Generic testing tools that do NOT depend on Twisted.
2
2
3 In particular, this module exposes a set of top-level assert* functions that
3 In particular, this module exposes a set of top-level assert* functions that
4 can be used in place of nose.tools.assert* in method generators (the ones in
4 can be used in place of nose.tools.assert* in method generators (the ones in
5 nose can not, at least as of nose 0.10.4).
5 nose can not, at least as of nose 0.10.4).
6
6
7 Note: our testing package contains testing.util, which does depend on Twisted
7 Note: our testing package contains testing.util, which does depend on Twisted
8 and provides utilities for tests that manage Deferreds. All testing support
8 and provides utilities for tests that manage Deferreds. All testing support
9 tools that only depend on nose, IPython or the standard library should go here
9 tools that only depend on nose, IPython or the standard library should go here
10 instead.
10 instead.
11
11
12
12
13 Authors
13 Authors
14 -------
14 -------
15 - Fernando Perez <Fernando.Perez@berkeley.edu>
15 - Fernando Perez <Fernando.Perez@berkeley.edu>
16 """
16 """
17
17
18 from __future__ import absolute_import
18 from __future__ import absolute_import
19
19
20 #-----------------------------------------------------------------------------
20 #-----------------------------------------------------------------------------
21 # Copyright (C) 2009 The IPython Development Team
21 # Copyright (C) 2009 The IPython Development Team
22 #
22 #
23 # Distributed under the terms of the BSD License. The full license is in
23 # Distributed under the terms of the BSD License. The full license is in
24 # the file COPYING, distributed as part of this software.
24 # the file COPYING, distributed as part of this software.
25 #-----------------------------------------------------------------------------
25 #-----------------------------------------------------------------------------
26
26
27 #-----------------------------------------------------------------------------
27 #-----------------------------------------------------------------------------
28 # Imports
28 # Imports
29 #-----------------------------------------------------------------------------
29 #-----------------------------------------------------------------------------
30
30
31 import os
31 import os
32 import re
32 import re
33 import sys
33 import sys
34 import tempfile
34 import tempfile
35
35
36 from contextlib import contextmanager
36 from contextlib import contextmanager
37 from io import StringIO
37
38
38 try:
39 try:
39 # These tools are used by parts of the runtime, so we make the nose
40 # These tools are used by parts of the runtime, so we make the nose
40 # dependency optional at this point. Nose is a hard dependency to run the
41 # dependency optional at this point. Nose is a hard dependency to run the
41 # test suite, but NOT to use ipython itself.
42 # test suite, but NOT to use ipython itself.
42 import nose.tools as nt
43 import nose.tools as nt
43 has_nose = True
44 has_nose = True
44 except ImportError:
45 except ImportError:
45 has_nose = False
46 has_nose = False
46
47
47 from IPython.config.loader import Config
48 from IPython.config.loader import Config
48 from IPython.utils.process import find_cmd, getoutputerror
49 from IPython.utils.process import find_cmd, getoutputerror
49 from IPython.utils.text import list_strings
50 from IPython.utils.text import list_strings, getdefaultencoding
50 from IPython.utils.io import temp_pyfile
51 from IPython.utils.io import temp_pyfile, Tee
51 from IPython.utils.py3compat import PY3
52 from IPython.utils import py3compat
52
53
53 from . import decorators as dec
54 from . import decorators as dec
54 from . import skipdoctest
55 from . import skipdoctest
55
56
56 #-----------------------------------------------------------------------------
57 #-----------------------------------------------------------------------------
57 # Globals
58 # Globals
58 #-----------------------------------------------------------------------------
59 #-----------------------------------------------------------------------------
59
60
60 # Make a bunch of nose.tools assert wrappers that can be used in test
61 # Make a bunch of nose.tools assert wrappers that can be used in test
61 # generators. This will expose an assert* function for each one in nose.tools.
62 # generators. This will expose an assert* function for each one in nose.tools.
62
63
63 _tpl = """
64 _tpl = """
64 def %(name)s(*a,**kw):
65 def %(name)s(*a,**kw):
65 return nt.%(name)s(*a,**kw)
66 return nt.%(name)s(*a,**kw)
66 """
67 """
67
68
68 if has_nose:
69 if has_nose:
69 for _x in [a for a in dir(nt) if a.startswith('assert')]:
70 for _x in [a for a in dir(nt) if a.startswith('assert')]:
70 exec _tpl % dict(name=_x)
71 exec _tpl % dict(name=_x)
71
72
72 #-----------------------------------------------------------------------------
73 #-----------------------------------------------------------------------------
73 # Functions and classes
74 # Functions and classes
74 #-----------------------------------------------------------------------------
75 #-----------------------------------------------------------------------------
75
76
76 # The docstring for full_path doctests differently on win32 (different path
77 # The docstring for full_path doctests differently on win32 (different path
77 # separator) so just skip the doctest there. The example remains informative.
78 # separator) so just skip the doctest there. The example remains informative.
78 doctest_deco = skipdoctest.skip_doctest if sys.platform == 'win32' else dec.null_deco
79 doctest_deco = skipdoctest.skip_doctest if sys.platform == 'win32' else dec.null_deco
79
80
80 @doctest_deco
81 @doctest_deco
81 def full_path(startPath,files):
82 def full_path(startPath,files):
82 """Make full paths for all the listed files, based on startPath.
83 """Make full paths for all the listed files, based on startPath.
83
84
84 Only the base part of startPath is kept, since this routine is typically
85 Only the base part of startPath is kept, since this routine is typically
85 used with a script's __file__ variable as startPath. The base of startPath
86 used with a script's __file__ variable as startPath. The base of startPath
86 is then prepended to all the listed files, forming the output list.
87 is then prepended to all the listed files, forming the output list.
87
88
88 Parameters
89 Parameters
89 ----------
90 ----------
90 startPath : string
91 startPath : string
91 Initial path to use as the base for the results. This path is split
92 Initial path to use as the base for the results. This path is split
92 using os.path.split() and only its first component is kept.
93 using os.path.split() and only its first component is kept.
93
94
94 files : string or list
95 files : string or list
95 One or more files.
96 One or more files.
96
97
97 Examples
98 Examples
98 --------
99 --------
99
100
100 >>> full_path('/foo/bar.py',['a.txt','b.txt'])
101 >>> full_path('/foo/bar.py',['a.txt','b.txt'])
101 ['/foo/a.txt', '/foo/b.txt']
102 ['/foo/a.txt', '/foo/b.txt']
102
103
103 >>> full_path('/foo',['a.txt','b.txt'])
104 >>> full_path('/foo',['a.txt','b.txt'])
104 ['/a.txt', '/b.txt']
105 ['/a.txt', '/b.txt']
105
106
106 If a single file is given, the output is still a list:
107 If a single file is given, the output is still a list:
107 >>> full_path('/foo','a.txt')
108 >>> full_path('/foo','a.txt')
108 ['/a.txt']
109 ['/a.txt']
109 """
110 """
110
111
111 files = list_strings(files)
112 files = list_strings(files)
112 base = os.path.split(startPath)[0]
113 base = os.path.split(startPath)[0]
113 return [ os.path.join(base,f) for f in files ]
114 return [ os.path.join(base,f) for f in files ]
114
115
115
116
116 def parse_test_output(txt):
117 def parse_test_output(txt):
117 """Parse the output of a test run and return errors, failures.
118 """Parse the output of a test run and return errors, failures.
118
119
119 Parameters
120 Parameters
120 ----------
121 ----------
121 txt : str
122 txt : str
122 Text output of a test run, assumed to contain a line of one of the
123 Text output of a test run, assumed to contain a line of one of the
123 following forms::
124 following forms::
124 'FAILED (errors=1)'
125 'FAILED (errors=1)'
125 'FAILED (failures=1)'
126 'FAILED (failures=1)'
126 'FAILED (errors=1, failures=1)'
127 'FAILED (errors=1, failures=1)'
127
128
128 Returns
129 Returns
129 -------
130 -------
130 nerr, nfail: number of errors and failures.
131 nerr, nfail: number of errors and failures.
131 """
132 """
132
133
133 err_m = re.search(r'^FAILED \(errors=(\d+)\)', txt, re.MULTILINE)
134 err_m = re.search(r'^FAILED \(errors=(\d+)\)', txt, re.MULTILINE)
134 if err_m:
135 if err_m:
135 nerr = int(err_m.group(1))
136 nerr = int(err_m.group(1))
136 nfail = 0
137 nfail = 0
137 return nerr, nfail
138 return nerr, nfail
138
139
139 fail_m = re.search(r'^FAILED \(failures=(\d+)\)', txt, re.MULTILINE)
140 fail_m = re.search(r'^FAILED \(failures=(\d+)\)', txt, re.MULTILINE)
140 if fail_m:
141 if fail_m:
141 nerr = 0
142 nerr = 0
142 nfail = int(fail_m.group(1))
143 nfail = int(fail_m.group(1))
143 return nerr, nfail
144 return nerr, nfail
144
145
145 both_m = re.search(r'^FAILED \(errors=(\d+), failures=(\d+)\)', txt,
146 both_m = re.search(r'^FAILED \(errors=(\d+), failures=(\d+)\)', txt,
146 re.MULTILINE)
147 re.MULTILINE)
147 if both_m:
148 if both_m:
148 nerr = int(both_m.group(1))
149 nerr = int(both_m.group(1))
149 nfail = int(both_m.group(2))
150 nfail = int(both_m.group(2))
150 return nerr, nfail
151 return nerr, nfail
151
152
152 # If the input didn't match any of these forms, assume no error/failures
153 # If the input didn't match any of these forms, assume no error/failures
153 return 0, 0
154 return 0, 0
154
155
155
156
156 # So nose doesn't think this is a test
157 # So nose doesn't think this is a test
157 parse_test_output.__test__ = False
158 parse_test_output.__test__ = False
158
159
159
160
160 def default_argv():
161 def default_argv():
161 """Return a valid default argv for creating testing instances of ipython"""
162 """Return a valid default argv for creating testing instances of ipython"""
162
163
163 return ['--quick', # so no config file is loaded
164 return ['--quick', # so no config file is loaded
164 # Other defaults to minimize side effects on stdout
165 # Other defaults to minimize side effects on stdout
165 '--colors=NoColor', '--no-term-title','--no-banner',
166 '--colors=NoColor', '--no-term-title','--no-banner',
166 '--autocall=0']
167 '--autocall=0']
167
168
168
169
169 def default_config():
170 def default_config():
170 """Return a config object with good defaults for testing."""
171 """Return a config object with good defaults for testing."""
171 config = Config()
172 config = Config()
172 config.TerminalInteractiveShell.colors = 'NoColor'
173 config.TerminalInteractiveShell.colors = 'NoColor'
173 config.TerminalTerminalInteractiveShell.term_title = False,
174 config.TerminalTerminalInteractiveShell.term_title = False,
174 config.TerminalInteractiveShell.autocall = 0
175 config.TerminalInteractiveShell.autocall = 0
175 config.HistoryManager.hist_file = tempfile.mktemp(u'test_hist.sqlite')
176 config.HistoryManager.hist_file = tempfile.mktemp(u'test_hist.sqlite')
176 config.HistoryManager.db_cache_size = 10000
177 config.HistoryManager.db_cache_size = 10000
177 return config
178 return config
178
179
179
180
180 def ipexec(fname, options=None):
181 def ipexec(fname, options=None):
181 """Utility to call 'ipython filename'.
182 """Utility to call 'ipython filename'.
182
183
183 Starts IPython witha minimal and safe configuration to make startup as fast
184 Starts IPython witha minimal and safe configuration to make startup as fast
184 as possible.
185 as possible.
185
186
186 Note that this starts IPython in a subprocess!
187 Note that this starts IPython in a subprocess!
187
188
188 Parameters
189 Parameters
189 ----------
190 ----------
190 fname : str
191 fname : str
191 Name of file to be executed (should have .py or .ipy extension).
192 Name of file to be executed (should have .py or .ipy extension).
192
193
193 options : optional, list
194 options : optional, list
194 Extra command-line flags to be passed to IPython.
195 Extra command-line flags to be passed to IPython.
195
196
196 Returns
197 Returns
197 -------
198 -------
198 (stdout, stderr) of ipython subprocess.
199 (stdout, stderr) of ipython subprocess.
199 """
200 """
200 if options is None: options = []
201 if options is None: options = []
201
202
202 # For these subprocess calls, eliminate all prompt printing so we only see
203 # For these subprocess calls, eliminate all prompt printing so we only see
203 # output from script execution
204 # output from script execution
204 prompt_opts = [ '--InteractiveShell.prompt_in1=""',
205 prompt_opts = [ '--InteractiveShell.prompt_in1=""',
205 '--InteractiveShell.prompt_in2=""',
206 '--InteractiveShell.prompt_in2=""',
206 '--InteractiveShell.prompt_out=""'
207 '--InteractiveShell.prompt_out=""'
207 ]
208 ]
208 cmdargs = ' '.join(default_argv() + prompt_opts + options)
209 cmdargs = ' '.join(default_argv() + prompt_opts + options)
209
210
210 _ip = get_ipython()
211 _ip = get_ipython()
211 test_dir = os.path.dirname(__file__)
212 test_dir = os.path.dirname(__file__)
212
213
213 ipython_cmd = find_cmd('ipython3' if PY3 else 'ipython')
214 ipython_cmd = find_cmd('ipython3' if py3compat.PY3 else 'ipython')
214 # Absolute path for filename
215 # Absolute path for filename
215 full_fname = os.path.join(test_dir, fname)
216 full_fname = os.path.join(test_dir, fname)
216 full_cmd = '%s %s %s' % (ipython_cmd, cmdargs, full_fname)
217 full_cmd = '%s %s %s' % (ipython_cmd, cmdargs, full_fname)
217 #print >> sys.stderr, 'FULL CMD:', full_cmd # dbg
218 #print >> sys.stderr, 'FULL CMD:', full_cmd # dbg
218 out = getoutputerror(full_cmd)
219 out = getoutputerror(full_cmd)
219 # `import readline` causes 'ESC[?1034h' to be the first output sometimes,
220 # `import readline` causes 'ESC[?1034h' to be the first output sometimes,
220 # so strip that off the front of the first line if it is found
221 # so strip that off the front of the first line if it is found
221 if out:
222 if out:
222 first = out[0]
223 first = out[0]
223 m = re.match(r'\x1b\[[^h]+h', first)
224 m = re.match(r'\x1b\[[^h]+h', first)
224 if m:
225 if m:
225 # strip initial readline escape
226 # strip initial readline escape
226 out = list(out)
227 out = list(out)
227 out[0] = first[len(m.group()):]
228 out[0] = first[len(m.group()):]
228 out = tuple(out)
229 out = tuple(out)
229 return out
230 return out
230
231
231
232
232 def ipexec_validate(fname, expected_out, expected_err='',
233 def ipexec_validate(fname, expected_out, expected_err='',
233 options=None):
234 options=None):
234 """Utility to call 'ipython filename' and validate output/error.
235 """Utility to call 'ipython filename' and validate output/error.
235
236
236 This function raises an AssertionError if the validation fails.
237 This function raises an AssertionError if the validation fails.
237
238
238 Note that this starts IPython in a subprocess!
239 Note that this starts IPython in a subprocess!
239
240
240 Parameters
241 Parameters
241 ----------
242 ----------
242 fname : str
243 fname : str
243 Name of the file to be executed (should have .py or .ipy extension).
244 Name of the file to be executed (should have .py or .ipy extension).
244
245
245 expected_out : str
246 expected_out : str
246 Expected stdout of the process.
247 Expected stdout of the process.
247
248
248 expected_err : optional, str
249 expected_err : optional, str
249 Expected stderr of the process.
250 Expected stderr of the process.
250
251
251 options : optional, list
252 options : optional, list
252 Extra command-line flags to be passed to IPython.
253 Extra command-line flags to be passed to IPython.
253
254
254 Returns
255 Returns
255 -------
256 -------
256 None
257 None
257 """
258 """
258
259
259 import nose.tools as nt
260 import nose.tools as nt
260
261
261 out, err = ipexec(fname)
262 out, err = ipexec(fname)
262 #print 'OUT', out # dbg
263 #print 'OUT', out # dbg
263 #print 'ERR', err # dbg
264 #print 'ERR', err # dbg
264 # If there are any errors, we must check those befor stdout, as they may be
265 # If there are any errors, we must check those befor stdout, as they may be
265 # more informative than simply having an empty stdout.
266 # more informative than simply having an empty stdout.
266 if err:
267 if err:
267 if expected_err:
268 if expected_err:
268 nt.assert_equals(err.strip(), expected_err.strip())
269 nt.assert_equals(err.strip(), expected_err.strip())
269 else:
270 else:
270 raise ValueError('Running file %r produced error: %r' %
271 raise ValueError('Running file %r produced error: %r' %
271 (fname, err))
272 (fname, err))
272 # If no errors or output on stderr was expected, match stdout
273 # If no errors or output on stderr was expected, match stdout
273 nt.assert_equals(out.strip(), expected_out.strip())
274 nt.assert_equals(out.strip(), expected_out.strip())
274
275
275
276
276 class TempFileMixin(object):
277 class TempFileMixin(object):
277 """Utility class to create temporary Python/IPython files.
278 """Utility class to create temporary Python/IPython files.
278
279
279 Meant as a mixin class for test cases."""
280 Meant as a mixin class for test cases."""
280
281
281 def mktmp(self, src, ext='.py'):
282 def mktmp(self, src, ext='.py'):
282 """Make a valid python temp file."""
283 """Make a valid python temp file."""
283 fname, f = temp_pyfile(src, ext)
284 fname, f = temp_pyfile(src, ext)
284 self.tmpfile = f
285 self.tmpfile = f
285 self.fname = fname
286 self.fname = fname
286
287
287 def tearDown(self):
288 def tearDown(self):
288 if hasattr(self, 'tmpfile'):
289 if hasattr(self, 'tmpfile'):
289 # If the tmpfile wasn't made because of skipped tests, like in
290 # If the tmpfile wasn't made because of skipped tests, like in
290 # win32, there's nothing to cleanup.
291 # win32, there's nothing to cleanup.
291 self.tmpfile.close()
292 self.tmpfile.close()
292 try:
293 try:
293 os.unlink(self.fname)
294 os.unlink(self.fname)
294 except:
295 except:
295 # On Windows, even though we close the file, we still can't
296 # On Windows, even though we close the file, we still can't
296 # delete it. I have no clue why
297 # delete it. I have no clue why
297 pass
298 pass
298
299
299 pair_fail_msg = ("Testing {0}\n\n"
300 pair_fail_msg = ("Testing {0}\n\n"
300 "In:\n"
301 "In:\n"
301 " {1!r}\n"
302 " {1!r}\n"
302 "Expected:\n"
303 "Expected:\n"
303 " {2!r}\n"
304 " {2!r}\n"
304 "Got:\n"
305 "Got:\n"
305 " {3!r}\n")
306 " {3!r}\n")
306 def check_pairs(func, pairs):
307 def check_pairs(func, pairs):
307 """Utility function for the common case of checking a function with a
308 """Utility function for the common case of checking a function with a
308 sequence of input/output pairs.
309 sequence of input/output pairs.
309
310
310 Parameters
311 Parameters
311 ----------
312 ----------
312 func : callable
313 func : callable
313 The function to be tested. Should accept a single argument.
314 The function to be tested. Should accept a single argument.
314 pairs : iterable
315 pairs : iterable
315 A list of (input, expected_output) tuples.
316 A list of (input, expected_output) tuples.
316
317
317 Returns
318 Returns
318 -------
319 -------
319 None. Raises an AssertionError if any output does not match the expected
320 None. Raises an AssertionError if any output does not match the expected
320 value.
321 value.
321 """
322 """
322 name = getattr(func, "func_name", getattr(func, "__name__", "<unknown>"))
323 name = getattr(func, "func_name", getattr(func, "__name__", "<unknown>"))
323 for inp, expected in pairs:
324 for inp, expected in pairs:
324 out = func(inp)
325 out = func(inp)
325 assert out == expected, pair_fail_msg.format(name, inp, expected, out)
326 assert out == expected, pair_fail_msg.format(name, inp, expected, out)
326
327
328 if py3compat.PY3:
329 MyStringIO = StringIO
330 else:
331 # In Python 2, stdout/stderr can have either bytes or unicode written to them,
332 # so we need a class that can handle both.
333 class MyStringIO(StringIO):
334 def write(self, s):
335 s = py3compat.cast_unicode(s, encoding=getdefaultencoding())
336 super(MyStringIO, self).write(s)
337
338 notprinted_msg = """Did not find {0!r} in printed output (on {1}):
339 {2!r}"""
340 class AssertPrints(object):
341 """Context manager for testing that code prints certain text.
342
343 Examples
344 --------
345 >>> with AssertPrints("abc"):
346 ... print "abcd"
347 ... print "def"
348 ...
349 abcd
350 def
351 """
352 def __init__(self, s, channel='stdout'):
353 self.s = s
354 self.channel = channel
355
356 def __enter__(self):
357 self.orig_stream = getattr(sys, self.channel)
358 self.buffer = MyStringIO()
359 self.tee = Tee(self.buffer, channel=self.channel)
360 setattr(sys, self.channel, self.tee)
361
362 def __exit__(self, etype, value, traceback):
363 self.tee.flush()
364 setattr(sys, self.channel, self.orig_stream)
365 printed = self.buffer.getvalue()
366 assert self.s in printed, notprinted_msg.format(self.s, self.channel, printed)
367 return False
368
327 @contextmanager
369 @contextmanager
328 def mute_warn():
370 def mute_warn():
329 from IPython.utils import warn
371 from IPython.utils import warn
330 save_warn = warn.warn
372 save_warn = warn.warn
331 warn.warn = lambda *a, **kw: None
373 warn.warn = lambda *a, **kw: None
332 try:
374 try:
333 yield
375 yield
334 finally:
376 finally:
335 warn.warn = save_warn
377 warn.warn = save_warn
336
378
337 @contextmanager
379 @contextmanager
338 def make_tempfile(name):
380 def make_tempfile(name):
339 """ Create an empty, named, temporary file for the duration of the context.
381 """ Create an empty, named, temporary file for the duration of the context.
340 """
382 """
341 f = open(name, 'w')
383 f = open(name, 'w')
342 f.close()
384 f.close()
343 try:
385 try:
344 yield
386 yield
345 finally:
387 finally:
346 os.unlink(name)
388 os.unlink(name)
@@ -1,450 +1,445 b''
1 # encoding: utf-8
1 # encoding: utf-8
2 """Tests for IPython.utils.path.py"""
2 """Tests for IPython.utils.path.py"""
3
3
4 #-----------------------------------------------------------------------------
4 #-----------------------------------------------------------------------------
5 # Copyright (C) 2008 The IPython Development Team
5 # Copyright (C) 2008 The IPython Development Team
6 #
6 #
7 # Distributed under the terms of the BSD License. The full license is in
7 # Distributed under the terms of the BSD License. The full license is in
8 # the file COPYING, distributed as part of this software.
8 # the file COPYING, distributed as part of this software.
9 #-----------------------------------------------------------------------------
9 #-----------------------------------------------------------------------------
10
10
11 #-----------------------------------------------------------------------------
11 #-----------------------------------------------------------------------------
12 # Imports
12 # Imports
13 #-----------------------------------------------------------------------------
13 #-----------------------------------------------------------------------------
14
14
15 from __future__ import with_statement
15 from __future__ import with_statement
16
16
17 import os
17 import os
18 import shutil
18 import shutil
19 import sys
19 import sys
20 import tempfile
20 import tempfile
21 from io import StringIO
21 from io import StringIO
22
22
23 from os.path import join, abspath, split
23 from os.path import join, abspath, split
24
24
25 import nose.tools as nt
25 import nose.tools as nt
26
26
27 from nose import with_setup
27 from nose import with_setup
28
28
29 import IPython
29 import IPython
30 from IPython.testing import decorators as dec
30 from IPython.testing import decorators as dec
31 from IPython.testing.decorators import skip_if_not_win32, skip_win32
31 from IPython.testing.decorators import skip_if_not_win32, skip_win32
32 from IPython.testing.tools import make_tempfile
32 from IPython.testing.tools import make_tempfile, AssertPrints
33 from IPython.utils import path, io
33 from IPython.utils import path, io
34 from IPython.utils import py3compat
34 from IPython.utils import py3compat
35
35
36 # Platform-dependent imports
36 # Platform-dependent imports
37 try:
37 try:
38 import _winreg as wreg
38 import _winreg as wreg
39 except ImportError:
39 except ImportError:
40 #Fake _winreg module on none windows platforms
40 #Fake _winreg module on none windows platforms
41 import types
41 import types
42 wr_name = "winreg" if py3compat.PY3 else "_winreg"
42 wr_name = "winreg" if py3compat.PY3 else "_winreg"
43 sys.modules[wr_name] = types.ModuleType(wr_name)
43 sys.modules[wr_name] = types.ModuleType(wr_name)
44 import _winreg as wreg
44 import _winreg as wreg
45 #Add entries that needs to be stubbed by the testing code
45 #Add entries that needs to be stubbed by the testing code
46 (wreg.OpenKey, wreg.QueryValueEx,) = (None, None)
46 (wreg.OpenKey, wreg.QueryValueEx,) = (None, None)
47
47
48 try:
48 try:
49 reload
49 reload
50 except NameError: # Python 3
50 except NameError: # Python 3
51 from imp import reload
51 from imp import reload
52
52
53 #-----------------------------------------------------------------------------
53 #-----------------------------------------------------------------------------
54 # Globals
54 # Globals
55 #-----------------------------------------------------------------------------
55 #-----------------------------------------------------------------------------
56 env = os.environ
56 env = os.environ
57 TEST_FILE_PATH = split(abspath(__file__))[0]
57 TEST_FILE_PATH = split(abspath(__file__))[0]
58 TMP_TEST_DIR = tempfile.mkdtemp()
58 TMP_TEST_DIR = tempfile.mkdtemp()
59 HOME_TEST_DIR = join(TMP_TEST_DIR, "home_test_dir")
59 HOME_TEST_DIR = join(TMP_TEST_DIR, "home_test_dir")
60 XDG_TEST_DIR = join(HOME_TEST_DIR, "xdg_test_dir")
60 XDG_TEST_DIR = join(HOME_TEST_DIR, "xdg_test_dir")
61 IP_TEST_DIR = join(HOME_TEST_DIR,'.ipython')
61 IP_TEST_DIR = join(HOME_TEST_DIR,'.ipython')
62 #
62 #
63 # Setup/teardown functions/decorators
63 # Setup/teardown functions/decorators
64 #
64 #
65
65
66 def setup():
66 def setup():
67 """Setup testenvironment for the module:
67 """Setup testenvironment for the module:
68
68
69 - Adds dummy home dir tree
69 - Adds dummy home dir tree
70 """
70 """
71 # Do not mask exceptions here. In particular, catching WindowsError is a
71 # Do not mask exceptions here. In particular, catching WindowsError is a
72 # problem because that exception is only defined on Windows...
72 # problem because that exception is only defined on Windows...
73 os.makedirs(IP_TEST_DIR)
73 os.makedirs(IP_TEST_DIR)
74 os.makedirs(os.path.join(XDG_TEST_DIR, 'ipython'))
74 os.makedirs(os.path.join(XDG_TEST_DIR, 'ipython'))
75
75
76
76
77 def teardown():
77 def teardown():
78 """Teardown testenvironment for the module:
78 """Teardown testenvironment for the module:
79
79
80 - Remove dummy home dir tree
80 - Remove dummy home dir tree
81 """
81 """
82 # Note: we remove the parent test dir, which is the root of all test
82 # Note: we remove the parent test dir, which is the root of all test
83 # subdirs we may have created. Use shutil instead of os.removedirs, so
83 # subdirs we may have created. Use shutil instead of os.removedirs, so
84 # that non-empty directories are all recursively removed.
84 # that non-empty directories are all recursively removed.
85 shutil.rmtree(TMP_TEST_DIR)
85 shutil.rmtree(TMP_TEST_DIR)
86
86
87
87
88 def setup_environment():
88 def setup_environment():
89 """Setup testenvironment for some functions that are tested
89 """Setup testenvironment for some functions that are tested
90 in this module. In particular this functions stores attributes
90 in this module. In particular this functions stores attributes
91 and other things that we need to stub in some test functions.
91 and other things that we need to stub in some test functions.
92 This needs to be done on a function level and not module level because
92 This needs to be done on a function level and not module level because
93 each testfunction needs a pristine environment.
93 each testfunction needs a pristine environment.
94 """
94 """
95 global oldstuff, platformstuff
95 global oldstuff, platformstuff
96 oldstuff = (env.copy(), os.name, path.get_home_dir, IPython.__file__, os.getcwd())
96 oldstuff = (env.copy(), os.name, path.get_home_dir, IPython.__file__, os.getcwd())
97
97
98 if os.name == 'nt':
98 if os.name == 'nt':
99 platformstuff = (wreg.OpenKey, wreg.QueryValueEx,)
99 platformstuff = (wreg.OpenKey, wreg.QueryValueEx,)
100
100
101
101
102 def teardown_environment():
102 def teardown_environment():
103 """Restore things that were remebered by the setup_environment function
103 """Restore things that were remebered by the setup_environment function
104 """
104 """
105 (oldenv, os.name, path.get_home_dir, IPython.__file__, old_wd) = oldstuff
105 (oldenv, os.name, path.get_home_dir, IPython.__file__, old_wd) = oldstuff
106 os.chdir(old_wd)
106 os.chdir(old_wd)
107 reload(path)
107 reload(path)
108
108
109 for key in env.keys():
109 for key in env.keys():
110 if key not in oldenv:
110 if key not in oldenv:
111 del env[key]
111 del env[key]
112 env.update(oldenv)
112 env.update(oldenv)
113 if hasattr(sys, 'frozen'):
113 if hasattr(sys, 'frozen'):
114 del sys.frozen
114 del sys.frozen
115 if os.name == 'nt':
115 if os.name == 'nt':
116 (wreg.OpenKey, wreg.QueryValueEx,) = platformstuff
116 (wreg.OpenKey, wreg.QueryValueEx,) = platformstuff
117
117
118 # Build decorator that uses the setup_environment/setup_environment
118 # Build decorator that uses the setup_environment/setup_environment
119 with_environment = with_setup(setup_environment, teardown_environment)
119 with_environment = with_setup(setup_environment, teardown_environment)
120
120
121
121
122 @skip_if_not_win32
122 @skip_if_not_win32
123 @with_environment
123 @with_environment
124 def test_get_home_dir_1():
124 def test_get_home_dir_1():
125 """Testcase for py2exe logic, un-compressed lib
125 """Testcase for py2exe logic, un-compressed lib
126 """
126 """
127 sys.frozen = True
127 sys.frozen = True
128
128
129 #fake filename for IPython.__init__
129 #fake filename for IPython.__init__
130 IPython.__file__ = abspath(join(HOME_TEST_DIR, "Lib/IPython/__init__.py"))
130 IPython.__file__ = abspath(join(HOME_TEST_DIR, "Lib/IPython/__init__.py"))
131
131
132 home_dir = path.get_home_dir()
132 home_dir = path.get_home_dir()
133 nt.assert_equal(home_dir, abspath(HOME_TEST_DIR))
133 nt.assert_equal(home_dir, abspath(HOME_TEST_DIR))
134
134
135
135
136 @skip_if_not_win32
136 @skip_if_not_win32
137 @with_environment
137 @with_environment
138 def test_get_home_dir_2():
138 def test_get_home_dir_2():
139 """Testcase for py2exe logic, compressed lib
139 """Testcase for py2exe logic, compressed lib
140 """
140 """
141 sys.frozen = True
141 sys.frozen = True
142 #fake filename for IPython.__init__
142 #fake filename for IPython.__init__
143 IPython.__file__ = abspath(join(HOME_TEST_DIR, "Library.zip/IPython/__init__.py")).lower()
143 IPython.__file__ = abspath(join(HOME_TEST_DIR, "Library.zip/IPython/__init__.py")).lower()
144
144
145 home_dir = path.get_home_dir()
145 home_dir = path.get_home_dir()
146 nt.assert_equal(home_dir, abspath(HOME_TEST_DIR).lower())
146 nt.assert_equal(home_dir, abspath(HOME_TEST_DIR).lower())
147
147
148
148
149 @with_environment
149 @with_environment
150 @skip_win32
150 @skip_win32
151 def test_get_home_dir_3():
151 def test_get_home_dir_3():
152 """Testcase $HOME is set, then use its value as home directory."""
152 """Testcase $HOME is set, then use its value as home directory."""
153 env["HOME"] = HOME_TEST_DIR
153 env["HOME"] = HOME_TEST_DIR
154 home_dir = path.get_home_dir()
154 home_dir = path.get_home_dir()
155 nt.assert_equal(home_dir, env["HOME"])
155 nt.assert_equal(home_dir, env["HOME"])
156
156
157
157
158 @with_environment
158 @with_environment
159 @skip_win32
159 @skip_win32
160 def test_get_home_dir_4():
160 def test_get_home_dir_4():
161 """Testcase $HOME is not set, os=='posix'.
161 """Testcase $HOME is not set, os=='posix'.
162 This should fail with HomeDirError"""
162 This should fail with HomeDirError"""
163
163
164 os.name = 'posix'
164 os.name = 'posix'
165 if 'HOME' in env: del env['HOME']
165 if 'HOME' in env: del env['HOME']
166 nt.assert_raises(path.HomeDirError, path.get_home_dir)
166 nt.assert_raises(path.HomeDirError, path.get_home_dir)
167
167
168
168
169 @skip_if_not_win32
169 @skip_if_not_win32
170 @with_environment
170 @with_environment
171 def test_get_home_dir_5():
171 def test_get_home_dir_5():
172 """Using HOMEDRIVE + HOMEPATH, os=='nt'.
172 """Using HOMEDRIVE + HOMEPATH, os=='nt'.
173
173
174 HOMESHARE is missing.
174 HOMESHARE is missing.
175 """
175 """
176
176
177 os.name = 'nt'
177 os.name = 'nt'
178 env.pop('HOMESHARE', None)
178 env.pop('HOMESHARE', None)
179 env['HOMEDRIVE'], env['HOMEPATH'] = os.path.splitdrive(HOME_TEST_DIR)
179 env['HOMEDRIVE'], env['HOMEPATH'] = os.path.splitdrive(HOME_TEST_DIR)
180 home_dir = path.get_home_dir()
180 home_dir = path.get_home_dir()
181 nt.assert_equal(home_dir, abspath(HOME_TEST_DIR))
181 nt.assert_equal(home_dir, abspath(HOME_TEST_DIR))
182
182
183
183
184 @skip_if_not_win32
184 @skip_if_not_win32
185 @with_environment
185 @with_environment
186 def test_get_home_dir_6():
186 def test_get_home_dir_6():
187 """Using USERPROFILE, os=='nt'.
187 """Using USERPROFILE, os=='nt'.
188
188
189 HOMESHARE, HOMEDRIVE, HOMEPATH are missing.
189 HOMESHARE, HOMEDRIVE, HOMEPATH are missing.
190 """
190 """
191
191
192 os.name = 'nt'
192 os.name = 'nt'
193 env.pop('HOMESHARE', None)
193 env.pop('HOMESHARE', None)
194 env.pop('HOMEDRIVE', None)
194 env.pop('HOMEDRIVE', None)
195 env.pop('HOMEPATH', None)
195 env.pop('HOMEPATH', None)
196 env["USERPROFILE"] = abspath(HOME_TEST_DIR)
196 env["USERPROFILE"] = abspath(HOME_TEST_DIR)
197 home_dir = path.get_home_dir()
197 home_dir = path.get_home_dir()
198 nt.assert_equal(home_dir, abspath(HOME_TEST_DIR))
198 nt.assert_equal(home_dir, abspath(HOME_TEST_DIR))
199
199
200
200
201 @skip_if_not_win32
201 @skip_if_not_win32
202 @with_environment
202 @with_environment
203 def test_get_home_dir_7():
203 def test_get_home_dir_7():
204 """Using HOMESHARE, os=='nt'."""
204 """Using HOMESHARE, os=='nt'."""
205
205
206 os.name = 'nt'
206 os.name = 'nt'
207 env["HOMESHARE"] = abspath(HOME_TEST_DIR)
207 env["HOMESHARE"] = abspath(HOME_TEST_DIR)
208 home_dir = path.get_home_dir()
208 home_dir = path.get_home_dir()
209 nt.assert_equal(home_dir, abspath(HOME_TEST_DIR))
209 nt.assert_equal(home_dir, abspath(HOME_TEST_DIR))
210
210
211
211
212 # Should we stub wreg fully so we can run the test on all platforms?
212 # Should we stub wreg fully so we can run the test on all platforms?
213 @skip_if_not_win32
213 @skip_if_not_win32
214 @with_environment
214 @with_environment
215 def test_get_home_dir_8():
215 def test_get_home_dir_8():
216 """Using registry hack for 'My Documents', os=='nt'
216 """Using registry hack for 'My Documents', os=='nt'
217
217
218 HOMESHARE, HOMEDRIVE, HOMEPATH, USERPROFILE and others are missing.
218 HOMESHARE, HOMEDRIVE, HOMEPATH, USERPROFILE and others are missing.
219 """
219 """
220 os.name = 'nt'
220 os.name = 'nt'
221 # Remove from stub environment all keys that may be set
221 # Remove from stub environment all keys that may be set
222 for key in ['HOME', 'HOMESHARE', 'HOMEDRIVE', 'HOMEPATH', 'USERPROFILE']:
222 for key in ['HOME', 'HOMESHARE', 'HOMEDRIVE', 'HOMEPATH', 'USERPROFILE']:
223 env.pop(key, None)
223 env.pop(key, None)
224
224
225 #Stub windows registry functions
225 #Stub windows registry functions
226 def OpenKey(x, y):
226 def OpenKey(x, y):
227 class key:
227 class key:
228 def Close(self):
228 def Close(self):
229 pass
229 pass
230 return key()
230 return key()
231 def QueryValueEx(x, y):
231 def QueryValueEx(x, y):
232 return [abspath(HOME_TEST_DIR)]
232 return [abspath(HOME_TEST_DIR)]
233
233
234 wreg.OpenKey = OpenKey
234 wreg.OpenKey = OpenKey
235 wreg.QueryValueEx = QueryValueEx
235 wreg.QueryValueEx = QueryValueEx
236
236
237 home_dir = path.get_home_dir()
237 home_dir = path.get_home_dir()
238 nt.assert_equal(home_dir, abspath(HOME_TEST_DIR))
238 nt.assert_equal(home_dir, abspath(HOME_TEST_DIR))
239
239
240
240
241 @with_environment
241 @with_environment
242 def test_get_ipython_dir_1():
242 def test_get_ipython_dir_1():
243 """test_get_ipython_dir_1, Testcase to see if we can call get_ipython_dir without Exceptions."""
243 """test_get_ipython_dir_1, Testcase to see if we can call get_ipython_dir without Exceptions."""
244 env_ipdir = os.path.join("someplace", ".ipython")
244 env_ipdir = os.path.join("someplace", ".ipython")
245 path._writable_dir = lambda path: True
245 path._writable_dir = lambda path: True
246 env['IPYTHON_DIR'] = env_ipdir
246 env['IPYTHON_DIR'] = env_ipdir
247 ipdir = path.get_ipython_dir()
247 ipdir = path.get_ipython_dir()
248 nt.assert_equal(ipdir, env_ipdir)
248 nt.assert_equal(ipdir, env_ipdir)
249
249
250
250
251 @with_environment
251 @with_environment
252 def test_get_ipython_dir_2():
252 def test_get_ipython_dir_2():
253 """test_get_ipython_dir_2, Testcase to see if we can call get_ipython_dir without Exceptions."""
253 """test_get_ipython_dir_2, Testcase to see if we can call get_ipython_dir without Exceptions."""
254 path.get_home_dir = lambda : "someplace"
254 path.get_home_dir = lambda : "someplace"
255 path.get_xdg_dir = lambda : None
255 path.get_xdg_dir = lambda : None
256 path._writable_dir = lambda path: True
256 path._writable_dir = lambda path: True
257 os.name = "posix"
257 os.name = "posix"
258 env.pop('IPYTHON_DIR', None)
258 env.pop('IPYTHON_DIR', None)
259 env.pop('IPYTHONDIR', None)
259 env.pop('IPYTHONDIR', None)
260 env.pop('XDG_CONFIG_HOME', None)
260 env.pop('XDG_CONFIG_HOME', None)
261 ipdir = path.get_ipython_dir()
261 ipdir = path.get_ipython_dir()
262 nt.assert_equal(ipdir, os.path.join("someplace", ".ipython"))
262 nt.assert_equal(ipdir, os.path.join("someplace", ".ipython"))
263
263
264 @with_environment
264 @with_environment
265 def test_get_ipython_dir_3():
265 def test_get_ipython_dir_3():
266 """test_get_ipython_dir_3, use XDG if defined, and .ipython doesn't exist."""
266 """test_get_ipython_dir_3, use XDG if defined, and .ipython doesn't exist."""
267 path.get_home_dir = lambda : "someplace"
267 path.get_home_dir = lambda : "someplace"
268 path._writable_dir = lambda path: True
268 path._writable_dir = lambda path: True
269 os.name = "posix"
269 os.name = "posix"
270 env.pop('IPYTHON_DIR', None)
270 env.pop('IPYTHON_DIR', None)
271 env.pop('IPYTHONDIR', None)
271 env.pop('IPYTHONDIR', None)
272 env['XDG_CONFIG_HOME'] = XDG_TEST_DIR
272 env['XDG_CONFIG_HOME'] = XDG_TEST_DIR
273 ipdir = path.get_ipython_dir()
273 ipdir = path.get_ipython_dir()
274 nt.assert_equal(ipdir, os.path.join(XDG_TEST_DIR, "ipython"))
274 nt.assert_equal(ipdir, os.path.join(XDG_TEST_DIR, "ipython"))
275
275
276 @with_environment
276 @with_environment
277 def test_get_ipython_dir_4():
277 def test_get_ipython_dir_4():
278 """test_get_ipython_dir_4, use XDG if both exist."""
278 """test_get_ipython_dir_4, use XDG if both exist."""
279 path.get_home_dir = lambda : HOME_TEST_DIR
279 path.get_home_dir = lambda : HOME_TEST_DIR
280 os.name = "posix"
280 os.name = "posix"
281 env.pop('IPYTHON_DIR', None)
281 env.pop('IPYTHON_DIR', None)
282 env.pop('IPYTHONDIR', None)
282 env.pop('IPYTHONDIR', None)
283 env['XDG_CONFIG_HOME'] = XDG_TEST_DIR
283 env['XDG_CONFIG_HOME'] = XDG_TEST_DIR
284 xdg_ipdir = os.path.join(XDG_TEST_DIR, "ipython")
284 xdg_ipdir = os.path.join(XDG_TEST_DIR, "ipython")
285 ipdir = path.get_ipython_dir()
285 ipdir = path.get_ipython_dir()
286 nt.assert_equal(ipdir, xdg_ipdir)
286 nt.assert_equal(ipdir, xdg_ipdir)
287
287
288 @with_environment
288 @with_environment
289 def test_get_ipython_dir_5():
289 def test_get_ipython_dir_5():
290 """test_get_ipython_dir_5, use .ipython if exists and XDG defined, but doesn't exist."""
290 """test_get_ipython_dir_5, use .ipython if exists and XDG defined, but doesn't exist."""
291 path.get_home_dir = lambda : HOME_TEST_DIR
291 path.get_home_dir = lambda : HOME_TEST_DIR
292 os.name = "posix"
292 os.name = "posix"
293 env.pop('IPYTHON_DIR', None)
293 env.pop('IPYTHON_DIR', None)
294 env.pop('IPYTHONDIR', None)
294 env.pop('IPYTHONDIR', None)
295 env['XDG_CONFIG_HOME'] = XDG_TEST_DIR
295 env['XDG_CONFIG_HOME'] = XDG_TEST_DIR
296 os.rmdir(os.path.join(XDG_TEST_DIR, 'ipython'))
296 os.rmdir(os.path.join(XDG_TEST_DIR, 'ipython'))
297 ipdir = path.get_ipython_dir()
297 ipdir = path.get_ipython_dir()
298 nt.assert_equal(ipdir, IP_TEST_DIR)
298 nt.assert_equal(ipdir, IP_TEST_DIR)
299
299
300 @with_environment
300 @with_environment
301 def test_get_ipython_dir_6():
301 def test_get_ipython_dir_6():
302 """test_get_ipython_dir_6, use XDG if defined and neither exist."""
302 """test_get_ipython_dir_6, use XDG if defined and neither exist."""
303 xdg = os.path.join(HOME_TEST_DIR, 'somexdg')
303 xdg = os.path.join(HOME_TEST_DIR, 'somexdg')
304 os.mkdir(xdg)
304 os.mkdir(xdg)
305 shutil.rmtree(os.path.join(HOME_TEST_DIR, '.ipython'))
305 shutil.rmtree(os.path.join(HOME_TEST_DIR, '.ipython'))
306 path.get_home_dir = lambda : HOME_TEST_DIR
306 path.get_home_dir = lambda : HOME_TEST_DIR
307 path.get_xdg_dir = lambda : xdg
307 path.get_xdg_dir = lambda : xdg
308 os.name = "posix"
308 os.name = "posix"
309 env.pop('IPYTHON_DIR', None)
309 env.pop('IPYTHON_DIR', None)
310 env.pop('IPYTHONDIR', None)
310 env.pop('IPYTHONDIR', None)
311 env.pop('XDG_CONFIG_HOME', None)
311 env.pop('XDG_CONFIG_HOME', None)
312 xdg_ipdir = os.path.join(xdg, "ipython")
312 xdg_ipdir = os.path.join(xdg, "ipython")
313 ipdir = path.get_ipython_dir()
313 ipdir = path.get_ipython_dir()
314 nt.assert_equal(ipdir, xdg_ipdir)
314 nt.assert_equal(ipdir, xdg_ipdir)
315
315
316 @with_environment
316 @with_environment
317 def test_get_ipython_dir_7():
317 def test_get_ipython_dir_7():
318 """test_get_ipython_dir_7, test home directory expansion on IPYTHON_DIR"""
318 """test_get_ipython_dir_7, test home directory expansion on IPYTHON_DIR"""
319 path._writable_dir = lambda path: True
319 path._writable_dir = lambda path: True
320 home_dir = os.path.expanduser('~')
320 home_dir = os.path.expanduser('~')
321 env['IPYTHON_DIR'] = os.path.join('~', 'somewhere')
321 env['IPYTHON_DIR'] = os.path.join('~', 'somewhere')
322 ipdir = path.get_ipython_dir()
322 ipdir = path.get_ipython_dir()
323 nt.assert_equal(ipdir, os.path.join(home_dir, 'somewhere'))
323 nt.assert_equal(ipdir, os.path.join(home_dir, 'somewhere'))
324
324
325
325
326 @with_environment
326 @with_environment
327 def test_get_xdg_dir_1():
327 def test_get_xdg_dir_1():
328 """test_get_xdg_dir_1, check xdg_dir"""
328 """test_get_xdg_dir_1, check xdg_dir"""
329 reload(path)
329 reload(path)
330 path._writable_dir = lambda path: True
330 path._writable_dir = lambda path: True
331 path.get_home_dir = lambda : 'somewhere'
331 path.get_home_dir = lambda : 'somewhere'
332 os.name = "posix"
332 os.name = "posix"
333 env.pop('IPYTHON_DIR', None)
333 env.pop('IPYTHON_DIR', None)
334 env.pop('IPYTHONDIR', None)
334 env.pop('IPYTHONDIR', None)
335 env.pop('XDG_CONFIG_HOME', None)
335 env.pop('XDG_CONFIG_HOME', None)
336
336
337 nt.assert_equal(path.get_xdg_dir(), os.path.join('somewhere', '.config'))
337 nt.assert_equal(path.get_xdg_dir(), os.path.join('somewhere', '.config'))
338
338
339
339
340 @with_environment
340 @with_environment
341 def test_get_xdg_dir_1():
341 def test_get_xdg_dir_1():
342 """test_get_xdg_dir_1, check nonexistant xdg_dir"""
342 """test_get_xdg_dir_1, check nonexistant xdg_dir"""
343 reload(path)
343 reload(path)
344 path.get_home_dir = lambda : HOME_TEST_DIR
344 path.get_home_dir = lambda : HOME_TEST_DIR
345 os.name = "posix"
345 os.name = "posix"
346 env.pop('IPYTHON_DIR', None)
346 env.pop('IPYTHON_DIR', None)
347 env.pop('IPYTHONDIR', None)
347 env.pop('IPYTHONDIR', None)
348 env.pop('XDG_CONFIG_HOME', None)
348 env.pop('XDG_CONFIG_HOME', None)
349 nt.assert_equal(path.get_xdg_dir(), None)
349 nt.assert_equal(path.get_xdg_dir(), None)
350
350
351 @with_environment
351 @with_environment
352 def test_get_xdg_dir_2():
352 def test_get_xdg_dir_2():
353 """test_get_xdg_dir_2, check xdg_dir default to ~/.config"""
353 """test_get_xdg_dir_2, check xdg_dir default to ~/.config"""
354 reload(path)
354 reload(path)
355 path.get_home_dir = lambda : HOME_TEST_DIR
355 path.get_home_dir = lambda : HOME_TEST_DIR
356 os.name = "posix"
356 os.name = "posix"
357 env.pop('IPYTHON_DIR', None)
357 env.pop('IPYTHON_DIR', None)
358 env.pop('IPYTHONDIR', None)
358 env.pop('IPYTHONDIR', None)
359 env.pop('XDG_CONFIG_HOME', None)
359 env.pop('XDG_CONFIG_HOME', None)
360 cfgdir=os.path.join(path.get_home_dir(), '.config')
360 cfgdir=os.path.join(path.get_home_dir(), '.config')
361 os.makedirs(cfgdir)
361 os.makedirs(cfgdir)
362
362
363 nt.assert_equal(path.get_xdg_dir(), cfgdir)
363 nt.assert_equal(path.get_xdg_dir(), cfgdir)
364
364
365 def test_filefind():
365 def test_filefind():
366 """Various tests for filefind"""
366 """Various tests for filefind"""
367 f = tempfile.NamedTemporaryFile()
367 f = tempfile.NamedTemporaryFile()
368 # print 'fname:',f.name
368 # print 'fname:',f.name
369 alt_dirs = path.get_ipython_dir()
369 alt_dirs = path.get_ipython_dir()
370 t = path.filefind(f.name, alt_dirs)
370 t = path.filefind(f.name, alt_dirs)
371 # print 'found:',t
371 # print 'found:',t
372
372
373
373
374 def test_get_ipython_package_dir():
374 def test_get_ipython_package_dir():
375 ipdir = path.get_ipython_package_dir()
375 ipdir = path.get_ipython_package_dir()
376 nt.assert_true(os.path.isdir(ipdir))
376 nt.assert_true(os.path.isdir(ipdir))
377
377
378
378
379 def test_get_ipython_module_path():
379 def test_get_ipython_module_path():
380 ipapp_path = path.get_ipython_module_path('IPython.frontend.terminal.ipapp')
380 ipapp_path = path.get_ipython_module_path('IPython.frontend.terminal.ipapp')
381 nt.assert_true(os.path.isfile(ipapp_path))
381 nt.assert_true(os.path.isfile(ipapp_path))
382
382
383
383
384 @dec.skip_if_not_win32
384 @dec.skip_if_not_win32
385 def test_get_long_path_name_win32():
385 def test_get_long_path_name_win32():
386 p = path.get_long_path_name('c:\\docume~1')
386 p = path.get_long_path_name('c:\\docume~1')
387 nt.assert_equals(p,u'c:\\Documents and Settings')
387 nt.assert_equals(p,u'c:\\Documents and Settings')
388
388
389
389
390 @dec.skip_win32
390 @dec.skip_win32
391 def test_get_long_path_name():
391 def test_get_long_path_name():
392 p = path.get_long_path_name('/usr/local')
392 p = path.get_long_path_name('/usr/local')
393 nt.assert_equals(p,'/usr/local')
393 nt.assert_equals(p,'/usr/local')
394
394
395 @dec.skip_win32 # can't create not-user-writable dir on win
395 @dec.skip_win32 # can't create not-user-writable dir on win
396 @with_environment
396 @with_environment
397 def test_not_writable_ipdir():
397 def test_not_writable_ipdir():
398 tmpdir = tempfile.mkdtemp()
398 tmpdir = tempfile.mkdtemp()
399 os.name = "posix"
399 os.name = "posix"
400 env.pop('IPYTHON_DIR', None)
400 env.pop('IPYTHON_DIR', None)
401 env.pop('IPYTHONDIR', None)
401 env.pop('IPYTHONDIR', None)
402 env.pop('XDG_CONFIG_HOME', None)
402 env.pop('XDG_CONFIG_HOME', None)
403 env['HOME'] = tmpdir
403 env['HOME'] = tmpdir
404 ipdir = os.path.join(tmpdir, '.ipython')
404 ipdir = os.path.join(tmpdir, '.ipython')
405 os.mkdir(ipdir)
405 os.mkdir(ipdir)
406 os.chmod(ipdir, 600)
406 os.chmod(ipdir, 600)
407 stderr = io.stderr
407 with AssertPrints('WARNING', channel='stderr'):
408 pipe = StringIO()
408 ipdir = path.get_ipython_dir()
409 io.stderr = pipe
410 ipdir = path.get_ipython_dir()
411 io.stderr.flush()
412 io.stderr = stderr
413 nt.assert_true('WARNING' in pipe.getvalue())
414 env.pop('IPYTHON_DIR', None)
409 env.pop('IPYTHON_DIR', None)
415
410
416 def test_unquote_filename():
411 def test_unquote_filename():
417 for win32 in (True, False):
412 for win32 in (True, False):
418 nt.assert_equals(path.unquote_filename('foo.py', win32=win32), 'foo.py')
413 nt.assert_equals(path.unquote_filename('foo.py', win32=win32), 'foo.py')
419 nt.assert_equals(path.unquote_filename('foo bar.py', win32=win32), 'foo bar.py')
414 nt.assert_equals(path.unquote_filename('foo bar.py', win32=win32), 'foo bar.py')
420 nt.assert_equals(path.unquote_filename('"foo.py"', win32=True), 'foo.py')
415 nt.assert_equals(path.unquote_filename('"foo.py"', win32=True), 'foo.py')
421 nt.assert_equals(path.unquote_filename('"foo bar.py"', win32=True), 'foo bar.py')
416 nt.assert_equals(path.unquote_filename('"foo bar.py"', win32=True), 'foo bar.py')
422 nt.assert_equals(path.unquote_filename("'foo.py'", win32=True), 'foo.py')
417 nt.assert_equals(path.unquote_filename("'foo.py'", win32=True), 'foo.py')
423 nt.assert_equals(path.unquote_filename("'foo bar.py'", win32=True), 'foo bar.py')
418 nt.assert_equals(path.unquote_filename("'foo bar.py'", win32=True), 'foo bar.py')
424 nt.assert_equals(path.unquote_filename('"foo.py"', win32=False), '"foo.py"')
419 nt.assert_equals(path.unquote_filename('"foo.py"', win32=False), '"foo.py"')
425 nt.assert_equals(path.unquote_filename('"foo bar.py"', win32=False), '"foo bar.py"')
420 nt.assert_equals(path.unquote_filename('"foo bar.py"', win32=False), '"foo bar.py"')
426 nt.assert_equals(path.unquote_filename("'foo.py'", win32=False), "'foo.py'")
421 nt.assert_equals(path.unquote_filename("'foo.py'", win32=False), "'foo.py'")
427 nt.assert_equals(path.unquote_filename("'foo bar.py'", win32=False), "'foo bar.py'")
422 nt.assert_equals(path.unquote_filename("'foo bar.py'", win32=False), "'foo bar.py'")
428
423
429 @with_environment
424 @with_environment
430 def test_get_py_filename():
425 def test_get_py_filename():
431 os.chdir(TMP_TEST_DIR)
426 os.chdir(TMP_TEST_DIR)
432 for win32 in (True, False):
427 for win32 in (True, False):
433 with make_tempfile('foo.py'):
428 with make_tempfile('foo.py'):
434 nt.assert_equals(path.get_py_filename('foo.py', force_win32=win32), 'foo.py')
429 nt.assert_equals(path.get_py_filename('foo.py', force_win32=win32), 'foo.py')
435 nt.assert_equals(path.get_py_filename('foo', force_win32=win32), 'foo.py')
430 nt.assert_equals(path.get_py_filename('foo', force_win32=win32), 'foo.py')
436 with make_tempfile('foo'):
431 with make_tempfile('foo'):
437 nt.assert_equals(path.get_py_filename('foo', force_win32=win32), 'foo')
432 nt.assert_equals(path.get_py_filename('foo', force_win32=win32), 'foo')
438 nt.assert_raises(IOError, path.get_py_filename, 'foo.py', force_win32=win32)
433 nt.assert_raises(IOError, path.get_py_filename, 'foo.py', force_win32=win32)
439 nt.assert_raises(IOError, path.get_py_filename, 'foo', force_win32=win32)
434 nt.assert_raises(IOError, path.get_py_filename, 'foo', force_win32=win32)
440 nt.assert_raises(IOError, path.get_py_filename, 'foo.py', force_win32=win32)
435 nt.assert_raises(IOError, path.get_py_filename, 'foo.py', force_win32=win32)
441 true_fn = 'foo with spaces.py'
436 true_fn = 'foo with spaces.py'
442 with make_tempfile(true_fn):
437 with make_tempfile(true_fn):
443 nt.assert_equals(path.get_py_filename('foo with spaces', force_win32=win32), true_fn)
438 nt.assert_equals(path.get_py_filename('foo with spaces', force_win32=win32), true_fn)
444 nt.assert_equals(path.get_py_filename('foo with spaces.py', force_win32=win32), true_fn)
439 nt.assert_equals(path.get_py_filename('foo with spaces.py', force_win32=win32), true_fn)
445 if win32:
440 if win32:
446 nt.assert_equals(path.get_py_filename('"foo with spaces.py"', force_win32=True), true_fn)
441 nt.assert_equals(path.get_py_filename('"foo with spaces.py"', force_win32=True), true_fn)
447 nt.assert_equals(path.get_py_filename("'foo with spaces.py'", force_win32=True), true_fn)
442 nt.assert_equals(path.get_py_filename("'foo with spaces.py'", force_win32=True), true_fn)
448 else:
443 else:
449 nt.assert_raises(IOError, path.get_py_filename, '"foo with spaces.py"', force_win32=False)
444 nt.assert_raises(IOError, path.get_py_filename, '"foo with spaces.py"', force_win32=False)
450 nt.assert_raises(IOError, path.get_py_filename, "'foo with spaces.py'", force_win32=False)
445 nt.assert_raises(IOError, path.get_py_filename, "'foo with spaces.py'", force_win32=False)
General Comments 0
You need to be logged in to leave comments. Login now