##// END OF EJS Templates
Backport PR #4019: Test skipping without unicode paths...
MinRK -
Show More
@@ -1,79 +1,120 b''
1 1 # -*- coding: utf-8 -*-
2 2 """Tests for completerlib.
3 3
4 4 """
5 5 from __future__ import absolute_import
6 6
7 7 #-----------------------------------------------------------------------------
8 8 # Imports
9 9 #-----------------------------------------------------------------------------
10 10
11 11 import os
12 12 import shutil
13 13 import sys
14 14 import tempfile
15 15 import unittest
16 16 from os.path import join
17 17
18 18 from IPython.core.completerlib import magic_run_completer, module_completion
19 19 from IPython.utils.tempdir import TemporaryDirectory
20 from IPython.testing.decorators import onlyif_unicode_paths
20 21
21 22
22 23 class MockEvent(object):
23 24 def __init__(self, line):
24 25 self.line = line
25 26
26 27 #-----------------------------------------------------------------------------
27 28 # Test functions begin
28 29 #-----------------------------------------------------------------------------
29 30 class Test_magic_run_completer(unittest.TestCase):
30 31 def setUp(self):
31 32 self.BASETESTDIR = tempfile.mkdtemp()
32 for fil in [u"aaΓΈ.py", u"a.py", u"b.py"]:
33 for fil in [u"aao.py", u"a.py", u"b.py"]:
33 34 with open(join(self.BASETESTDIR, fil), "w") as sfile:
34 35 sfile.write("pass\n")
35 36 self.oldpath = os.getcwdu()
36 37 os.chdir(self.BASETESTDIR)
37 38
38 39 def tearDown(self):
39 40 os.chdir(self.oldpath)
40 41 shutil.rmtree(self.BASETESTDIR)
41 42
42 43 def test_1(self):
43 44 """Test magic_run_completer, should match two alterntives
44 45 """
45 46 event = MockEvent(u"%run a")
46 47 mockself = None
47 48 match = set(magic_run_completer(mockself, event))
48 self.assertEqual(match, set([u"a.py", u"aaΓΈ.py"]))
49 self.assertEqual(match, set([u"a.py", u"aao.py"]))
49 50
50 51 def test_2(self):
51 52 """Test magic_run_completer, should match one alterntive
52 53 """
53 54 event = MockEvent(u"%run aa")
54 55 mockself = None
55 56 match = set(magic_run_completer(mockself, event))
56 self.assertEqual(match, set([u"aaΓΈ.py"]))
57 self.assertEqual(match, set([u"aao.py"]))
57 58
58 59 def test_3(self):
59 60 """Test magic_run_completer with unterminated " """
60 61 event = MockEvent(u'%run "a')
61 62 mockself = None
62 63 match = set(magic_run_completer(mockself, event))
63 self.assertEqual(match, set([u"a.py", u"aaΓΈ.py"]))
64 self.assertEqual(match, set([u"a.py", u"aao.py"]))
64 65
65 66 def test_import_invalid_module(self):
66 67 """Testing of issue https://github.com/ipython/ipython/issues/1107"""
67 68 invalid_module_names = set(['foo-bar', 'foo:bar', '10foo'])
68 69 valid_module_names = set(['foobar'])
69 70 with TemporaryDirectory() as tmpdir:
70 71 sys.path.insert( 0, tmpdir )
71 72 for name in invalid_module_names | valid_module_names:
72 73 filename = os.path.join(tmpdir, name + '.py')
73 74 open(filename, 'w').close()
74 75
75 76 s = set( module_completion('import foo') )
76 77 intersection = s.intersection(invalid_module_names)
77 78 self.assertFalse(intersection, intersection)
78 79
79 80 assert valid_module_names.issubset(s), valid_module_names.intersection(s)
81
82 class Test_magic_run_completer_nonascii(unittest.TestCase):
83 @onlyif_unicode_paths
84 def setUp(self):
85 self.BASETESTDIR = tempfile.mkdtemp()
86 for fil in [u"aaΓΈ.py", u"a.py", u"b.py"]:
87 with open(join(self.BASETESTDIR, fil), "w") as sfile:
88 sfile.write("pass\n")
89 self.oldpath = os.getcwdu()
90 os.chdir(self.BASETESTDIR)
91
92 def tearDown(self):
93 os.chdir(self.oldpath)
94 shutil.rmtree(self.BASETESTDIR)
95
96 @onlyif_unicode_paths
97 def test_1(self):
98 """Test magic_run_completer, should match two alterntives
99 """
100 event = MockEvent(u"%run a")
101 mockself = None
102 match = set(magic_run_completer(mockself, event))
103 self.assertEqual(match, set([u"a.py", u"aaΓΈ.py"]))
104
105 @onlyif_unicode_paths
106 def test_2(self):
107 """Test magic_run_completer, should match one alterntive
108 """
109 event = MockEvent(u"%run aa")
110 mockself = None
111 match = set(magic_run_completer(mockself, event))
112 self.assertEqual(match, set([u"aaΓΈ.py"]))
113
114 @onlyif_unicode_paths
115 def test_3(self):
116 """Test magic_run_completer with unterminated " """
117 event = MockEvent(u'%run "a')
118 mockself = None
119 match = set(magic_run_completer(mockself, event))
120 self.assertEqual(match, set([u"a.py", u"aaΓΈ.py"]))
@@ -1,649 +1,652 b''
1 1 # -*- coding: utf-8 -*-
2 2 """Tests for the key interactiveshell module.
3 3
4 4 Historically the main classes in interactiveshell have been under-tested. This
5 5 module should grow as many single-method tests as possible to trap many of the
6 6 recurring bugs we seem to encounter with high-level interaction.
7 7
8 8 Authors
9 9 -------
10 10 * Fernando Perez
11 11 """
12 12 #-----------------------------------------------------------------------------
13 13 # Copyright (C) 2011 The IPython Development Team
14 14 #
15 15 # Distributed under the terms of the BSD License. The full license is in
16 16 # the file COPYING, distributed as part of this software.
17 17 #-----------------------------------------------------------------------------
18 18
19 19 #-----------------------------------------------------------------------------
20 20 # Imports
21 21 #-----------------------------------------------------------------------------
22 22 # stdlib
23 23 import ast
24 24 import os
25 25 import shutil
26 26 import sys
27 27 import tempfile
28 28 import unittest
29 29 from os.path import join
30 30 from StringIO import StringIO
31 31
32 32 # third-party
33 33 import nose.tools as nt
34 34
35 35 # Our own
36 from IPython.testing.decorators import skipif
36 from IPython.testing.decorators import skipif, onlyif_unicode_paths
37 37 from IPython.testing import tools as tt
38 38 from IPython.utils import io
39 39
40 40 #-----------------------------------------------------------------------------
41 41 # Globals
42 42 #-----------------------------------------------------------------------------
43 43 # This is used by every single test, no point repeating it ad nauseam
44 44 ip = get_ipython()
45 45
46 46 #-----------------------------------------------------------------------------
47 47 # Tests
48 48 #-----------------------------------------------------------------------------
49 49
50 50 class InteractiveShellTestCase(unittest.TestCase):
51 51 def test_naked_string_cells(self):
52 52 """Test that cells with only naked strings are fully executed"""
53 53 # First, single-line inputs
54 54 ip.run_cell('"a"\n')
55 55 self.assertEqual(ip.user_ns['_'], 'a')
56 56 # And also multi-line cells
57 57 ip.run_cell('"""a\nb"""\n')
58 58 self.assertEqual(ip.user_ns['_'], 'a\nb')
59 59
60 60 def test_run_empty_cell(self):
61 61 """Just make sure we don't get a horrible error with a blank
62 62 cell of input. Yes, I did overlook that."""
63 63 old_xc = ip.execution_count
64 64 ip.run_cell('')
65 65 self.assertEqual(ip.execution_count, old_xc)
66 66
67 67 def test_run_cell_multiline(self):
68 68 """Multi-block, multi-line cells must execute correctly.
69 69 """
70 70 src = '\n'.join(["x=1",
71 71 "y=2",
72 72 "if 1:",
73 73 " x += 1",
74 74 " y += 1",])
75 75 ip.run_cell(src)
76 76 self.assertEqual(ip.user_ns['x'], 2)
77 77 self.assertEqual(ip.user_ns['y'], 3)
78 78
79 79 def test_multiline_string_cells(self):
80 80 "Code sprinkled with multiline strings should execute (GH-306)"
81 81 ip.run_cell('tmp=0')
82 82 self.assertEqual(ip.user_ns['tmp'], 0)
83 83 ip.run_cell('tmp=1;"""a\nb"""\n')
84 84 self.assertEqual(ip.user_ns['tmp'], 1)
85 85
86 86 def test_dont_cache_with_semicolon(self):
87 87 "Ending a line with semicolon should not cache the returned object (GH-307)"
88 88 oldlen = len(ip.user_ns['Out'])
89 89 a = ip.run_cell('1;', store_history=True)
90 90 newlen = len(ip.user_ns['Out'])
91 91 self.assertEqual(oldlen, newlen)
92 92 #also test the default caching behavior
93 93 ip.run_cell('1', store_history=True)
94 94 newlen = len(ip.user_ns['Out'])
95 95 self.assertEqual(oldlen+1, newlen)
96 96
97 97 def test_In_variable(self):
98 98 "Verify that In variable grows with user input (GH-284)"
99 99 oldlen = len(ip.user_ns['In'])
100 100 ip.run_cell('1;', store_history=True)
101 101 newlen = len(ip.user_ns['In'])
102 102 self.assertEqual(oldlen+1, newlen)
103 103 self.assertEqual(ip.user_ns['In'][-1],'1;')
104 104
105 105 def test_magic_names_in_string(self):
106 106 ip.run_cell('a = """\n%exit\n"""')
107 107 self.assertEqual(ip.user_ns['a'], '\n%exit\n')
108 108
109 109 def test_alias_crash(self):
110 110 """Errors in prefilter can't crash IPython"""
111 111 ip.run_cell('%alias parts echo first %s second %s')
112 112 # capture stderr:
113 113 save_err = io.stderr
114 114 io.stderr = StringIO()
115 115 ip.run_cell('parts 1')
116 116 err = io.stderr.getvalue()
117 117 io.stderr = save_err
118 118 self.assertEqual(err.split(':')[0], 'ERROR')
119 119
120 120 def test_trailing_newline(self):
121 121 """test that running !(command) does not raise a SyntaxError"""
122 122 ip.run_cell('!(true)\n', False)
123 123 ip.run_cell('!(true)\n\n\n', False)
124 124
125 125 def test_gh_597(self):
126 126 """Pretty-printing lists of objects with non-ascii reprs may cause
127 127 problems."""
128 128 class Spam(object):
129 129 def __repr__(self):
130 130 return "\xe9"*50
131 131 import IPython.core.formatters
132 132 f = IPython.core.formatters.PlainTextFormatter()
133 133 f([Spam(),Spam()])
134 134
135 135
136 136 def test_future_flags(self):
137 137 """Check that future flags are used for parsing code (gh-777)"""
138 138 ip.run_cell('from __future__ import print_function')
139 139 try:
140 140 ip.run_cell('prfunc_return_val = print(1,2, sep=" ")')
141 141 assert 'prfunc_return_val' in ip.user_ns
142 142 finally:
143 143 # Reset compiler flags so we don't mess up other tests.
144 144 ip.compile.reset_compiler_flags()
145 145
146 146 def test_future_unicode(self):
147 147 """Check that unicode_literals is imported from __future__ (gh #786)"""
148 148 try:
149 149 ip.run_cell(u'byte_str = "a"')
150 150 assert isinstance(ip.user_ns['byte_str'], str) # string literals are byte strings by default
151 151 ip.run_cell('from __future__ import unicode_literals')
152 152 ip.run_cell(u'unicode_str = "a"')
153 153 assert isinstance(ip.user_ns['unicode_str'], unicode) # strings literals are now unicode
154 154 finally:
155 155 # Reset compiler flags so we don't mess up other tests.
156 156 ip.compile.reset_compiler_flags()
157 157
158 158 def test_can_pickle(self):
159 159 "Can we pickle objects defined interactively (GH-29)"
160 160 ip = get_ipython()
161 161 ip.reset()
162 162 ip.run_cell(("class Mylist(list):\n"
163 163 " def __init__(self,x=[]):\n"
164 164 " list.__init__(self,x)"))
165 165 ip.run_cell("w=Mylist([1,2,3])")
166 166
167 167 from cPickle import dumps
168 168
169 169 # We need to swap in our main module - this is only necessary
170 170 # inside the test framework, because IPython puts the interactive module
171 171 # in place (but the test framework undoes this).
172 172 _main = sys.modules['__main__']
173 173 sys.modules['__main__'] = ip.user_module
174 174 try:
175 175 res = dumps(ip.user_ns["w"])
176 176 finally:
177 177 sys.modules['__main__'] = _main
178 178 self.assertTrue(isinstance(res, bytes))
179 179
180 180 def test_global_ns(self):
181 181 "Code in functions must be able to access variables outside them."
182 182 ip = get_ipython()
183 183 ip.run_cell("a = 10")
184 184 ip.run_cell(("def f(x):\n"
185 185 " return x + a"))
186 186 ip.run_cell("b = f(12)")
187 187 self.assertEqual(ip.user_ns["b"], 22)
188 188
189 189 def test_bad_custom_tb(self):
190 190 """Check that InteractiveShell is protected from bad custom exception handlers"""
191 191 from IPython.utils import io
192 192 save_stderr = io.stderr
193 193 try:
194 194 # capture stderr
195 195 io.stderr = StringIO()
196 196 ip.set_custom_exc((IOError,), lambda etype,value,tb: 1/0)
197 197 self.assertEqual(ip.custom_exceptions, (IOError,))
198 198 ip.run_cell(u'raise IOError("foo")')
199 199 self.assertEqual(ip.custom_exceptions, ())
200 200 self.assertTrue("Custom TB Handler failed" in io.stderr.getvalue())
201 201 finally:
202 202 io.stderr = save_stderr
203 203
204 204 def test_bad_custom_tb_return(self):
205 205 """Check that InteractiveShell is protected from bad return types in custom exception handlers"""
206 206 from IPython.utils import io
207 207 save_stderr = io.stderr
208 208 try:
209 209 # capture stderr
210 210 io.stderr = StringIO()
211 211 ip.set_custom_exc((NameError,),lambda etype,value,tb, tb_offset=None: 1)
212 212 self.assertEqual(ip.custom_exceptions, (NameError,))
213 213 ip.run_cell(u'a=abracadabra')
214 214 self.assertEqual(ip.custom_exceptions, ())
215 215 self.assertTrue("Custom TB Handler failed" in io.stderr.getvalue())
216 216 finally:
217 217 io.stderr = save_stderr
218 218
219 219 def test_drop_by_id(self):
220 220 myvars = {"a":object(), "b":object(), "c": object()}
221 221 ip.push(myvars, interactive=False)
222 222 for name in myvars:
223 223 assert name in ip.user_ns, name
224 224 assert name in ip.user_ns_hidden, name
225 225 ip.user_ns['b'] = 12
226 226 ip.drop_by_id(myvars)
227 227 for name in ["a", "c"]:
228 228 assert name not in ip.user_ns, name
229 229 assert name not in ip.user_ns_hidden, name
230 230 assert ip.user_ns['b'] == 12
231 231 ip.reset()
232 232
233 233 def test_var_expand(self):
234 234 ip.user_ns['f'] = u'Ca\xf1o'
235 235 self.assertEqual(ip.var_expand(u'echo $f'), u'echo Ca\xf1o')
236 236 self.assertEqual(ip.var_expand(u'echo {f}'), u'echo Ca\xf1o')
237 237 self.assertEqual(ip.var_expand(u'echo {f[:-1]}'), u'echo Ca\xf1')
238 238 self.assertEqual(ip.var_expand(u'echo {1*2}'), u'echo 2')
239 239
240 240 ip.user_ns['f'] = b'Ca\xc3\xb1o'
241 241 # This should not raise any exception:
242 242 ip.var_expand(u'echo $f')
243 243
244 244 def test_var_expand_local(self):
245 245 """Test local variable expansion in !system and %magic calls"""
246 246 # !system
247 247 ip.run_cell('def test():\n'
248 248 ' lvar = "ttt"\n'
249 249 ' ret = !echo {lvar}\n'
250 250 ' return ret[0]\n')
251 251 res = ip.user_ns['test']()
252 252 nt.assert_in('ttt', res)
253 253
254 254 # %magic
255 255 ip.run_cell('def makemacro():\n'
256 256 ' macroname = "macro_var_expand_locals"\n'
257 257 ' %macro {macroname} codestr\n')
258 258 ip.user_ns['codestr'] = "str(12)"
259 259 ip.run_cell('makemacro()')
260 260 nt.assert_in('macro_var_expand_locals', ip.user_ns)
261 261
262 262 def test_var_expand_self(self):
263 263 """Test variable expansion with the name 'self', which was failing.
264 264
265 265 See https://github.com/ipython/ipython/issues/1878#issuecomment-7698218
266 266 """
267 267 ip.run_cell('class cTest:\n'
268 268 ' classvar="see me"\n'
269 269 ' def test(self):\n'
270 270 ' res = !echo Variable: {self.classvar}\n'
271 271 ' return res[0]\n')
272 272 nt.assert_in('see me', ip.user_ns['cTest']().test())
273 273
274 274 def test_bad_var_expand(self):
275 275 """var_expand on invalid formats shouldn't raise"""
276 276 # SyntaxError
277 277 self.assertEqual(ip.var_expand(u"{'a':5}"), u"{'a':5}")
278 278 # NameError
279 279 self.assertEqual(ip.var_expand(u"{asdf}"), u"{asdf}")
280 280 # ZeroDivisionError
281 281 self.assertEqual(ip.var_expand(u"{1/0}"), u"{1/0}")
282 282
283 283 def test_silent_nopostexec(self):
284 284 """run_cell(silent=True) doesn't invoke post-exec funcs"""
285 285 d = dict(called=False)
286 286 def set_called():
287 287 d['called'] = True
288 288
289 289 ip.register_post_execute(set_called)
290 290 ip.run_cell("1", silent=True)
291 291 self.assertFalse(d['called'])
292 292 # double-check that non-silent exec did what we expected
293 293 # silent to avoid
294 294 ip.run_cell("1")
295 295 self.assertTrue(d['called'])
296 296 # remove post-exec
297 297 ip._post_execute.pop(set_called)
298 298
299 299 def test_silent_noadvance(self):
300 300 """run_cell(silent=True) doesn't advance execution_count"""
301 301 ec = ip.execution_count
302 302 # silent should force store_history=False
303 303 ip.run_cell("1", store_history=True, silent=True)
304 304
305 305 self.assertEqual(ec, ip.execution_count)
306 306 # double-check that non-silent exec did what we expected
307 307 # silent to avoid
308 308 ip.run_cell("1", store_history=True)
309 309 self.assertEqual(ec+1, ip.execution_count)
310 310
311 311 def test_silent_nodisplayhook(self):
312 312 """run_cell(silent=True) doesn't trigger displayhook"""
313 313 d = dict(called=False)
314 314
315 315 trap = ip.display_trap
316 316 save_hook = trap.hook
317 317
318 318 def failing_hook(*args, **kwargs):
319 319 d['called'] = True
320 320
321 321 try:
322 322 trap.hook = failing_hook
323 323 ip.run_cell("1", silent=True)
324 324 self.assertFalse(d['called'])
325 325 # double-check that non-silent exec did what we expected
326 326 # silent to avoid
327 327 ip.run_cell("1")
328 328 self.assertTrue(d['called'])
329 329 finally:
330 330 trap.hook = save_hook
331 331
332 332 @skipif(sys.version_info[0] >= 3, "softspace removed in py3")
333 333 def test_print_softspace(self):
334 334 """Verify that softspace is handled correctly when executing multiple
335 335 statements.
336 336
337 337 In [1]: print 1; print 2
338 338 1
339 339 2
340 340
341 341 In [2]: print 1,; print 2
342 342 1 2
343 343 """
344 344
345 345 def test_ofind_line_magic(self):
346 346 from IPython.core.magic import register_line_magic
347 347
348 348 @register_line_magic
349 349 def lmagic(line):
350 350 "A line magic"
351 351
352 352 # Get info on line magic
353 353 lfind = ip._ofind('lmagic')
354 354 info = dict(found=True, isalias=False, ismagic=True,
355 355 namespace = 'IPython internal', obj= lmagic.__wrapped__,
356 356 parent = None)
357 357 nt.assert_equal(lfind, info)
358 358
359 359 def test_ofind_cell_magic(self):
360 360 from IPython.core.magic import register_cell_magic
361 361
362 362 @register_cell_magic
363 363 def cmagic(line, cell):
364 364 "A cell magic"
365 365
366 366 # Get info on cell magic
367 367 find = ip._ofind('cmagic')
368 368 info = dict(found=True, isalias=False, ismagic=True,
369 369 namespace = 'IPython internal', obj= cmagic.__wrapped__,
370 370 parent = None)
371 371 nt.assert_equal(find, info)
372 372
373 373 def test_custom_exception(self):
374 374 called = []
375 375 def my_handler(shell, etype, value, tb, tb_offset=None):
376 376 called.append(etype)
377 377 shell.showtraceback((etype, value, tb), tb_offset=tb_offset)
378 378
379 379 ip.set_custom_exc((ValueError,), my_handler)
380 380 try:
381 381 ip.run_cell("raise ValueError('test')")
382 382 # Check that this was called, and only once.
383 383 self.assertEqual(called, [ValueError])
384 384 finally:
385 385 # Reset the custom exception hook
386 386 ip.set_custom_exc((), None)
387 387
388 388 @skipif(sys.version_info[0] >= 3, "no differences with __future__ in py3")
389 389 def test_future_environment(self):
390 390 "Can we run code with & without the shell's __future__ imports?"
391 391 ip.run_cell("from __future__ import division")
392 392 ip.run_cell("a = 1/2", shell_futures=True)
393 393 self.assertEqual(ip.user_ns['a'], 0.5)
394 394 ip.run_cell("b = 1/2", shell_futures=False)
395 395 self.assertEqual(ip.user_ns['b'], 0)
396 396
397 397 ip.compile.reset_compiler_flags()
398 398 # This shouldn't leak to the shell's compiler
399 399 ip.run_cell("from __future__ import division \nc=1/2", shell_futures=False)
400 400 self.assertEqual(ip.user_ns['c'], 0.5)
401 401 ip.run_cell("d = 1/2", shell_futures=True)
402 402 self.assertEqual(ip.user_ns['d'], 0)
403 403
404 404
405 405 class TestSafeExecfileNonAsciiPath(unittest.TestCase):
406 406
407 @onlyif_unicode_paths
407 408 def setUp(self):
408 409 self.BASETESTDIR = tempfile.mkdtemp()
409 410 self.TESTDIR = join(self.BASETESTDIR, u"Γ₯Àâ")
410 411 os.mkdir(self.TESTDIR)
411 412 with open(join(self.TESTDIR, u"Γ₯Àâtestscript.py"), "w") as sfile:
412 413 sfile.write("pass\n")
413 414 self.oldpath = os.getcwdu()
414 415 os.chdir(self.TESTDIR)
415 416 self.fname = u"Γ₯Àâtestscript.py"
416 417
417 418 def tearDown(self):
418 419 os.chdir(self.oldpath)
419 420 shutil.rmtree(self.BASETESTDIR)
420 421
422 @onlyif_unicode_paths
421 423 def test_1(self):
422 424 """Test safe_execfile with non-ascii path
423 425 """
424 426 ip.safe_execfile(self.fname, {}, raise_exceptions=True)
425 427
426 428
427 429 class TestSystemRaw(unittest.TestCase):
430 @onlyif_unicode_paths
428 431 def test_1(self):
429 432 """Test system_raw with non-ascii cmd
430 433 """
431 434 cmd = ur'''python -c "'Γ₯Àâ'" '''
432 435 ip.system_raw(cmd)
433 436
434 437 def test_exit_code(self):
435 438 """Test that the exit code is parsed correctly."""
436 439 ip.system_raw('exit 1')
437 440 self.assertEqual(ip.user_ns['_exit_code'], 1)
438 441
439 442 class TestModules(unittest.TestCase, tt.TempFileMixin):
440 443 def test_extraneous_loads(self):
441 444 """Test we're not loading modules on startup that we shouldn't.
442 445 """
443 446 self.mktmp("import sys\n"
444 447 "print('numpy' in sys.modules)\n"
445 448 "print('IPython.parallel' in sys.modules)\n"
446 449 "print('IPython.kernel.zmq' in sys.modules)\n"
447 450 )
448 451 out = "False\nFalse\nFalse\n"
449 452 tt.ipexec_validate(self.fname, out)
450 453
451 454 class Negator(ast.NodeTransformer):
452 455 """Negates all number literals in an AST."""
453 456 def visit_Num(self, node):
454 457 node.n = -node.n
455 458 return node
456 459
457 460 class TestAstTransform(unittest.TestCase):
458 461 def setUp(self):
459 462 self.negator = Negator()
460 463 ip.ast_transformers.append(self.negator)
461 464
462 465 def tearDown(self):
463 466 ip.ast_transformers.remove(self.negator)
464 467
465 468 def test_run_cell(self):
466 469 with tt.AssertPrints('-34'):
467 470 ip.run_cell('print (12 + 22)')
468 471
469 472 # A named reference to a number shouldn't be transformed.
470 473 ip.user_ns['n'] = 55
471 474 with tt.AssertNotPrints('-55'):
472 475 ip.run_cell('print (n)')
473 476
474 477 def test_timeit(self):
475 478 called = set()
476 479 def f(x):
477 480 called.add(x)
478 481 ip.push({'f':f})
479 482
480 483 with tt.AssertPrints("best of "):
481 484 ip.run_line_magic("timeit", "-n1 f(1)")
482 485 self.assertEqual(called, set([-1]))
483 486 called.clear()
484 487
485 488 with tt.AssertPrints("best of "):
486 489 ip.run_cell_magic("timeit", "-n1 f(2)", "f(3)")
487 490 self.assertEqual(called, set([-2, -3]))
488 491
489 492 def test_time(self):
490 493 called = []
491 494 def f(x):
492 495 called.append(x)
493 496 ip.push({'f':f})
494 497
495 498 # Test with an expression
496 499 with tt.AssertPrints("Wall time: "):
497 500 ip.run_line_magic("time", "f(5+9)")
498 501 self.assertEqual(called, [-14])
499 502 called[:] = []
500 503
501 504 # Test with a statement (different code path)
502 505 with tt.AssertPrints("Wall time: "):
503 506 ip.run_line_magic("time", "a = f(-3 + -2)")
504 507 self.assertEqual(called, [5])
505 508
506 509 def test_macro(self):
507 510 ip.push({'a':10})
508 511 # The AST transformation makes this do a+=-1
509 512 ip.define_macro("amacro", "a+=1\nprint(a)")
510 513
511 514 with tt.AssertPrints("9"):
512 515 ip.run_cell("amacro")
513 516 with tt.AssertPrints("8"):
514 517 ip.run_cell("amacro")
515 518
516 519 class IntegerWrapper(ast.NodeTransformer):
517 520 """Wraps all integers in a call to Integer()"""
518 521 def visit_Num(self, node):
519 522 if isinstance(node.n, int):
520 523 return ast.Call(func=ast.Name(id='Integer', ctx=ast.Load()),
521 524 args=[node], keywords=[])
522 525 return node
523 526
524 527 class TestAstTransform2(unittest.TestCase):
525 528 def setUp(self):
526 529 self.intwrapper = IntegerWrapper()
527 530 ip.ast_transformers.append(self.intwrapper)
528 531
529 532 self.calls = []
530 533 def Integer(*args):
531 534 self.calls.append(args)
532 535 return args
533 536 ip.push({"Integer": Integer})
534 537
535 538 def tearDown(self):
536 539 ip.ast_transformers.remove(self.intwrapper)
537 540 del ip.user_ns['Integer']
538 541
539 542 def test_run_cell(self):
540 543 ip.run_cell("n = 2")
541 544 self.assertEqual(self.calls, [(2,)])
542 545
543 546 # This shouldn't throw an error
544 547 ip.run_cell("o = 2.0")
545 548 self.assertEqual(ip.user_ns['o'], 2.0)
546 549
547 550 def test_timeit(self):
548 551 called = set()
549 552 def f(x):
550 553 called.add(x)
551 554 ip.push({'f':f})
552 555
553 556 with tt.AssertPrints("best of "):
554 557 ip.run_line_magic("timeit", "-n1 f(1)")
555 558 self.assertEqual(called, set([(1,)]))
556 559 called.clear()
557 560
558 561 with tt.AssertPrints("best of "):
559 562 ip.run_cell_magic("timeit", "-n1 f(2)", "f(3)")
560 563 self.assertEqual(called, set([(2,), (3,)]))
561 564
562 565 class ErrorTransformer(ast.NodeTransformer):
563 566 """Throws an error when it sees a number."""
564 567 def visit_Num(self):
565 568 raise ValueError("test")
566 569
567 570 class TestAstTransformError(unittest.TestCase):
568 571 def test_unregistering(self):
569 572 err_transformer = ErrorTransformer()
570 573 ip.ast_transformers.append(err_transformer)
571 574
572 575 with tt.AssertPrints("unregister", channel='stderr'):
573 576 ip.run_cell("1 + 2")
574 577
575 578 # This should have been removed.
576 579 nt.assert_not_in(err_transformer, ip.ast_transformers)
577 580
578 581 def test__IPYTHON__():
579 582 # This shouldn't raise a NameError, that's all
580 583 __IPYTHON__
581 584
582 585
583 586 class DummyRepr(object):
584 587 def __repr__(self):
585 588 return "DummyRepr"
586 589
587 590 def _repr_html_(self):
588 591 return "<b>dummy</b>"
589 592
590 593 def _repr_javascript_(self):
591 594 return "console.log('hi');", {'key': 'value'}
592 595
593 596
594 597 def test_user_variables():
595 598 # enable all formatters
596 599 ip.display_formatter.active_types = ip.display_formatter.format_types
597 600
598 601 ip.user_ns['dummy'] = d = DummyRepr()
599 602 keys = set(['dummy', 'doesnotexist'])
600 603 r = ip.user_variables(keys)
601 604
602 605 nt.assert_equal(keys, set(r.keys()))
603 606 dummy = r['dummy']
604 607 nt.assert_equal(set(['status', 'data', 'metadata']), set(dummy.keys()))
605 608 nt.assert_equal(dummy['status'], 'ok')
606 609 data = dummy['data']
607 610 metadata = dummy['metadata']
608 611 nt.assert_equal(data.get('text/html'), d._repr_html_())
609 612 js, jsmd = d._repr_javascript_()
610 613 nt.assert_equal(data.get('application/javascript'), js)
611 614 nt.assert_equal(metadata.get('application/javascript'), jsmd)
612 615
613 616 dne = r['doesnotexist']
614 617 nt.assert_equal(dne['status'], 'error')
615 618 nt.assert_equal(dne['ename'], 'KeyError')
616 619
617 620 # back to text only
618 621 ip.display_formatter.active_types = ['text/plain']
619 622
620 623 def test_user_expression():
621 624 # enable all formatters
622 625 ip.display_formatter.active_types = ip.display_formatter.format_types
623 626 query = {
624 627 'a' : '1 + 2',
625 628 'b' : '1/0',
626 629 }
627 630 r = ip.user_expressions(query)
628 631 import pprint
629 632 pprint.pprint(r)
630 633 nt.assert_equal(r.keys(), query.keys())
631 634 a = r['a']
632 635 nt.assert_equal(set(['status', 'data', 'metadata']), set(a.keys()))
633 636 nt.assert_equal(a['status'], 'ok')
634 637 data = a['data']
635 638 metadata = a['metadata']
636 639 nt.assert_equal(data.get('text/plain'), '3')
637 640
638 641 b = r['b']
639 642 nt.assert_equal(b['status'], 'error')
640 643 nt.assert_equal(b['ename'], 'ZeroDivisionError')
641 644
642 645 # back to text only
643 646 ip.display_formatter.active_types = ['text/plain']
644 647
645 648
646 649
647 650
648 651
649 652
@@ -1,150 +1,153 b''
1 1 # coding: utf-8
2 2 """Tests for profile-related functions.
3 3
4 4 Currently only the startup-dir functionality is tested, but more tests should
5 5 be added for:
6 6
7 7 * ipython profile create
8 8 * ipython profile list
9 9 * ipython profile create --parallel
10 10 * security dir permissions
11 11
12 12 Authors
13 13 -------
14 14
15 15 * MinRK
16 16
17 17 """
18 18 from __future__ import absolute_import
19 19
20 20 #-----------------------------------------------------------------------------
21 21 # Imports
22 22 #-----------------------------------------------------------------------------
23 23
24 24 import os
25 25 import shutil
26 26 import sys
27 27 import tempfile
28 28
29 29 from unittest import TestCase
30 30
31 31 import nose.tools as nt
32 32
33 33 from IPython.core.profileapp import list_profiles_in, list_bundled_profiles
34 34 from IPython.core.profiledir import ProfileDir
35 35
36 36 from IPython.testing import decorators as dec
37 37 from IPython.testing import tools as tt
38 38 from IPython.utils import py3compat
39 39
40 40
41 41 #-----------------------------------------------------------------------------
42 42 # Globals
43 43 #-----------------------------------------------------------------------------
44 44 TMP_TEST_DIR = tempfile.mkdtemp()
45 45 HOME_TEST_DIR = os.path.join(TMP_TEST_DIR, "home_test_dir")
46 46 IP_TEST_DIR = os.path.join(HOME_TEST_DIR,'.ipython')
47 47
48 48 #
49 49 # Setup/teardown functions/decorators
50 50 #
51 51
52 52 def setup():
53 53 """Setup test environment for the module:
54 54
55 55 - Adds dummy home dir tree
56 56 """
57 57 # Do not mask exceptions here. In particular, catching WindowsError is a
58 58 # problem because that exception is only defined on Windows...
59 59 os.makedirs(IP_TEST_DIR)
60 60
61 61
62 62 def teardown():
63 63 """Teardown test environment for the module:
64 64
65 65 - Remove dummy home dir tree
66 66 """
67 67 # Note: we remove the parent test dir, which is the root of all test
68 68 # subdirs we may have created. Use shutil instead of os.removedirs, so
69 69 # that non-empty directories are all recursively removed.
70 70 shutil.rmtree(TMP_TEST_DIR)
71 71
72 72
73 73 #-----------------------------------------------------------------------------
74 74 # Test functions
75 75 #-----------------------------------------------------------------------------
76 76 def win32_without_pywin32():
77 77 if sys.platform == 'win32':
78 78 try:
79 79 import pywin32
80 80 except ImportError:
81 81 return True
82 82 return False
83 83
84 84
85 85 class ProfileStartupTest(TestCase):
86 86 def setUp(self):
87 87 # create profile dir
88 88 self.pd = ProfileDir.create_profile_dir_by_name(IP_TEST_DIR, 'test')
89 89 self.options = ['--ipython-dir', IP_TEST_DIR, '--profile', 'test']
90 90 self.fname = os.path.join(TMP_TEST_DIR, 'test.py')
91 91
92 92 def tearDown(self):
93 93 # We must remove this profile right away so its presence doesn't
94 94 # confuse other tests.
95 95 shutil.rmtree(self.pd.location)
96 96
97 97 def init(self, startup_file, startup, test):
98 98 # write startup python file
99 99 with open(os.path.join(self.pd.startup_dir, startup_file), 'w') as f:
100 100 f.write(startup)
101 101 # write simple test file, to check that the startup file was run
102 102 with open(self.fname, 'w') as f:
103 103 f.write(py3compat.doctest_refactor_print(test))
104 104
105 105 def validate(self, output):
106 106 tt.ipexec_validate(self.fname, output, '', options=self.options)
107 107
108 108 @dec.skipif(win32_without_pywin32(), "Test requires pywin32 on Windows")
109 109 def test_startup_py(self):
110 110 self.init('00-start.py', 'zzz=123\n',
111 111 py3compat.doctest_refactor_print('print zzz\n'))
112 112 self.validate('123')
113 113
114 114 @dec.skipif(win32_without_pywin32(), "Test requires pywin32 on Windows")
115 115 def test_startup_ipy(self):
116 116 self.init('00-start.ipy', '%profile\n', '')
117 117 self.validate('test')
118 118
119 119
120 120 def test_list_profiles_in():
121 121 # No need to remove these directories and files, as they will get nuked in
122 122 # the module-level teardown.
123 123 td = tempfile.mkdtemp(dir=TMP_TEST_DIR)
124 124 td = py3compat.str_to_unicode(td)
125 for name in ('profile_foo', u'profile_ΓΌnicode', 'profile_hello',
126 'not_a_profile'):
125 for name in ('profile_foo', 'profile_hello', 'not_a_profile'):
127 126 os.mkdir(os.path.join(td, name))
127 if dec.unicode_paths:
128 os.mkdir(os.path.join(td, u'profile_ΓΌnicode'))
129
128 130 with open(os.path.join(td, 'profile_file'), 'w') as f:
129 131 f.write("I am not a profile directory")
130 132 profiles = list_profiles_in(td)
131 133
132 134 # unicode normalization can turn u'ΓΌnicode' into u'u\0308nicode',
133 135 # so only check for *nicode, and that creating a ProfileDir from the
134 136 # name remains valid
135 137 found_unicode = False
136 138 for p in list(profiles):
137 139 if p.endswith('nicode'):
138 140 pd = ProfileDir.find_profile_dir_by_name(td, p)
139 141 profiles.remove(p)
140 142 found_unicode = True
141 143 break
142 nt.assert_true(found_unicode)
144 if dec.unicode_paths:
145 nt.assert_true(found_unicode)
143 146 nt.assert_equal(set(profiles), set(['foo', 'hello']))
144 147
145 148
146 149 def test_list_bundled_profiles():
147 150 # This variable will need to be updated when a new profile gets bundled
148 151 bundled_true = [u'cluster', u'math', u'pysh', u'sympy']
149 152 bundled = sorted(list_bundled_profiles())
150 153 nt.assert_equal(bundled, bundled_true)
@@ -1,109 +1,110 b''
1 1 # -*- coding: utf-8
2 2 """Tests for prompt generation."""
3 3
4 4 import unittest
5 5
6 6 import os
7 7
8 8 from IPython.testing import tools as tt, decorators as dec
9 9 from IPython.core.prompts import PromptManager, LazyEvaluate
10 10 from IPython.testing.globalipapp import get_ipython
11 11 from IPython.utils.tempdir import TemporaryDirectory
12 12
13 13 ip = get_ipython()
14 14
15 15
16 16 class PromptTests(unittest.TestCase):
17 17 def setUp(self):
18 18 self.pm = PromptManager(shell=ip, config=ip.config)
19 19
20 20 def test_multiline_prompt(self):
21 21 self.pm.in_template = "[In]\n>>>"
22 22 self.pm.render('in')
23 23 self.assertEqual(self.pm.width, 3)
24 24 self.assertEqual(self.pm.txtwidth, 3)
25 25
26 26 self.pm.in_template = '[In]\n'
27 27 self.pm.render('in')
28 28 self.assertEqual(self.pm.width, 0)
29 29 self.assertEqual(self.pm.txtwidth, 0)
30 30
31 31 def test_translate_abbreviations(self):
32 32 def do_translate(template):
33 33 self.pm.in_template = template
34 34 return self.pm.templates['in']
35 35
36 36 pairs = [(r'%n>', '{color.number}{count}{color.prompt}>'),
37 37 (r'\T', '{time}'),
38 38 (r'\n', '\n')
39 39 ]
40 40
41 41 tt.check_pairs(do_translate, pairs)
42 42
43 43 def test_user_ns(self):
44 44 self.pm.color_scheme = 'NoColor'
45 45 ip.ex("foo='bar'")
46 46 self.pm.in_template = "In [{foo}]"
47 47 prompt = self.pm.render('in')
48 48 self.assertEqual(prompt, u'In [bar]')
49 49
50 50 def test_builtins(self):
51 51 self.pm.color_scheme = 'NoColor'
52 52 self.pm.in_template = "In [{int}]"
53 53 prompt = self.pm.render('in')
54 54 self.assertEqual(prompt, u"In [%r]" % int)
55 55
56 56 def test_undefined(self):
57 57 self.pm.color_scheme = 'NoColor'
58 58 self.pm.in_template = "In [{foo_dne}]"
59 59 prompt = self.pm.render('in')
60 60 self.assertEqual(prompt, u"In [<ERROR: 'foo_dne' not found>]")
61 61
62 62 def test_render(self):
63 63 self.pm.in_template = r'\#>'
64 64 self.assertEqual(self.pm.render('in',color=False), '%d>' % ip.execution_count)
65 65
66 @dec.onlyif_unicode_paths
66 67 def test_render_unicode_cwd(self):
67 68 save = os.getcwdu()
68 69 with TemporaryDirectory(u'ΓΌnicΓΈdΓ©') as td:
69 70 os.chdir(td)
70 71 self.pm.in_template = r'\w [\#]'
71 72 p = self.pm.render('in', color=False)
72 73 self.assertEqual(p, u"%s [%i]" % (os.getcwdu(), ip.execution_count))
73 74 os.chdir(save)
74 75
75 76 def test_lazy_eval_unicode(self):
76 77 u = u'ΓΌnicΓΈdΓ©'
77 78 lz = LazyEvaluate(lambda : u)
78 79 # str(lz) would fail
79 80 self.assertEqual(unicode(lz), u)
80 81 self.assertEqual(format(lz), u)
81 82
82 83 def test_lazy_eval_nonascii_bytes(self):
83 84 u = u'ΓΌnicΓΈdΓ©'
84 85 b = u.encode('utf8')
85 86 lz = LazyEvaluate(lambda : b)
86 87 # unicode(lz) would fail
87 88 self.assertEqual(str(lz), str(b))
88 89 self.assertEqual(format(lz), str(b))
89 90
90 91 def test_lazy_eval_float(self):
91 92 f = 0.503
92 93 lz = LazyEvaluate(lambda : f)
93 94
94 95 self.assertEqual(str(lz), str(f))
95 96 self.assertEqual(unicode(lz), unicode(f))
96 97 self.assertEqual(format(lz), str(f))
97 98 self.assertEqual(format(lz, '.1'), '0.5')
98 99
99 100 @dec.skip_win32
100 101 def test_cwd_x(self):
101 102 self.pm.in_template = r"\X0"
102 103 save = os.getcwdu()
103 104 os.chdir(os.path.expanduser('~'))
104 105 p = self.pm.render('in', color=False)
105 106 try:
106 107 self.assertEqual(p, '~')
107 108 finally:
108 109 os.chdir(save)
109 110
@@ -1,101 +1,115 b''
1 1 # encoding: utf-8
2 2 """Tests for IPython.core.ultratb
3 3 """
4 4 import io
5 5 import os.path
6 6 import unittest
7 7
8 8 from IPython.testing import tools as tt
9 from IPython.testing.decorators import onlyif_unicode_paths
9 10 from IPython.utils.syspathcontext import prepended_to_syspath
10 11 from IPython.utils.tempdir import TemporaryDirectory
11 12
12 13 ip = get_ipython()
13 14
14 15 file_1 = """1
15 16 2
16 17 3
17 18 def f():
18 19 1/0
19 20 """
20 21
21 22 file_2 = """def f():
22 23 1/0
23 24 """
24 25
25 26 class ChangedPyFileTest(unittest.TestCase):
26 27 def test_changing_py_file(self):
27 28 """Traceback produced if the line where the error occurred is missing?
28 29
29 30 https://github.com/ipython/ipython/issues/1456
30 31 """
31 32 with TemporaryDirectory() as td:
32 33 fname = os.path.join(td, "foo.py")
33 34 with open(fname, "w") as f:
34 35 f.write(file_1)
35 36
36 37 with prepended_to_syspath(td):
37 38 ip.run_cell("import foo")
38 39
39 40 with tt.AssertPrints("ZeroDivisionError"):
40 41 ip.run_cell("foo.f()")
41 42
42 43 # Make the file shorter, so the line of the error is missing.
43 44 with open(fname, "w") as f:
44 45 f.write(file_2)
45 46
46 47 # For some reason, this was failing on the *second* call after
47 48 # changing the file, so we call f() twice.
48 49 with tt.AssertNotPrints("Internal Python error", channel='stderr'):
49 50 with tt.AssertPrints("ZeroDivisionError"):
50 51 ip.run_cell("foo.f()")
51 52 with tt.AssertPrints("ZeroDivisionError"):
52 53 ip.run_cell("foo.f()")
53 54
54 55 iso_8859_5_file = u'''# coding: iso-8859-5
55 56
56 57 def fail():
57 58 """Π΄Π±Π˜Π–"""
58 59 1/0 # Π΄Π±Π˜Π–
59 60 '''
60 61
61 62 class NonAsciiTest(unittest.TestCase):
62 def test_iso8859_5(self):
63 @onlyif_unicode_paths
64 def test_nonascii_path(self):
63 65 # Non-ascii directory name as well.
64 66 with TemporaryDirectory(suffix=u'Γ©') as td:
67 fname = os.path.join(td, u"fooΓ©.py")
68 with open(fname, "w") as f:
69 f.write(file_1)
70
71 with prepended_to_syspath(td):
72 ip.run_cell("import foo")
73
74 with tt.AssertPrints("ZeroDivisionError"):
75 ip.run_cell("foo.f()")
76
77 def test_iso8859_5(self):
78 with TemporaryDirectory() as td:
65 79 fname = os.path.join(td, 'dfghjkl.py')
66 80
67 81 with io.open(fname, 'w', encoding='iso-8859-5') as f:
68 82 f.write(iso_8859_5_file)
69 83
70 84 with prepended_to_syspath(td):
71 85 ip.run_cell("from dfghjkl import fail")
72 86
73 87 with tt.AssertPrints("ZeroDivisionError"):
74 88 with tt.AssertPrints(u'Π΄Π±Π˜Π–', suppress=False):
75 89 ip.run_cell('fail()')
76 90
77 91 indentationerror_file = """if True:
78 92 zoon()
79 93 """
80 94
81 95 class IndentationErrorTest(unittest.TestCase):
82 96 def test_indentationerror_shows_line(self):
83 97 # See issue gh-2398
84 98 with tt.AssertPrints("IndentationError"):
85 99 with tt.AssertPrints("zoon()", suppress=False):
86 100 ip.run_cell(indentationerror_file)
87 101
88 102 with TemporaryDirectory() as td:
89 103 fname = os.path.join(td, "foo.py")
90 104 with open(fname, "w") as f:
91 105 f.write(indentationerror_file)
92 106
93 107 with tt.AssertPrints("IndentationError"):
94 108 with tt.AssertPrints("zoon()", suppress=False):
95 109 ip.magic('run %s' % fname)
96 110
97 111 class SyntaxErrorTest(unittest.TestCase):
98 112 def test_syntaxerror_without_lineno(self):
99 113 with tt.AssertNotPrints("TypeError"):
100 114 with tt.AssertPrints("line unknown"):
101 115 ip.run_cell("raise SyntaxError()")
@@ -1,635 +1,637 b''
1 1 # encoding: utf-8
2 2 """Tests for IPython.utils.path.py"""
3 3
4 4 #-----------------------------------------------------------------------------
5 5 # Copyright (C) 2008-2011 The IPython Development Team
6 6 #
7 7 # Distributed under the terms of the BSD License. The full license is in
8 8 # the file COPYING, distributed as part of this software.
9 9 #-----------------------------------------------------------------------------
10 10
11 11 #-----------------------------------------------------------------------------
12 12 # Imports
13 13 #-----------------------------------------------------------------------------
14 14
15 15 from __future__ import with_statement
16 16
17 17 import os
18 18 import shutil
19 19 import sys
20 20 import tempfile
21 21 from contextlib import contextmanager
22 22
23 23 from os.path import join, abspath, split
24 24
25 25 import nose.tools as nt
26 26
27 27 from nose import with_setup
28 28
29 29 import IPython
30 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 onlyif_unicode_paths,)
32 33 from IPython.testing.tools import make_tempfile, AssertPrints
33 34 from IPython.utils import path
34 35 from IPython.utils import py3compat
35 36 from IPython.utils.tempdir import TemporaryDirectory
36 37
37 38 # Platform-dependent imports
38 39 try:
39 40 import _winreg as wreg
40 41 except ImportError:
41 42 #Fake _winreg module on none windows platforms
42 43 import types
43 44 wr_name = "winreg" if py3compat.PY3 else "_winreg"
44 45 sys.modules[wr_name] = types.ModuleType(wr_name)
45 46 import _winreg as wreg
46 47 #Add entries that needs to be stubbed by the testing code
47 48 (wreg.OpenKey, wreg.QueryValueEx,) = (None, None)
48 49
49 50 try:
50 51 reload
51 52 except NameError: # Python 3
52 53 from imp import reload
53 54
54 55 #-----------------------------------------------------------------------------
55 56 # Globals
56 57 #-----------------------------------------------------------------------------
57 58 env = os.environ
58 59 TEST_FILE_PATH = split(abspath(__file__))[0]
59 60 TMP_TEST_DIR = tempfile.mkdtemp()
60 61 HOME_TEST_DIR = join(TMP_TEST_DIR, "home_test_dir")
61 62 XDG_TEST_DIR = join(HOME_TEST_DIR, "xdg_test_dir")
62 63 XDG_CACHE_DIR = join(HOME_TEST_DIR, "xdg_cache_dir")
63 64 IP_TEST_DIR = join(HOME_TEST_DIR,'.ipython')
64 65 #
65 66 # Setup/teardown functions/decorators
66 67 #
67 68
68 69 def setup():
69 70 """Setup testenvironment for the module:
70 71
71 72 - Adds dummy home dir tree
72 73 """
73 74 # Do not mask exceptions here. In particular, catching WindowsError is a
74 75 # problem because that exception is only defined on Windows...
75 76 os.makedirs(IP_TEST_DIR)
76 77 os.makedirs(os.path.join(XDG_TEST_DIR, 'ipython'))
77 78 os.makedirs(os.path.join(XDG_CACHE_DIR, 'ipython'))
78 79
79 80
80 81 def teardown():
81 82 """Teardown testenvironment for the module:
82 83
83 84 - Remove dummy home dir tree
84 85 """
85 86 # Note: we remove the parent test dir, which is the root of all test
86 87 # subdirs we may have created. Use shutil instead of os.removedirs, so
87 88 # that non-empty directories are all recursively removed.
88 89 shutil.rmtree(TMP_TEST_DIR)
89 90
90 91
91 92 def setup_environment():
92 93 """Setup testenvironment for some functions that are tested
93 94 in this module. In particular this functions stores attributes
94 95 and other things that we need to stub in some test functions.
95 96 This needs to be done on a function level and not module level because
96 97 each testfunction needs a pristine environment.
97 98 """
98 99 global oldstuff, platformstuff
99 100 oldstuff = (env.copy(), os.name, sys.platform, path.get_home_dir, IPython.__file__, os.getcwd())
100 101
101 102 if os.name == 'nt':
102 103 platformstuff = (wreg.OpenKey, wreg.QueryValueEx,)
103 104
104 105
105 106 def teardown_environment():
106 107 """Restore things that were remembered by the setup_environment function
107 108 """
108 109 (oldenv, os.name, sys.platform, path.get_home_dir, IPython.__file__, old_wd) = oldstuff
109 110 os.chdir(old_wd)
110 111 reload(path)
111 112
112 113 for key in env.keys():
113 114 if key not in oldenv:
114 115 del env[key]
115 116 env.update(oldenv)
116 117 if hasattr(sys, 'frozen'):
117 118 del sys.frozen
118 119 if os.name == 'nt':
119 120 (wreg.OpenKey, wreg.QueryValueEx,) = platformstuff
120 121
121 122 # Build decorator that uses the setup_environment/setup_environment
122 123 with_environment = with_setup(setup_environment, teardown_environment)
123 124
124 125 @skip_if_not_win32
125 126 @with_environment
126 127 def test_get_home_dir_1():
127 128 """Testcase for py2exe logic, un-compressed lib
128 129 """
129 130 unfrozen = path.get_home_dir()
130 131 sys.frozen = True
131 132
132 133 #fake filename for IPython.__init__
133 134 IPython.__file__ = abspath(join(HOME_TEST_DIR, "Lib/IPython/__init__.py"))
134 135
135 136 home_dir = path.get_home_dir()
136 137 nt.assert_equal(home_dir, unfrozen)
137 138
138 139
139 140 @skip_if_not_win32
140 141 @with_environment
141 142 def test_get_home_dir_2():
142 143 """Testcase for py2exe logic, compressed lib
143 144 """
144 145 unfrozen = path.get_home_dir()
145 146 sys.frozen = True
146 147 #fake filename for IPython.__init__
147 148 IPython.__file__ = abspath(join(HOME_TEST_DIR, "Library.zip/IPython/__init__.py")).lower()
148 149
149 150 home_dir = path.get_home_dir(True)
150 151 nt.assert_equal(home_dir, unfrozen)
151 152
152 153
153 154 @with_environment
154 155 def test_get_home_dir_3():
155 156 """get_home_dir() uses $HOME if set"""
156 157 env["HOME"] = HOME_TEST_DIR
157 158 home_dir = path.get_home_dir(True)
158 159 # get_home_dir expands symlinks
159 160 nt.assert_equal(home_dir, os.path.realpath(env["HOME"]))
160 161
161 162
162 163 @with_environment
163 164 def test_get_home_dir_4():
164 165 """get_home_dir() still works if $HOME is not set"""
165 166
166 167 if 'HOME' in env: del env['HOME']
167 168 # this should still succeed, but we don't care what the answer is
168 169 home = path.get_home_dir(False)
169 170
170 171 @with_environment
171 172 def test_get_home_dir_5():
172 173 """raise HomeDirError if $HOME is specified, but not a writable dir"""
173 174 env['HOME'] = abspath(HOME_TEST_DIR+'garbage')
174 175 # set os.name = posix, to prevent My Documents fallback on Windows
175 176 os.name = 'posix'
176 177 nt.assert_raises(path.HomeDirError, path.get_home_dir, True)
177 178
178 179
179 180 # Should we stub wreg fully so we can run the test on all platforms?
180 181 @skip_if_not_win32
181 182 @with_environment
182 183 def test_get_home_dir_8():
183 184 """Using registry hack for 'My Documents', os=='nt'
184 185
185 186 HOMESHARE, HOMEDRIVE, HOMEPATH, USERPROFILE and others are missing.
186 187 """
187 188 os.name = 'nt'
188 189 # Remove from stub environment all keys that may be set
189 190 for key in ['HOME', 'HOMESHARE', 'HOMEDRIVE', 'HOMEPATH', 'USERPROFILE']:
190 191 env.pop(key, None)
191 192
192 193 #Stub windows registry functions
193 194 def OpenKey(x, y):
194 195 class key:
195 196 def Close(self):
196 197 pass
197 198 return key()
198 199 def QueryValueEx(x, y):
199 200 return [abspath(HOME_TEST_DIR)]
200 201
201 202 wreg.OpenKey = OpenKey
202 203 wreg.QueryValueEx = QueryValueEx
203 204
204 205 home_dir = path.get_home_dir()
205 206 nt.assert_equal(home_dir, abspath(HOME_TEST_DIR))
206 207
207 208
208 209 @with_environment
209 210 def test_get_ipython_dir_1():
210 211 """test_get_ipython_dir_1, Testcase to see if we can call get_ipython_dir without Exceptions."""
211 212 env_ipdir = os.path.join("someplace", ".ipython")
212 213 path._writable_dir = lambda path: True
213 214 env['IPYTHONDIR'] = env_ipdir
214 215 ipdir = path.get_ipython_dir()
215 216 nt.assert_equal(ipdir, env_ipdir)
216 217
217 218
218 219 @with_environment
219 220 def test_get_ipython_dir_2():
220 221 """test_get_ipython_dir_2, Testcase to see if we can call get_ipython_dir without Exceptions."""
221 222 path.get_home_dir = lambda : "someplace"
222 223 path.get_xdg_dir = lambda : None
223 224 path._writable_dir = lambda path: True
224 225 os.name = "posix"
225 226 env.pop('IPYTHON_DIR', None)
226 227 env.pop('IPYTHONDIR', None)
227 228 env.pop('XDG_CONFIG_HOME', None)
228 229 ipdir = path.get_ipython_dir()
229 230 nt.assert_equal(ipdir, os.path.join("someplace", ".ipython"))
230 231
231 232 @with_environment
232 233 def test_get_ipython_dir_3():
233 234 """test_get_ipython_dir_3, use XDG if defined, and .ipython doesn't exist."""
234 235 path.get_home_dir = lambda : "someplace"
235 236 path._writable_dir = lambda path: True
236 237 os.name = "posix"
237 238 env.pop('IPYTHON_DIR', None)
238 239 env.pop('IPYTHONDIR', None)
239 240 env['XDG_CONFIG_HOME'] = XDG_TEST_DIR
240 241 ipdir = path.get_ipython_dir()
241 242 if sys.platform == "darwin":
242 243 expected = os.path.join("someplace", ".ipython")
243 244 else:
244 245 expected = os.path.join(XDG_TEST_DIR, "ipython")
245 246 nt.assert_equal(ipdir, expected)
246 247
247 248 @with_environment
248 249 def test_get_ipython_dir_4():
249 250 """test_get_ipython_dir_4, use XDG if both exist."""
250 251 path.get_home_dir = lambda : HOME_TEST_DIR
251 252 os.name = "posix"
252 253 env.pop('IPYTHON_DIR', None)
253 254 env.pop('IPYTHONDIR', None)
254 255 env['XDG_CONFIG_HOME'] = XDG_TEST_DIR
255 256 ipdir = path.get_ipython_dir()
256 257 if sys.platform == "darwin":
257 258 expected = os.path.join(HOME_TEST_DIR, ".ipython")
258 259 else:
259 260 expected = os.path.join(XDG_TEST_DIR, "ipython")
260 261 nt.assert_equal(ipdir, expected)
261 262
262 263 @with_environment
263 264 def test_get_ipython_dir_5():
264 265 """test_get_ipython_dir_5, use .ipython if exists and XDG defined, but doesn't exist."""
265 266 path.get_home_dir = lambda : HOME_TEST_DIR
266 267 os.name = "posix"
267 268 env.pop('IPYTHON_DIR', None)
268 269 env.pop('IPYTHONDIR', None)
269 270 env['XDG_CONFIG_HOME'] = XDG_TEST_DIR
270 271 os.rmdir(os.path.join(XDG_TEST_DIR, 'ipython'))
271 272 ipdir = path.get_ipython_dir()
272 273 nt.assert_equal(ipdir, IP_TEST_DIR)
273 274
274 275 @with_environment
275 276 def test_get_ipython_dir_6():
276 277 """test_get_ipython_dir_6, use XDG if defined and neither exist."""
277 278 xdg = os.path.join(HOME_TEST_DIR, 'somexdg')
278 279 os.mkdir(xdg)
279 280 shutil.rmtree(os.path.join(HOME_TEST_DIR, '.ipython'))
280 281 path.get_home_dir = lambda : HOME_TEST_DIR
281 282 path.get_xdg_dir = lambda : xdg
282 283 os.name = "posix"
283 284 env.pop('IPYTHON_DIR', None)
284 285 env.pop('IPYTHONDIR', None)
285 286 env.pop('XDG_CONFIG_HOME', None)
286 287 xdg_ipdir = os.path.join(xdg, "ipython")
287 288 ipdir = path.get_ipython_dir()
288 289 nt.assert_equal(ipdir, xdg_ipdir)
289 290
290 291 @with_environment
291 292 def test_get_ipython_dir_7():
292 293 """test_get_ipython_dir_7, test home directory expansion on IPYTHONDIR"""
293 294 path._writable_dir = lambda path: True
294 295 home_dir = os.path.normpath(os.path.expanduser('~'))
295 296 env['IPYTHONDIR'] = os.path.join('~', 'somewhere')
296 297 ipdir = path.get_ipython_dir()
297 298 nt.assert_equal(ipdir, os.path.join(home_dir, 'somewhere'))
298 299
299 300 @skip_win32
300 301 @with_environment
301 302 def test_get_ipython_dir_8():
302 303 """test_get_ipython_dir_8, test / home directory"""
303 304 old = path._writable_dir, path.get_xdg_dir
304 305 try:
305 306 path._writable_dir = lambda path: bool(path)
306 307 path.get_xdg_dir = lambda: None
307 308 env.pop('IPYTHON_DIR', None)
308 309 env.pop('IPYTHONDIR', None)
309 310 env['HOME'] = '/'
310 311 nt.assert_equal(path.get_ipython_dir(), '/.ipython')
311 312 finally:
312 313 path._writable_dir, path.get_xdg_dir = old
313 314
314 315 @with_environment
315 316 def test_get_xdg_dir_0():
316 317 """test_get_xdg_dir_0, check xdg_dir"""
317 318 reload(path)
318 319 path._writable_dir = lambda path: True
319 320 path.get_home_dir = lambda : 'somewhere'
320 321 os.name = "posix"
321 322 sys.platform = "linux2"
322 323 env.pop('IPYTHON_DIR', None)
323 324 env.pop('IPYTHONDIR', None)
324 325 env.pop('XDG_CONFIG_HOME', None)
325 326
326 327 nt.assert_equal(path.get_xdg_dir(), os.path.join('somewhere', '.config'))
327 328
328 329
329 330 @with_environment
330 331 def test_get_xdg_dir_1():
331 332 """test_get_xdg_dir_1, check nonexistant xdg_dir"""
332 333 reload(path)
333 334 path.get_home_dir = lambda : HOME_TEST_DIR
334 335 os.name = "posix"
335 336 sys.platform = "linux2"
336 337 env.pop('IPYTHON_DIR', None)
337 338 env.pop('IPYTHONDIR', None)
338 339 env.pop('XDG_CONFIG_HOME', None)
339 340 nt.assert_equal(path.get_xdg_dir(), None)
340 341
341 342 @with_environment
342 343 def test_get_xdg_dir_2():
343 344 """test_get_xdg_dir_2, check xdg_dir default to ~/.config"""
344 345 reload(path)
345 346 path.get_home_dir = lambda : HOME_TEST_DIR
346 347 os.name = "posix"
347 348 sys.platform = "linux2"
348 349 env.pop('IPYTHON_DIR', None)
349 350 env.pop('IPYTHONDIR', None)
350 351 env.pop('XDG_CONFIG_HOME', None)
351 352 cfgdir=os.path.join(path.get_home_dir(), '.config')
352 353 if not os.path.exists(cfgdir):
353 354 os.makedirs(cfgdir)
354 355
355 356 nt.assert_equal(path.get_xdg_dir(), cfgdir)
356 357
357 358 @with_environment
358 359 def test_get_xdg_dir_3():
359 360 """test_get_xdg_dir_3, check xdg_dir not used on OS X"""
360 361 reload(path)
361 362 path.get_home_dir = lambda : HOME_TEST_DIR
362 363 os.name = "posix"
363 364 sys.platform = "darwin"
364 365 env.pop('IPYTHON_DIR', None)
365 366 env.pop('IPYTHONDIR', None)
366 367 env.pop('XDG_CONFIG_HOME', None)
367 368 cfgdir=os.path.join(path.get_home_dir(), '.config')
368 369 if not os.path.exists(cfgdir):
369 370 os.makedirs(cfgdir)
370 371
371 372 nt.assert_equal(path.get_xdg_dir(), None)
372 373
373 374 def test_filefind():
374 375 """Various tests for filefind"""
375 376 f = tempfile.NamedTemporaryFile()
376 377 # print 'fname:',f.name
377 378 alt_dirs = path.get_ipython_dir()
378 379 t = path.filefind(f.name, alt_dirs)
379 380 # print 'found:',t
380 381
381 382 @with_environment
382 383 def test_get_ipython_cache_dir():
383 384 os.environ["HOME"] = HOME_TEST_DIR
384 385 if os.name == 'posix' and sys.platform != 'darwin':
385 386 # test default
386 387 os.makedirs(os.path.join(HOME_TEST_DIR, ".cache"))
387 388 os.environ.pop("XDG_CACHE_HOME", None)
388 389 ipdir = path.get_ipython_cache_dir()
389 390 nt.assert_equal(os.path.join(HOME_TEST_DIR, ".cache", "ipython"),
390 391 ipdir)
391 392 nt.assert_true(os.path.isdir(ipdir))
392 393
393 394 # test env override
394 395 os.environ["XDG_CACHE_HOME"] = XDG_CACHE_DIR
395 396 ipdir = path.get_ipython_cache_dir()
396 397 nt.assert_true(os.path.isdir(ipdir))
397 398 nt.assert_equal(ipdir, os.path.join(XDG_CACHE_DIR, "ipython"))
398 399 else:
399 400 nt.assert_equal(path.get_ipython_cache_dir(),
400 401 path.get_ipython_dir())
401 402
402 403 def test_get_ipython_package_dir():
403 404 ipdir = path.get_ipython_package_dir()
404 405 nt.assert_true(os.path.isdir(ipdir))
405 406
406 407
407 408 def test_get_ipython_module_path():
408 409 ipapp_path = path.get_ipython_module_path('IPython.terminal.ipapp')
409 410 nt.assert_true(os.path.isfile(ipapp_path))
410 411
411 412
412 413 @dec.skip_if_not_win32
413 414 def test_get_long_path_name_win32():
414 415 with TemporaryDirectory() as tmpdir:
415 416
416 417 # Make a long path.
417 418 long_path = os.path.join(tmpdir, u'this is my long path name')
418 419 os.makedirs(long_path)
419 420
420 421 # Test to see if the short path evaluates correctly.
421 422 short_path = os.path.join(tmpdir, u'THISIS~1')
422 423 evaluated_path = path.get_long_path_name(short_path)
423 424 nt.assert_equal(evaluated_path.lower(), long_path.lower())
424 425
425 426
426 427 @dec.skip_win32
427 428 def test_get_long_path_name():
428 429 p = path.get_long_path_name('/usr/local')
429 430 nt.assert_equal(p,'/usr/local')
430 431
431 432 @dec.skip_win32 # can't create not-user-writable dir on win
432 433 @with_environment
433 434 def test_not_writable_ipdir():
434 435 tmpdir = tempfile.mkdtemp()
435 436 os.name = "posix"
436 437 env.pop('IPYTHON_DIR', None)
437 438 env.pop('IPYTHONDIR', None)
438 439 env.pop('XDG_CONFIG_HOME', None)
439 440 env['HOME'] = tmpdir
440 441 ipdir = os.path.join(tmpdir, '.ipython')
441 442 os.mkdir(ipdir)
442 443 os.chmod(ipdir, 600)
443 444 with AssertPrints('is not a writable location', channel='stderr'):
444 445 ipdir = path.get_ipython_dir()
445 446 env.pop('IPYTHON_DIR', None)
446 447
447 448 def test_unquote_filename():
448 449 for win32 in (True, False):
449 450 nt.assert_equal(path.unquote_filename('foo.py', win32=win32), 'foo.py')
450 451 nt.assert_equal(path.unquote_filename('foo bar.py', win32=win32), 'foo bar.py')
451 452 nt.assert_equal(path.unquote_filename('"foo.py"', win32=True), 'foo.py')
452 453 nt.assert_equal(path.unquote_filename('"foo bar.py"', win32=True), 'foo bar.py')
453 454 nt.assert_equal(path.unquote_filename("'foo.py'", win32=True), 'foo.py')
454 455 nt.assert_equal(path.unquote_filename("'foo bar.py'", win32=True), 'foo bar.py')
455 456 nt.assert_equal(path.unquote_filename('"foo.py"', win32=False), '"foo.py"')
456 457 nt.assert_equal(path.unquote_filename('"foo bar.py"', win32=False), '"foo bar.py"')
457 458 nt.assert_equal(path.unquote_filename("'foo.py'", win32=False), "'foo.py'")
458 459 nt.assert_equal(path.unquote_filename("'foo bar.py'", win32=False), "'foo bar.py'")
459 460
460 461 @with_environment
461 462 def test_get_py_filename():
462 463 os.chdir(TMP_TEST_DIR)
463 464 for win32 in (True, False):
464 465 with make_tempfile('foo.py'):
465 466 nt.assert_equal(path.get_py_filename('foo.py', force_win32=win32), 'foo.py')
466 467 nt.assert_equal(path.get_py_filename('foo', force_win32=win32), 'foo.py')
467 468 with make_tempfile('foo'):
468 469 nt.assert_equal(path.get_py_filename('foo', force_win32=win32), 'foo')
469 470 nt.assert_raises(IOError, path.get_py_filename, 'foo.py', force_win32=win32)
470 471 nt.assert_raises(IOError, path.get_py_filename, 'foo', force_win32=win32)
471 472 nt.assert_raises(IOError, path.get_py_filename, 'foo.py', force_win32=win32)
472 473 true_fn = 'foo with spaces.py'
473 474 with make_tempfile(true_fn):
474 475 nt.assert_equal(path.get_py_filename('foo with spaces', force_win32=win32), true_fn)
475 476 nt.assert_equal(path.get_py_filename('foo with spaces.py', force_win32=win32), true_fn)
476 477 if win32:
477 478 nt.assert_equal(path.get_py_filename('"foo with spaces.py"', force_win32=True), true_fn)
478 479 nt.assert_equal(path.get_py_filename("'foo with spaces.py'", force_win32=True), true_fn)
479 480 else:
480 481 nt.assert_raises(IOError, path.get_py_filename, '"foo with spaces.py"', force_win32=False)
481 482 nt.assert_raises(IOError, path.get_py_filename, "'foo with spaces.py'", force_win32=False)
482
483
484 @onlyif_unicode_paths
483 485 def test_unicode_in_filename():
484 486 """When a file doesn't exist, the exception raised should be safe to call
485 487 str() on - i.e. in Python 2 it must only have ASCII characters.
486 488
487 489 https://github.com/ipython/ipython/issues/875
488 490 """
489 491 try:
490 492 # these calls should not throw unicode encode exceptions
491 493 path.get_py_filename(u'fooéè.py', force_win32=False)
492 494 except IOError as ex:
493 495 str(ex)
494 496
495 497
496 498 class TestShellGlob(object):
497 499
498 500 @classmethod
499 501 def setUpClass(cls):
500 502 cls.filenames_start_with_a = map('a{0}'.format, range(3))
501 503 cls.filenames_end_with_b = map('{0}b'.format, range(3))
502 504 cls.filenames = cls.filenames_start_with_a + cls.filenames_end_with_b
503 505 cls.tempdir = TemporaryDirectory()
504 506 td = cls.tempdir.name
505 507
506 508 with cls.in_tempdir():
507 509 # Create empty files
508 510 for fname in cls.filenames:
509 511 open(os.path.join(td, fname), 'w').close()
510 512
511 513 @classmethod
512 514 def tearDownClass(cls):
513 515 cls.tempdir.cleanup()
514 516
515 517 @classmethod
516 518 @contextmanager
517 519 def in_tempdir(cls):
518 520 save = os.getcwdu()
519 521 try:
520 522 os.chdir(cls.tempdir.name)
521 523 yield
522 524 finally:
523 525 os.chdir(save)
524 526
525 527 def check_match(self, patterns, matches):
526 528 with self.in_tempdir():
527 529 # glob returns unordered list. that's why sorted is required.
528 530 nt.assert_equals(sorted(path.shellglob(patterns)),
529 531 sorted(matches))
530 532
531 533 def common_cases(self):
532 534 return [
533 535 (['*'], self.filenames),
534 536 (['a*'], self.filenames_start_with_a),
535 537 (['*c'], ['*c']),
536 538 (['*', 'a*', '*b', '*c'], self.filenames
537 539 + self.filenames_start_with_a
538 540 + self.filenames_end_with_b
539 541 + ['*c']),
540 542 (['a[012]'], self.filenames_start_with_a),
541 543 ]
542 544
543 545 @skip_win32
544 546 def test_match_posix(self):
545 547 for (patterns, matches) in self.common_cases() + [
546 548 ([r'\*'], ['*']),
547 549 ([r'a\*', 'a*'], ['a*'] + self.filenames_start_with_a),
548 550 ([r'a\[012]'], ['a[012]']),
549 551 ]:
550 552 yield (self.check_match, patterns, matches)
551 553
552 554 @skip_if_not_win32
553 555 def test_match_windows(self):
554 556 for (patterns, matches) in self.common_cases() + [
555 557 # In windows, backslash is interpreted as path
556 558 # separator. Therefore, you can't escape glob
557 559 # using it.
558 560 ([r'a\*', 'a*'], [r'a\*'] + self.filenames_start_with_a),
559 561 ([r'a\[012]'], [r'a\[012]']),
560 562 ]:
561 563 yield (self.check_match, patterns, matches)
562 564
563 565
564 566 def test_unescape_glob():
565 567 nt.assert_equals(path.unescape_glob(r'\*\[\!\]\?'), '*[!]?')
566 568 nt.assert_equals(path.unescape_glob(r'\\*'), r'\*')
567 569 nt.assert_equals(path.unescape_glob(r'\\\*'), r'\*')
568 570 nt.assert_equals(path.unescape_glob(r'\\a'), r'\a')
569 571 nt.assert_equals(path.unescape_glob(r'\a'), r'\a')
570 572
571 573
572 574 class TestLinkOrCopy(object):
573 575 def setUp(self):
574 576 self.tempdir = TemporaryDirectory()
575 577 self.src = self.dst("src")
576 578 with open(self.src, "w") as f:
577 579 f.write("Hello, world!")
578 580
579 581 def tearDown(self):
580 582 self.tempdir.cleanup()
581 583
582 584 def dst(self, *args):
583 585 return os.path.join(self.tempdir.name, *args)
584 586
585 587 def assert_inode_not_equal(self, a, b):
586 588 nt.assert_not_equals(os.stat(a).st_ino, os.stat(b).st_ino,
587 589 "%r and %r do reference the same indoes" %(a, b))
588 590
589 591 def assert_inode_equal(self, a, b):
590 592 nt.assert_equals(os.stat(a).st_ino, os.stat(b).st_ino,
591 593 "%r and %r do not reference the same indoes" %(a, b))
592 594
593 595 def assert_content_equal(self, a, b):
594 596 with open(a) as a_f:
595 597 with open(b) as b_f:
596 598 nt.assert_equals(a_f.read(), b_f.read())
597 599
598 600 @skip_win32
599 601 def test_link_successful(self):
600 602 dst = self.dst("target")
601 603 path.link_or_copy(self.src, dst)
602 604 self.assert_inode_equal(self.src, dst)
603 605
604 606 @skip_win32
605 607 def test_link_into_dir(self):
606 608 dst = self.dst("some_dir")
607 609 os.mkdir(dst)
608 610 path.link_or_copy(self.src, dst)
609 611 expected_dst = self.dst("some_dir", os.path.basename(self.src))
610 612 self.assert_inode_equal(self.src, expected_dst)
611 613
612 614 @skip_win32
613 615 def test_target_exists(self):
614 616 dst = self.dst("target")
615 617 open(dst, "w").close()
616 618 path.link_or_copy(self.src, dst)
617 619 self.assert_inode_equal(self.src, dst)
618 620
619 621 @skip_win32
620 622 def test_no_link(self):
621 623 real_link = os.link
622 624 try:
623 625 del os.link
624 626 dst = self.dst("target")
625 627 path.link_or_copy(self.src, dst)
626 628 self.assert_content_equal(self.src, dst)
627 629 self.assert_inode_not_equal(self.src, dst)
628 630 finally:
629 631 os.link = real_link
630 632
631 633 @skip_if_not_win32
632 634 def test_windows(self):
633 635 dst = self.dst("target")
634 636 path.link_or_copy(self.src, dst)
635 637 self.assert_content_equal(self.src, dst)
General Comments 0
You need to be logged in to leave comments. Login now