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