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