##// END OF EJS Templates
Assume sqlite3 always available in testing.
Terry Davis -
Show More
@@ -1,588 +1,582 b''
1 # encoding: utf-8
1 # encoding: utf-8
2 """Tests for code execution (%run and related), which is particularly tricky.
2 """Tests for code execution (%run and related), which is particularly tricky.
3
3
4 Because of how %run manages namespaces, and the fact that we are trying here to
4 Because of how %run manages namespaces, and the fact that we are trying here to
5 verify subtle object deletion and reference counting issues, the %run tests
5 verify subtle object deletion and reference counting issues, the %run tests
6 will be kept in this separate file. This makes it easier to aggregate in one
6 will be kept in this separate file. This makes it easier to aggregate in one
7 place the tricks needed to handle it; most other magics are much easier to test
7 place the tricks needed to handle it; most other magics are much easier to test
8 and we do so in a common test_magic file.
8 and we do so in a common test_magic file.
9
9
10 Note that any test using `run -i` should make sure to do a `reset` afterwards,
10 Note that any test using `run -i` should make sure to do a `reset` afterwards,
11 as otherwise it may influence later tests.
11 as otherwise it may influence later tests.
12 """
12 """
13
13
14 # Copyright (c) IPython Development Team.
14 # Copyright (c) IPython Development Team.
15 # Distributed under the terms of the Modified BSD License.
15 # Distributed under the terms of the Modified BSD License.
16
16
17
17
18
18
19 import functools
19 import functools
20 import os
20 import os
21 from os.path import join as pjoin
21 from os.path import join as pjoin
22 import random
22 import random
23 import string
23 import string
24 import sys
24 import sys
25 import textwrap
25 import textwrap
26 import unittest
26 import unittest
27 from unittest.mock import patch
27 from unittest.mock import patch
28
28
29 import nose.tools as nt
29 import nose.tools as nt
30 from nose import SkipTest
30 from nose import SkipTest
31
31
32 from IPython.testing import decorators as dec
32 from IPython.testing import decorators as dec
33 from IPython.testing import tools as tt
33 from IPython.testing import tools as tt
34 from IPython.utils.io import capture_output
34 from IPython.utils.io import capture_output
35 from IPython.utils.tempdir import TemporaryDirectory
35 from IPython.utils.tempdir import TemporaryDirectory
36 from IPython.core import debugger
36 from IPython.core import debugger
37
37
38 def doctest_refbug():
38 def doctest_refbug():
39 """Very nasty problem with references held by multiple runs of a script.
39 """Very nasty problem with references held by multiple runs of a script.
40 See: https://github.com/ipython/ipython/issues/141
40 See: https://github.com/ipython/ipython/issues/141
41
41
42 In [1]: _ip.clear_main_mod_cache()
42 In [1]: _ip.clear_main_mod_cache()
43 # random
43 # random
44
44
45 In [2]: %run refbug
45 In [2]: %run refbug
46
46
47 In [3]: call_f()
47 In [3]: call_f()
48 lowercased: hello
48 lowercased: hello
49
49
50 In [4]: %run refbug
50 In [4]: %run refbug
51
51
52 In [5]: call_f()
52 In [5]: call_f()
53 lowercased: hello
53 lowercased: hello
54 lowercased: hello
54 lowercased: hello
55 """
55 """
56
56
57
57
58 def doctest_run_builtins():
58 def doctest_run_builtins():
59 r"""Check that %run doesn't damage __builtins__.
59 r"""Check that %run doesn't damage __builtins__.
60
60
61 In [1]: import tempfile
61 In [1]: import tempfile
62
62
63 In [2]: bid1 = id(__builtins__)
63 In [2]: bid1 = id(__builtins__)
64
64
65 In [3]: fname = tempfile.mkstemp('.py')[1]
65 In [3]: fname = tempfile.mkstemp('.py')[1]
66
66
67 In [3]: f = open(fname,'w')
67 In [3]: f = open(fname,'w')
68
68
69 In [4]: dummy= f.write('pass\n')
69 In [4]: dummy= f.write('pass\n')
70
70
71 In [5]: f.flush()
71 In [5]: f.flush()
72
72
73 In [6]: t1 = type(__builtins__)
73 In [6]: t1 = type(__builtins__)
74
74
75 In [7]: %run $fname
75 In [7]: %run $fname
76
76
77 In [7]: f.close()
77 In [7]: f.close()
78
78
79 In [8]: bid2 = id(__builtins__)
79 In [8]: bid2 = id(__builtins__)
80
80
81 In [9]: t2 = type(__builtins__)
81 In [9]: t2 = type(__builtins__)
82
82
83 In [10]: t1 == t2
83 In [10]: t1 == t2
84 Out[10]: True
84 Out[10]: True
85
85
86 In [10]: bid1 == bid2
86 In [10]: bid1 == bid2
87 Out[10]: True
87 Out[10]: True
88
88
89 In [12]: try:
89 In [12]: try:
90 ....: os.unlink(fname)
90 ....: os.unlink(fname)
91 ....: except:
91 ....: except:
92 ....: pass
92 ....: pass
93 ....:
93 ....:
94 """
94 """
95
95
96
96
97 def doctest_run_option_parser():
97 def doctest_run_option_parser():
98 r"""Test option parser in %run.
98 r"""Test option parser in %run.
99
99
100 In [1]: %run print_argv.py
100 In [1]: %run print_argv.py
101 []
101 []
102
102
103 In [2]: %run print_argv.py print*.py
103 In [2]: %run print_argv.py print*.py
104 ['print_argv.py']
104 ['print_argv.py']
105
105
106 In [3]: %run -G print_argv.py print*.py
106 In [3]: %run -G print_argv.py print*.py
107 ['print*.py']
107 ['print*.py']
108
108
109 """
109 """
110
110
111
111
112 @dec.skip_win32
112 @dec.skip_win32
113 def doctest_run_option_parser_for_posix():
113 def doctest_run_option_parser_for_posix():
114 r"""Test option parser in %run (Linux/OSX specific).
114 r"""Test option parser in %run (Linux/OSX specific).
115
115
116 You need double quote to escape glob in POSIX systems:
116 You need double quote to escape glob in POSIX systems:
117
117
118 In [1]: %run print_argv.py print\\*.py
118 In [1]: %run print_argv.py print\\*.py
119 ['print*.py']
119 ['print*.py']
120
120
121 You can't use quote to escape glob in POSIX systems:
121 You can't use quote to escape glob in POSIX systems:
122
122
123 In [2]: %run print_argv.py 'print*.py'
123 In [2]: %run print_argv.py 'print*.py'
124 ['print_argv.py']
124 ['print_argv.py']
125
125
126 """
126 """
127
127
128
128
129 @dec.skip_if_not_win32
129 @dec.skip_if_not_win32
130 def doctest_run_option_parser_for_windows():
130 def doctest_run_option_parser_for_windows():
131 r"""Test option parser in %run (Windows specific).
131 r"""Test option parser in %run (Windows specific).
132
132
133 In Windows, you can't escape ``*` `by backslash:
133 In Windows, you can't escape ``*` `by backslash:
134
134
135 In [1]: %run print_argv.py print\\*.py
135 In [1]: %run print_argv.py print\\*.py
136 ['print\\*.py']
136 ['print\\*.py']
137
137
138 You can use quote to escape glob:
138 You can use quote to escape glob:
139
139
140 In [2]: %run print_argv.py 'print*.py'
140 In [2]: %run print_argv.py 'print*.py'
141 ['print*.py']
141 ['print*.py']
142
142
143 """
143 """
144
144
145
145
146 def doctest_reset_del():
146 def doctest_reset_del():
147 """Test that resetting doesn't cause errors in __del__ methods.
147 """Test that resetting doesn't cause errors in __del__ methods.
148
148
149 In [2]: class A(object):
149 In [2]: class A(object):
150 ...: def __del__(self):
150 ...: def __del__(self):
151 ...: print(str("Hi"))
151 ...: print(str("Hi"))
152 ...:
152 ...:
153
153
154 In [3]: a = A()
154 In [3]: a = A()
155
155
156 In [4]: get_ipython().reset()
156 In [4]: get_ipython().reset()
157 Hi
157 Hi
158
158
159 In [5]: 1+1
159 In [5]: 1+1
160 Out[5]: 2
160 Out[5]: 2
161 """
161 """
162
162
163 # For some tests, it will be handy to organize them in a class with a common
163 # For some tests, it will be handy to organize them in a class with a common
164 # setup that makes a temp file
164 # setup that makes a temp file
165
165
166 class TestMagicRunPass(tt.TempFileMixin):
166 class TestMagicRunPass(tt.TempFileMixin):
167
167
168 def setUp(self):
168 def setUp(self):
169 content = "a = [1,2,3]\nb = 1"
169 content = "a = [1,2,3]\nb = 1"
170 self.mktmp(content)
170 self.mktmp(content)
171
171
172 def run_tmpfile(self):
172 def run_tmpfile(self):
173 _ip = get_ipython()
173 _ip = get_ipython()
174 # This fails on Windows if self.tmpfile.name has spaces or "~" in it.
174 # This fails on Windows if self.tmpfile.name has spaces or "~" in it.
175 # See below and ticket https://bugs.launchpad.net/bugs/366353
175 # See below and ticket https://bugs.launchpad.net/bugs/366353
176 _ip.magic('run %s' % self.fname)
176 _ip.magic('run %s' % self.fname)
177
177
178 def run_tmpfile_p(self):
178 def run_tmpfile_p(self):
179 _ip = get_ipython()
179 _ip = get_ipython()
180 # This fails on Windows if self.tmpfile.name has spaces or "~" in it.
180 # This fails on Windows if self.tmpfile.name has spaces or "~" in it.
181 # See below and ticket https://bugs.launchpad.net/bugs/366353
181 # See below and ticket https://bugs.launchpad.net/bugs/366353
182 _ip.magic('run -p %s' % self.fname)
182 _ip.magic('run -p %s' % self.fname)
183
183
184 def test_builtins_id(self):
184 def test_builtins_id(self):
185 """Check that %run doesn't damage __builtins__ """
185 """Check that %run doesn't damage __builtins__ """
186 _ip = get_ipython()
186 _ip = get_ipython()
187 # Test that the id of __builtins__ is not modified by %run
187 # Test that the id of __builtins__ is not modified by %run
188 bid1 = id(_ip.user_ns['__builtins__'])
188 bid1 = id(_ip.user_ns['__builtins__'])
189 self.run_tmpfile()
189 self.run_tmpfile()
190 bid2 = id(_ip.user_ns['__builtins__'])
190 bid2 = id(_ip.user_ns['__builtins__'])
191 nt.assert_equal(bid1, bid2)
191 nt.assert_equal(bid1, bid2)
192
192
193 def test_builtins_type(self):
193 def test_builtins_type(self):
194 """Check that the type of __builtins__ doesn't change with %run.
194 """Check that the type of __builtins__ doesn't change with %run.
195
195
196 However, the above could pass if __builtins__ was already modified to
196 However, the above could pass if __builtins__ was already modified to
197 be a dict (it should be a module) by a previous use of %run. So we
197 be a dict (it should be a module) by a previous use of %run. So we
198 also check explicitly that it really is a module:
198 also check explicitly that it really is a module:
199 """
199 """
200 _ip = get_ipython()
200 _ip = get_ipython()
201 self.run_tmpfile()
201 self.run_tmpfile()
202 nt.assert_equal(type(_ip.user_ns['__builtins__']),type(sys))
202 nt.assert_equal(type(_ip.user_ns['__builtins__']),type(sys))
203
203
204 def test_run_profile( self ):
204 def test_run_profile( self ):
205 """Test that the option -p, which invokes the profiler, do not
205 """Test that the option -p, which invokes the profiler, do not
206 crash by invoking execfile"""
206 crash by invoking execfile"""
207 self.run_tmpfile_p()
207 self.run_tmpfile_p()
208
208
209 def test_run_debug_twice(self):
209 def test_run_debug_twice(self):
210 # https://github.com/ipython/ipython/issues/10028
210 # https://github.com/ipython/ipython/issues/10028
211 _ip = get_ipython()
211 _ip = get_ipython()
212 with tt.fake_input(['c']):
212 with tt.fake_input(['c']):
213 _ip.magic('run -d %s' % self.fname)
213 _ip.magic('run -d %s' % self.fname)
214 with tt.fake_input(['c']):
214 with tt.fake_input(['c']):
215 _ip.magic('run -d %s' % self.fname)
215 _ip.magic('run -d %s' % self.fname)
216
216
217 def test_run_debug_twice_with_breakpoint(self):
217 def test_run_debug_twice_with_breakpoint(self):
218 """Make a valid python temp file."""
218 """Make a valid python temp file."""
219 _ip = get_ipython()
219 _ip = get_ipython()
220 with tt.fake_input(['b 2', 'c', 'c']):
220 with tt.fake_input(['b 2', 'c', 'c']):
221 _ip.magic('run -d %s' % self.fname)
221 _ip.magic('run -d %s' % self.fname)
222
222
223 with tt.fake_input(['c']):
223 with tt.fake_input(['c']):
224 with tt.AssertNotPrints('KeyError'):
224 with tt.AssertNotPrints('KeyError'):
225 _ip.magic('run -d %s' % self.fname)
225 _ip.magic('run -d %s' % self.fname)
226
226
227
227
228 class TestMagicRunSimple(tt.TempFileMixin):
228 class TestMagicRunSimple(tt.TempFileMixin):
229
229
230 def test_simpledef(self):
230 def test_simpledef(self):
231 """Test that simple class definitions work."""
231 """Test that simple class definitions work."""
232 src = ("class foo: pass\n"
232 src = ("class foo: pass\n"
233 "def f(): return foo()")
233 "def f(): return foo()")
234 self.mktmp(src)
234 self.mktmp(src)
235 _ip.magic('run %s' % self.fname)
235 _ip.magic('run %s' % self.fname)
236 _ip.run_cell('t = isinstance(f(), foo)')
236 _ip.run_cell('t = isinstance(f(), foo)')
237 nt.assert_true(_ip.user_ns['t'])
237 nt.assert_true(_ip.user_ns['t'])
238
238
239 def test_obj_del(self):
239 def test_obj_del(self):
240 """Test that object's __del__ methods are called on exit."""
240 """Test that object's __del__ methods are called on exit."""
241 if sys.platform == 'win32':
241 if sys.platform == 'win32':
242 try:
242 try:
243 import win32api
243 import win32api
244 except ImportError:
244 except ImportError:
245 raise SkipTest("Test requires pywin32")
245 raise SkipTest("Test requires pywin32")
246 src = ("class A(object):\n"
246 src = ("class A(object):\n"
247 " def __del__(self):\n"
247 " def __del__(self):\n"
248 " print('object A deleted')\n"
248 " print('object A deleted')\n"
249 "a = A()\n")
249 "a = A()\n")
250 self.mktmp(src)
250 self.mktmp(src)
251 if dec.module_not_available('sqlite3'):
251 err = None
252 err = 'WARNING: IPython History requires SQLite, your history will not be saved\n'
253 else:
254 err = None
255 tt.ipexec_validate(self.fname, 'object A deleted', err)
252 tt.ipexec_validate(self.fname, 'object A deleted', err)
256
253
257 def test_aggressive_namespace_cleanup(self):
254 def test_aggressive_namespace_cleanup(self):
258 """Test that namespace cleanup is not too aggressive GH-238
255 """Test that namespace cleanup is not too aggressive GH-238
259
256
260 Returning from another run magic deletes the namespace"""
257 Returning from another run magic deletes the namespace"""
261 # see ticket https://github.com/ipython/ipython/issues/238
258 # see ticket https://github.com/ipython/ipython/issues/238
262
259
263 with tt.TempFileMixin() as empty:
260 with tt.TempFileMixin() as empty:
264 empty.mktmp('')
261 empty.mktmp('')
265 # On Windows, the filename will have \users in it, so we need to use the
262 # On Windows, the filename will have \users in it, so we need to use the
266 # repr so that the \u becomes \\u.
263 # repr so that the \u becomes \\u.
267 src = ("ip = get_ipython()\n"
264 src = ("ip = get_ipython()\n"
268 "for i in range(5):\n"
265 "for i in range(5):\n"
269 " try:\n"
266 " try:\n"
270 " ip.magic(%r)\n"
267 " ip.magic(%r)\n"
271 " except NameError as e:\n"
268 " except NameError as e:\n"
272 " print(i)\n"
269 " print(i)\n"
273 " break\n" % ('run ' + empty.fname))
270 " break\n" % ('run ' + empty.fname))
274 self.mktmp(src)
271 self.mktmp(src)
275 _ip.magic('run %s' % self.fname)
272 _ip.magic('run %s' % self.fname)
276 _ip.run_cell('ip == get_ipython()')
273 _ip.run_cell('ip == get_ipython()')
277 nt.assert_equal(_ip.user_ns['i'], 4)
274 nt.assert_equal(_ip.user_ns['i'], 4)
278
275
279 def test_run_second(self):
276 def test_run_second(self):
280 """Test that running a second file doesn't clobber the first, gh-3547
277 """Test that running a second file doesn't clobber the first, gh-3547
281 """
278 """
282 self.mktmp("avar = 1\n"
279 self.mktmp("avar = 1\n"
283 "def afunc():\n"
280 "def afunc():\n"
284 " return avar\n")
281 " return avar\n")
285
282
286 with tt.TempFileMixin() as empty:
283 with tt.TempFileMixin() as empty:
287 empty.mktmp("")
284 empty.mktmp("")
288
285
289 _ip.magic('run %s' % self.fname)
286 _ip.magic('run %s' % self.fname)
290 _ip.magic('run %s' % empty.fname)
287 _ip.magic('run %s' % empty.fname)
291 nt.assert_equal(_ip.user_ns['afunc'](), 1)
288 nt.assert_equal(_ip.user_ns['afunc'](), 1)
292
289
293 @dec.skip_win32
290 @dec.skip_win32
294 def test_tclass(self):
291 def test_tclass(self):
295 mydir = os.path.dirname(__file__)
292 mydir = os.path.dirname(__file__)
296 tc = os.path.join(mydir, 'tclass')
293 tc = os.path.join(mydir, 'tclass')
297 src = ("%%run '%s' C-first\n"
294 src = ("%%run '%s' C-first\n"
298 "%%run '%s' C-second\n"
295 "%%run '%s' C-second\n"
299 "%%run '%s' C-third\n") % (tc, tc, tc)
296 "%%run '%s' C-third\n") % (tc, tc, tc)
300 self.mktmp(src, '.ipy')
297 self.mktmp(src, '.ipy')
301 out = """\
298 out = """\
302 ARGV 1-: ['C-first']
299 ARGV 1-: ['C-first']
303 ARGV 1-: ['C-second']
300 ARGV 1-: ['C-second']
304 tclass.py: deleting object: C-first
301 tclass.py: deleting object: C-first
305 ARGV 1-: ['C-third']
302 ARGV 1-: ['C-third']
306 tclass.py: deleting object: C-second
303 tclass.py: deleting object: C-second
307 tclass.py: deleting object: C-third
304 tclass.py: deleting object: C-third
308 """
305 """
309 if dec.module_not_available('sqlite3'):
306 err = None
310 err = 'WARNING: IPython History requires SQLite, your history will not be saved\n'
311 else:
312 err = None
313 tt.ipexec_validate(self.fname, out, err)
307 tt.ipexec_validate(self.fname, out, err)
314
308
315 def test_run_i_after_reset(self):
309 def test_run_i_after_reset(self):
316 """Check that %run -i still works after %reset (gh-693)"""
310 """Check that %run -i still works after %reset (gh-693)"""
317 src = "yy = zz\n"
311 src = "yy = zz\n"
318 self.mktmp(src)
312 self.mktmp(src)
319 _ip.run_cell("zz = 23")
313 _ip.run_cell("zz = 23")
320 try:
314 try:
321 _ip.magic('run -i %s' % self.fname)
315 _ip.magic('run -i %s' % self.fname)
322 nt.assert_equal(_ip.user_ns['yy'], 23)
316 nt.assert_equal(_ip.user_ns['yy'], 23)
323 finally:
317 finally:
324 _ip.magic('reset -f')
318 _ip.magic('reset -f')
325
319
326 _ip.run_cell("zz = 23")
320 _ip.run_cell("zz = 23")
327 try:
321 try:
328 _ip.magic('run -i %s' % self.fname)
322 _ip.magic('run -i %s' % self.fname)
329 nt.assert_equal(_ip.user_ns['yy'], 23)
323 nt.assert_equal(_ip.user_ns['yy'], 23)
330 finally:
324 finally:
331 _ip.magic('reset -f')
325 _ip.magic('reset -f')
332
326
333 def test_unicode(self):
327 def test_unicode(self):
334 """Check that files in odd encodings are accepted."""
328 """Check that files in odd encodings are accepted."""
335 mydir = os.path.dirname(__file__)
329 mydir = os.path.dirname(__file__)
336 na = os.path.join(mydir, 'nonascii.py')
330 na = os.path.join(mydir, 'nonascii.py')
337 _ip.magic('run "%s"' % na)
331 _ip.magic('run "%s"' % na)
338 nt.assert_equal(_ip.user_ns['u'], u'ΠŽΡ‚β„–Π€')
332 nt.assert_equal(_ip.user_ns['u'], u'ΠŽΡ‚β„–Π€')
339
333
340 def test_run_py_file_attribute(self):
334 def test_run_py_file_attribute(self):
341 """Test handling of `__file__` attribute in `%run <file>.py`."""
335 """Test handling of `__file__` attribute in `%run <file>.py`."""
342 src = "t = __file__\n"
336 src = "t = __file__\n"
343 self.mktmp(src)
337 self.mktmp(src)
344 _missing = object()
338 _missing = object()
345 file1 = _ip.user_ns.get('__file__', _missing)
339 file1 = _ip.user_ns.get('__file__', _missing)
346 _ip.magic('run %s' % self.fname)
340 _ip.magic('run %s' % self.fname)
347 file2 = _ip.user_ns.get('__file__', _missing)
341 file2 = _ip.user_ns.get('__file__', _missing)
348
342
349 # Check that __file__ was equal to the filename in the script's
343 # Check that __file__ was equal to the filename in the script's
350 # namespace.
344 # namespace.
351 nt.assert_equal(_ip.user_ns['t'], self.fname)
345 nt.assert_equal(_ip.user_ns['t'], self.fname)
352
346
353 # Check that __file__ was not leaked back into user_ns.
347 # Check that __file__ was not leaked back into user_ns.
354 nt.assert_equal(file1, file2)
348 nt.assert_equal(file1, file2)
355
349
356 def test_run_ipy_file_attribute(self):
350 def test_run_ipy_file_attribute(self):
357 """Test handling of `__file__` attribute in `%run <file.ipy>`."""
351 """Test handling of `__file__` attribute in `%run <file.ipy>`."""
358 src = "t = __file__\n"
352 src = "t = __file__\n"
359 self.mktmp(src, ext='.ipy')
353 self.mktmp(src, ext='.ipy')
360 _missing = object()
354 _missing = object()
361 file1 = _ip.user_ns.get('__file__', _missing)
355 file1 = _ip.user_ns.get('__file__', _missing)
362 _ip.magic('run %s' % self.fname)
356 _ip.magic('run %s' % self.fname)
363 file2 = _ip.user_ns.get('__file__', _missing)
357 file2 = _ip.user_ns.get('__file__', _missing)
364
358
365 # Check that __file__ was equal to the filename in the script's
359 # Check that __file__ was equal to the filename in the script's
366 # namespace.
360 # namespace.
367 nt.assert_equal(_ip.user_ns['t'], self.fname)
361 nt.assert_equal(_ip.user_ns['t'], self.fname)
368
362
369 # Check that __file__ was not leaked back into user_ns.
363 # Check that __file__ was not leaked back into user_ns.
370 nt.assert_equal(file1, file2)
364 nt.assert_equal(file1, file2)
371
365
372 def test_run_formatting(self):
366 def test_run_formatting(self):
373 """ Test that %run -t -N<N> does not raise a TypeError for N > 1."""
367 """ Test that %run -t -N<N> does not raise a TypeError for N > 1."""
374 src = "pass"
368 src = "pass"
375 self.mktmp(src)
369 self.mktmp(src)
376 _ip.magic('run -t -N 1 %s' % self.fname)
370 _ip.magic('run -t -N 1 %s' % self.fname)
377 _ip.magic('run -t -N 10 %s' % self.fname)
371 _ip.magic('run -t -N 10 %s' % self.fname)
378
372
379 def test_ignore_sys_exit(self):
373 def test_ignore_sys_exit(self):
380 """Test the -e option to ignore sys.exit()"""
374 """Test the -e option to ignore sys.exit()"""
381 src = "import sys; sys.exit(1)"
375 src = "import sys; sys.exit(1)"
382 self.mktmp(src)
376 self.mktmp(src)
383 with tt.AssertPrints('SystemExit'):
377 with tt.AssertPrints('SystemExit'):
384 _ip.magic('run %s' % self.fname)
378 _ip.magic('run %s' % self.fname)
385
379
386 with tt.AssertNotPrints('SystemExit'):
380 with tt.AssertNotPrints('SystemExit'):
387 _ip.magic('run -e %s' % self.fname)
381 _ip.magic('run -e %s' % self.fname)
388
382
389 def test_run_nb(self):
383 def test_run_nb(self):
390 """Test %run notebook.ipynb"""
384 """Test %run notebook.ipynb"""
391 from nbformat import v4, writes
385 from nbformat import v4, writes
392 nb = v4.new_notebook(
386 nb = v4.new_notebook(
393 cells=[
387 cells=[
394 v4.new_markdown_cell("The Ultimate Question of Everything"),
388 v4.new_markdown_cell("The Ultimate Question of Everything"),
395 v4.new_code_cell("answer=42")
389 v4.new_code_cell("answer=42")
396 ]
390 ]
397 )
391 )
398 src = writes(nb, version=4)
392 src = writes(nb, version=4)
399 self.mktmp(src, ext='.ipynb')
393 self.mktmp(src, ext='.ipynb')
400
394
401 _ip.magic("run %s" % self.fname)
395 _ip.magic("run %s" % self.fname)
402
396
403 nt.assert_equal(_ip.user_ns['answer'], 42)
397 nt.assert_equal(_ip.user_ns['answer'], 42)
404
398
405 def test_file_options(self):
399 def test_file_options(self):
406 src = ('import sys\n'
400 src = ('import sys\n'
407 'a = " ".join(sys.argv[1:])\n')
401 'a = " ".join(sys.argv[1:])\n')
408 self.mktmp(src)
402 self.mktmp(src)
409 test_opts = '-x 3 --verbose'
403 test_opts = '-x 3 --verbose'
410 _ip.run_line_magic("run", '{0} {1}'.format(self.fname, test_opts))
404 _ip.run_line_magic("run", '{0} {1}'.format(self.fname, test_opts))
411 nt.assert_equal(_ip.user_ns['a'], test_opts)
405 nt.assert_equal(_ip.user_ns['a'], test_opts)
412
406
413
407
414 class TestMagicRunWithPackage(unittest.TestCase):
408 class TestMagicRunWithPackage(unittest.TestCase):
415
409
416 def writefile(self, name, content):
410 def writefile(self, name, content):
417 path = os.path.join(self.tempdir.name, name)
411 path = os.path.join(self.tempdir.name, name)
418 d = os.path.dirname(path)
412 d = os.path.dirname(path)
419 if not os.path.isdir(d):
413 if not os.path.isdir(d):
420 os.makedirs(d)
414 os.makedirs(d)
421 with open(path, 'w') as f:
415 with open(path, 'w') as f:
422 f.write(textwrap.dedent(content))
416 f.write(textwrap.dedent(content))
423
417
424 def setUp(self):
418 def setUp(self):
425 self.package = package = 'tmp{0}'.format(''.join([random.choice(string.ascii_letters) for i in range(10)]))
419 self.package = package = 'tmp{0}'.format(''.join([random.choice(string.ascii_letters) for i in range(10)]))
426 """Temporary (probably) valid python package name."""
420 """Temporary (probably) valid python package name."""
427
421
428 self.value = int(random.random() * 10000)
422 self.value = int(random.random() * 10000)
429
423
430 self.tempdir = TemporaryDirectory()
424 self.tempdir = TemporaryDirectory()
431 self.__orig_cwd = os.getcwd()
425 self.__orig_cwd = os.getcwd()
432 sys.path.insert(0, self.tempdir.name)
426 sys.path.insert(0, self.tempdir.name)
433
427
434 self.writefile(os.path.join(package, '__init__.py'), '')
428 self.writefile(os.path.join(package, '__init__.py'), '')
435 self.writefile(os.path.join(package, 'sub.py'), """
429 self.writefile(os.path.join(package, 'sub.py'), """
436 x = {0!r}
430 x = {0!r}
437 """.format(self.value))
431 """.format(self.value))
438 self.writefile(os.path.join(package, 'relative.py'), """
432 self.writefile(os.path.join(package, 'relative.py'), """
439 from .sub import x
433 from .sub import x
440 """)
434 """)
441 self.writefile(os.path.join(package, 'absolute.py'), """
435 self.writefile(os.path.join(package, 'absolute.py'), """
442 from {0}.sub import x
436 from {0}.sub import x
443 """.format(package))
437 """.format(package))
444 self.writefile(os.path.join(package, 'args.py'), """
438 self.writefile(os.path.join(package, 'args.py'), """
445 import sys
439 import sys
446 a = " ".join(sys.argv[1:])
440 a = " ".join(sys.argv[1:])
447 """.format(package))
441 """.format(package))
448
442
449 def tearDown(self):
443 def tearDown(self):
450 os.chdir(self.__orig_cwd)
444 os.chdir(self.__orig_cwd)
451 sys.path[:] = [p for p in sys.path if p != self.tempdir.name]
445 sys.path[:] = [p for p in sys.path if p != self.tempdir.name]
452 self.tempdir.cleanup()
446 self.tempdir.cleanup()
453
447
454 def check_run_submodule(self, submodule, opts=''):
448 def check_run_submodule(self, submodule, opts=''):
455 _ip.user_ns.pop('x', None)
449 _ip.user_ns.pop('x', None)
456 _ip.magic('run {2} -m {0}.{1}'.format(self.package, submodule, opts))
450 _ip.magic('run {2} -m {0}.{1}'.format(self.package, submodule, opts))
457 self.assertEqual(_ip.user_ns['x'], self.value,
451 self.assertEqual(_ip.user_ns['x'], self.value,
458 'Variable `x` is not loaded from module `{0}`.'
452 'Variable `x` is not loaded from module `{0}`.'
459 .format(submodule))
453 .format(submodule))
460
454
461 def test_run_submodule_with_absolute_import(self):
455 def test_run_submodule_with_absolute_import(self):
462 self.check_run_submodule('absolute')
456 self.check_run_submodule('absolute')
463
457
464 def test_run_submodule_with_relative_import(self):
458 def test_run_submodule_with_relative_import(self):
465 """Run submodule that has a relative import statement (#2727)."""
459 """Run submodule that has a relative import statement (#2727)."""
466 self.check_run_submodule('relative')
460 self.check_run_submodule('relative')
467
461
468 def test_prun_submodule_with_absolute_import(self):
462 def test_prun_submodule_with_absolute_import(self):
469 self.check_run_submodule('absolute', '-p')
463 self.check_run_submodule('absolute', '-p')
470
464
471 def test_prun_submodule_with_relative_import(self):
465 def test_prun_submodule_with_relative_import(self):
472 self.check_run_submodule('relative', '-p')
466 self.check_run_submodule('relative', '-p')
473
467
474 def with_fake_debugger(func):
468 def with_fake_debugger(func):
475 @functools.wraps(func)
469 @functools.wraps(func)
476 def wrapper(*args, **kwds):
470 def wrapper(*args, **kwds):
477 with patch.object(debugger.Pdb, 'run', staticmethod(eval)):
471 with patch.object(debugger.Pdb, 'run', staticmethod(eval)):
478 return func(*args, **kwds)
472 return func(*args, **kwds)
479 return wrapper
473 return wrapper
480
474
481 @with_fake_debugger
475 @with_fake_debugger
482 def test_debug_run_submodule_with_absolute_import(self):
476 def test_debug_run_submodule_with_absolute_import(self):
483 self.check_run_submodule('absolute', '-d')
477 self.check_run_submodule('absolute', '-d')
484
478
485 @with_fake_debugger
479 @with_fake_debugger
486 def test_debug_run_submodule_with_relative_import(self):
480 def test_debug_run_submodule_with_relative_import(self):
487 self.check_run_submodule('relative', '-d')
481 self.check_run_submodule('relative', '-d')
488
482
489 def test_module_options(self):
483 def test_module_options(self):
490 _ip.user_ns.pop('a', None)
484 _ip.user_ns.pop('a', None)
491 test_opts = '-x abc -m test'
485 test_opts = '-x abc -m test'
492 _ip.run_line_magic('run', '-m {0}.args {1}'.format(self.package, test_opts))
486 _ip.run_line_magic('run', '-m {0}.args {1}'.format(self.package, test_opts))
493 nt.assert_equal(_ip.user_ns['a'], test_opts)
487 nt.assert_equal(_ip.user_ns['a'], test_opts)
494
488
495 def test_module_options_with_separator(self):
489 def test_module_options_with_separator(self):
496 _ip.user_ns.pop('a', None)
490 _ip.user_ns.pop('a', None)
497 test_opts = '-x abc -m test'
491 test_opts = '-x abc -m test'
498 _ip.run_line_magic('run', '-m {0}.args -- {1}'.format(self.package, test_opts))
492 _ip.run_line_magic('run', '-m {0}.args -- {1}'.format(self.package, test_opts))
499 nt.assert_equal(_ip.user_ns['a'], test_opts)
493 nt.assert_equal(_ip.user_ns['a'], test_opts)
500
494
501 def test_run__name__():
495 def test_run__name__():
502 with TemporaryDirectory() as td:
496 with TemporaryDirectory() as td:
503 path = pjoin(td, 'foo.py')
497 path = pjoin(td, 'foo.py')
504 with open(path, 'w') as f:
498 with open(path, 'w') as f:
505 f.write("q = __name__")
499 f.write("q = __name__")
506
500
507 _ip.user_ns.pop('q', None)
501 _ip.user_ns.pop('q', None)
508 _ip.magic('run {}'.format(path))
502 _ip.magic('run {}'.format(path))
509 nt.assert_equal(_ip.user_ns.pop('q'), '__main__')
503 nt.assert_equal(_ip.user_ns.pop('q'), '__main__')
510
504
511 _ip.magic('run -n {}'.format(path))
505 _ip.magic('run -n {}'.format(path))
512 nt.assert_equal(_ip.user_ns.pop('q'), 'foo')
506 nt.assert_equal(_ip.user_ns.pop('q'), 'foo')
513
507
514 try:
508 try:
515 _ip.magic('run -i -n {}'.format(path))
509 _ip.magic('run -i -n {}'.format(path))
516 nt.assert_equal(_ip.user_ns.pop('q'), 'foo')
510 nt.assert_equal(_ip.user_ns.pop('q'), 'foo')
517 finally:
511 finally:
518 _ip.magic('reset -f')
512 _ip.magic('reset -f')
519
513
520
514
521 def test_run_tb():
515 def test_run_tb():
522 """Test traceback offset in %run"""
516 """Test traceback offset in %run"""
523 with TemporaryDirectory() as td:
517 with TemporaryDirectory() as td:
524 path = pjoin(td, 'foo.py')
518 path = pjoin(td, 'foo.py')
525 with open(path, 'w') as f:
519 with open(path, 'w') as f:
526 f.write('\n'.join([
520 f.write('\n'.join([
527 "def foo():",
521 "def foo():",
528 " return bar()",
522 " return bar()",
529 "def bar():",
523 "def bar():",
530 " raise RuntimeError('hello!')",
524 " raise RuntimeError('hello!')",
531 "foo()",
525 "foo()",
532 ]))
526 ]))
533 with capture_output() as io:
527 with capture_output() as io:
534 _ip.magic('run {}'.format(path))
528 _ip.magic('run {}'.format(path))
535 out = io.stdout
529 out = io.stdout
536 nt.assert_not_in("execfile", out)
530 nt.assert_not_in("execfile", out)
537 nt.assert_in("RuntimeError", out)
531 nt.assert_in("RuntimeError", out)
538 nt.assert_equal(out.count("---->"), 3)
532 nt.assert_equal(out.count("---->"), 3)
539 del ip.user_ns['bar']
533 del ip.user_ns['bar']
540 del ip.user_ns['foo']
534 del ip.user_ns['foo']
541
535
542
536
543 def test_multiprocessing_run():
537 def test_multiprocessing_run():
544 """Set we can run mutiprocesgin without messing up up main namespace
538 """Set we can run mutiprocesgin without messing up up main namespace
545
539
546 Note that import `nose.tools as nt` mdify the value s
540 Note that import `nose.tools as nt` mdify the value s
547 sys.module['__mp_main__'] so wee need to temporarily set it to None to test
541 sys.module['__mp_main__'] so wee need to temporarily set it to None to test
548 the issue.
542 the issue.
549 """
543 """
550 with TemporaryDirectory() as td:
544 with TemporaryDirectory() as td:
551 mpm = sys.modules.get('__mp_main__')
545 mpm = sys.modules.get('__mp_main__')
552 assert mpm is not None
546 assert mpm is not None
553 sys.modules['__mp_main__'] = None
547 sys.modules['__mp_main__'] = None
554 try:
548 try:
555 path = pjoin(td, 'test.py')
549 path = pjoin(td, 'test.py')
556 with open(path, 'w') as f:
550 with open(path, 'w') as f:
557 f.write("import multiprocessing\nprint('hoy')")
551 f.write("import multiprocessing\nprint('hoy')")
558 with capture_output() as io:
552 with capture_output() as io:
559 _ip.run_line_magic('run', path)
553 _ip.run_line_magic('run', path)
560 _ip.run_cell("i_m_undefined")
554 _ip.run_cell("i_m_undefined")
561 out = io.stdout
555 out = io.stdout
562 nt.assert_in("hoy", out)
556 nt.assert_in("hoy", out)
563 nt.assert_not_in("AttributeError", out)
557 nt.assert_not_in("AttributeError", out)
564 nt.assert_in("NameError", out)
558 nt.assert_in("NameError", out)
565 nt.assert_equal(out.count("---->"), 1)
559 nt.assert_equal(out.count("---->"), 1)
566 except:
560 except:
567 raise
561 raise
568 finally:
562 finally:
569 sys.modules['__mp_main__'] = mpm
563 sys.modules['__mp_main__'] = mpm
570
564
571 @dec.knownfailureif(sys.platform == 'win32', "writes to io.stdout aren't captured on Windows")
565 @dec.knownfailureif(sys.platform == 'win32', "writes to io.stdout aren't captured on Windows")
572 def test_script_tb():
566 def test_script_tb():
573 """Test traceback offset in `ipython script.py`"""
567 """Test traceback offset in `ipython script.py`"""
574 with TemporaryDirectory() as td:
568 with TemporaryDirectory() as td:
575 path = pjoin(td, 'foo.py')
569 path = pjoin(td, 'foo.py')
576 with open(path, 'w') as f:
570 with open(path, 'w') as f:
577 f.write('\n'.join([
571 f.write('\n'.join([
578 "def foo():",
572 "def foo():",
579 " return bar()",
573 " return bar()",
580 "def bar():",
574 "def bar():",
581 " raise RuntimeError('hello!')",
575 " raise RuntimeError('hello!')",
582 "foo()",
576 "foo()",
583 ]))
577 ]))
584 out, err = tt.ipexec(path)
578 out, err = tt.ipexec(path)
585 nt.assert_not_in("execfile", out)
579 nt.assert_not_in("execfile", out)
586 nt.assert_in("RuntimeError", out)
580 nt.assert_in("RuntimeError", out)
587 nt.assert_equal(out.count("---->"), 3)
581 nt.assert_equal(out.count("---->"), 3)
588
582
@@ -1,60 +1,57 b''
1 # -*- coding: utf-8 -*-
1 # -*- coding: utf-8 -*-
2 """Tests for shellapp module.
2 """Tests for shellapp module.
3
3
4 Authors
4 Authors
5 -------
5 -------
6 * Bradley Froehle
6 * Bradley Froehle
7 """
7 """
8 #-----------------------------------------------------------------------------
8 #-----------------------------------------------------------------------------
9 # Copyright (C) 2012 The IPython Development Team
9 # Copyright (C) 2012 The IPython Development Team
10 #
10 #
11 # Distributed under the terms of the BSD License. The full license is in
11 # Distributed under the terms of the BSD License. The full license is in
12 # the file COPYING, distributed as part of this software.
12 # the file COPYING, distributed as part of this software.
13 #-----------------------------------------------------------------------------
13 #-----------------------------------------------------------------------------
14
14
15 #-----------------------------------------------------------------------------
15 #-----------------------------------------------------------------------------
16 # Imports
16 # Imports
17 #-----------------------------------------------------------------------------
17 #-----------------------------------------------------------------------------
18 import unittest
18 import unittest
19
19
20 from IPython.testing import decorators as dec
20 from IPython.testing import decorators as dec
21 from IPython.testing import tools as tt
21 from IPython.testing import tools as tt
22
22
23 sqlite_err_maybe = dec.module_not_available('sqlite3')
24 SQLITE_NOT_AVAILABLE_ERROR = ('WARNING: IPython History requires SQLite,'
25 ' your history will not be saved\n')
26
23
27 class TestFileToRun(tt.TempFileMixin, unittest.TestCase):
24 class TestFileToRun(tt.TempFileMixin, unittest.TestCase):
28 """Test the behavior of the file_to_run parameter."""
25 """Test the behavior of the file_to_run parameter."""
29
26
30 def test_py_script_file_attribute(self):
27 def test_py_script_file_attribute(self):
31 """Test that `__file__` is set when running `ipython file.py`"""
28 """Test that `__file__` is set when running `ipython file.py`"""
32 src = "print(__file__)\n"
29 src = "print(__file__)\n"
33 self.mktmp(src)
30 self.mktmp(src)
34
31
35 err = SQLITE_NOT_AVAILABLE_ERROR if sqlite_err_maybe else None
32 err = None
36 tt.ipexec_validate(self.fname, self.fname, err)
33 tt.ipexec_validate(self.fname, self.fname, err)
37
34
38 def test_ipy_script_file_attribute(self):
35 def test_ipy_script_file_attribute(self):
39 """Test that `__file__` is set when running `ipython file.ipy`"""
36 """Test that `__file__` is set when running `ipython file.ipy`"""
40 src = "print(__file__)\n"
37 src = "print(__file__)\n"
41 self.mktmp(src, ext='.ipy')
38 self.mktmp(src, ext='.ipy')
42
39
43 err = SQLITE_NOT_AVAILABLE_ERROR if sqlite_err_maybe else None
40 err = None
44 tt.ipexec_validate(self.fname, self.fname, err)
41 tt.ipexec_validate(self.fname, self.fname, err)
45
42
46 # The commands option to ipexec_validate doesn't work on Windows, and it
43 # The commands option to ipexec_validate doesn't work on Windows, and it
47 # doesn't seem worth fixing
44 # doesn't seem worth fixing
48 @dec.skip_win32
45 @dec.skip_win32
49 def test_py_script_file_attribute_interactively(self):
46 def test_py_script_file_attribute_interactively(self):
50 """Test that `__file__` is not set after `ipython -i file.py`"""
47 """Test that `__file__` is not set after `ipython -i file.py`"""
51 src = "True\n"
48 src = "True\n"
52 self.mktmp(src)
49 self.mktmp(src)
53
50
54 out, err = tt.ipexec(self.fname, options=['-i'],
51 out, err = tt.ipexec(self.fname, options=['-i'],
55 commands=['"__file__" in globals()', 'print(123)', 'exit()'])
52 commands=['"__file__" in globals()', 'print(123)', 'exit()'])
56 if 'False' not in out:
53 if 'False' not in out:
57 print("Subprocess stderr:")
54 print("Subprocess stderr:")
58 print(err)
55 print(err)
59 print('-----')
56 print('-----')
60 raise AssertionError("'False' not found in %r" % out)
57 raise AssertionError("'False' not found in %r" % out)
General Comments 0
You need to be logged in to leave comments. Login now