##// END OF EJS Templates
test %run notebook.ipynb
MinRK -
Show More
@@ -1,458 +1,475 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.tempdir import TemporaryDirectory
31 from IPython.utils.tempdir import TemporaryDirectory
32 from IPython.core import debugger
32 from IPython.core import debugger
33
33
34 #-----------------------------------------------------------------------------
34 #-----------------------------------------------------------------------------
35 # Test functions begin
35 # Test functions begin
36 #-----------------------------------------------------------------------------
36 #-----------------------------------------------------------------------------
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 @py3compat.doctest_refactor_print
146 @py3compat.doctest_refactor_print
147 def doctest_reset_del():
147 def doctest_reset_del():
148 """Test that resetting doesn't cause errors in __del__ methods.
148 """Test that resetting doesn't cause errors in __del__ methods.
149
149
150 In [2]: class A(object):
150 In [2]: class A(object):
151 ...: def __del__(self):
151 ...: def __del__(self):
152 ...: print str("Hi")
152 ...: print str("Hi")
153 ...:
153 ...:
154
154
155 In [3]: a = A()
155 In [3]: a = A()
156
156
157 In [4]: get_ipython().reset()
157 In [4]: get_ipython().reset()
158 Hi
158 Hi
159
159
160 In [5]: 1+1
160 In [5]: 1+1
161 Out[5]: 2
161 Out[5]: 2
162 """
162 """
163
163
164 # For some tests, it will be handy to organize them in a class with a common
164 # For some tests, it will be handy to organize them in a class with a common
165 # setup that makes a temp file
165 # setup that makes a temp file
166
166
167 class TestMagicRunPass(tt.TempFileMixin):
167 class TestMagicRunPass(tt.TempFileMixin):
168
168
169 def setup(self):
169 def setup(self):
170 """Make a valid python temp file."""
170 """Make a valid python temp file."""
171 self.mktmp('pass\n')
171 self.mktmp('pass\n')
172
172
173 def run_tmpfile(self):
173 def run_tmpfile(self):
174 _ip = get_ipython()
174 _ip = get_ipython()
175 # This fails on Windows if self.tmpfile.name has spaces or "~" in it.
175 # This fails on Windows if self.tmpfile.name has spaces or "~" in it.
176 # See below and ticket https://bugs.launchpad.net/bugs/366353
176 # See below and ticket https://bugs.launchpad.net/bugs/366353
177 _ip.magic('run %s' % self.fname)
177 _ip.magic('run %s' % self.fname)
178
178
179 def run_tmpfile_p(self):
179 def run_tmpfile_p(self):
180 _ip = get_ipython()
180 _ip = get_ipython()
181 # This fails on Windows if self.tmpfile.name has spaces or "~" in it.
181 # This fails on Windows if self.tmpfile.name has spaces or "~" in it.
182 # See below and ticket https://bugs.launchpad.net/bugs/366353
182 # See below and ticket https://bugs.launchpad.net/bugs/366353
183 _ip.magic('run -p %s' % self.fname)
183 _ip.magic('run -p %s' % self.fname)
184
184
185 def test_builtins_id(self):
185 def test_builtins_id(self):
186 """Check that %run doesn't damage __builtins__ """
186 """Check that %run doesn't damage __builtins__ """
187 _ip = get_ipython()
187 _ip = get_ipython()
188 # Test that the id of __builtins__ is not modified by %run
188 # Test that the id of __builtins__ is not modified by %run
189 bid1 = id(_ip.user_ns['__builtins__'])
189 bid1 = id(_ip.user_ns['__builtins__'])
190 self.run_tmpfile()
190 self.run_tmpfile()
191 bid2 = id(_ip.user_ns['__builtins__'])
191 bid2 = id(_ip.user_ns['__builtins__'])
192 nt.assert_equal(bid1, bid2)
192 nt.assert_equal(bid1, bid2)
193
193
194 def test_builtins_type(self):
194 def test_builtins_type(self):
195 """Check that the type of __builtins__ doesn't change with %run.
195 """Check that the type of __builtins__ doesn't change with %run.
196
196
197 However, the above could pass if __builtins__ was already modified to
197 However, the above could pass if __builtins__ was already modified to
198 be a dict (it should be a module) by a previous use of %run. So we
198 be a dict (it should be a module) by a previous use of %run. So we
199 also check explicitly that it really is a module:
199 also check explicitly that it really is a module:
200 """
200 """
201 _ip = get_ipython()
201 _ip = get_ipython()
202 self.run_tmpfile()
202 self.run_tmpfile()
203 nt.assert_equal(type(_ip.user_ns['__builtins__']),type(sys))
203 nt.assert_equal(type(_ip.user_ns['__builtins__']),type(sys))
204
204
205 def test_prompts(self):
205 def test_prompts(self):
206 """Test that prompts correctly generate after %run"""
206 """Test that prompts correctly generate after %run"""
207 self.run_tmpfile()
207 self.run_tmpfile()
208 _ip = get_ipython()
208 _ip = get_ipython()
209 p2 = _ip.prompt_manager.render('in2').strip()
209 p2 = _ip.prompt_manager.render('in2').strip()
210 nt.assert_equal(p2[:3], '...')
210 nt.assert_equal(p2[:3], '...')
211
211
212 def test_run_profile( self ):
212 def test_run_profile( self ):
213 """Test that the option -p, which invokes the profiler, do not
213 """Test that the option -p, which invokes the profiler, do not
214 crash by invoking execfile"""
214 crash by invoking execfile"""
215 _ip = get_ipython()
215 _ip = get_ipython()
216 self.run_tmpfile_p()
216 self.run_tmpfile_p()
217
217
218
218
219 class TestMagicRunSimple(tt.TempFileMixin):
219 class TestMagicRunSimple(tt.TempFileMixin):
220
220
221 def test_simpledef(self):
221 def test_simpledef(self):
222 """Test that simple class definitions work."""
222 """Test that simple class definitions work."""
223 src = ("class foo: pass\n"
223 src = ("class foo: pass\n"
224 "def f(): return foo()")
224 "def f(): return foo()")
225 self.mktmp(src)
225 self.mktmp(src)
226 _ip.magic('run %s' % self.fname)
226 _ip.magic('run %s' % self.fname)
227 _ip.run_cell('t = isinstance(f(), foo)')
227 _ip.run_cell('t = isinstance(f(), foo)')
228 nt.assert_true(_ip.user_ns['t'])
228 nt.assert_true(_ip.user_ns['t'])
229
229
230 def test_obj_del(self):
230 def test_obj_del(self):
231 """Test that object's __del__ methods are called on exit."""
231 """Test that object's __del__ methods are called on exit."""
232 if sys.platform == 'win32':
232 if sys.platform == 'win32':
233 try:
233 try:
234 import win32api
234 import win32api
235 except ImportError:
235 except ImportError:
236 raise SkipTest("Test requires pywin32")
236 raise SkipTest("Test requires pywin32")
237 src = ("class A(object):\n"
237 src = ("class A(object):\n"
238 " def __del__(self):\n"
238 " def __del__(self):\n"
239 " print 'object A deleted'\n"
239 " print 'object A deleted'\n"
240 "a = A()\n")
240 "a = A()\n")
241 self.mktmp(py3compat.doctest_refactor_print(src))
241 self.mktmp(py3compat.doctest_refactor_print(src))
242 if dec.module_not_available('sqlite3'):
242 if dec.module_not_available('sqlite3'):
243 err = 'WARNING: IPython History requires SQLite, your history will not be saved\n'
243 err = 'WARNING: IPython History requires SQLite, your history will not be saved\n'
244 else:
244 else:
245 err = None
245 err = None
246 tt.ipexec_validate(self.fname, 'object A deleted', err)
246 tt.ipexec_validate(self.fname, 'object A deleted', err)
247
247
248 def test_aggressive_namespace_cleanup(self):
248 def test_aggressive_namespace_cleanup(self):
249 """Test that namespace cleanup is not too aggressive GH-238
249 """Test that namespace cleanup is not too aggressive GH-238
250
250
251 Returning from another run magic deletes the namespace"""
251 Returning from another run magic deletes the namespace"""
252 # see ticket https://github.com/ipython/ipython/issues/238
252 # see ticket https://github.com/ipython/ipython/issues/238
253 class secondtmp(tt.TempFileMixin): pass
253 class secondtmp(tt.TempFileMixin): pass
254 empty = secondtmp()
254 empty = secondtmp()
255 empty.mktmp('')
255 empty.mktmp('')
256 # On Windows, the filename will have \users in it, so we need to use the
256 # On Windows, the filename will have \users in it, so we need to use the
257 # repr so that the \u becomes \\u.
257 # repr so that the \u becomes \\u.
258 src = ("ip = get_ipython()\n"
258 src = ("ip = get_ipython()\n"
259 "for i in range(5):\n"
259 "for i in range(5):\n"
260 " try:\n"
260 " try:\n"
261 " ip.magic(%r)\n"
261 " ip.magic(%r)\n"
262 " except NameError as e:\n"
262 " except NameError as e:\n"
263 " print(i)\n"
263 " print(i)\n"
264 " break\n" % ('run ' + empty.fname))
264 " break\n" % ('run ' + empty.fname))
265 self.mktmp(src)
265 self.mktmp(src)
266 _ip.magic('run %s' % self.fname)
266 _ip.magic('run %s' % self.fname)
267 _ip.run_cell('ip == get_ipython()')
267 _ip.run_cell('ip == get_ipython()')
268 nt.assert_equal(_ip.user_ns['i'], 4)
268 nt.assert_equal(_ip.user_ns['i'], 4)
269
269
270 def test_run_second(self):
270 def test_run_second(self):
271 """Test that running a second file doesn't clobber the first, gh-3547
271 """Test that running a second file doesn't clobber the first, gh-3547
272 """
272 """
273 self.mktmp("avar = 1\n"
273 self.mktmp("avar = 1\n"
274 "def afunc():\n"
274 "def afunc():\n"
275 " return avar\n")
275 " return avar\n")
276
276
277 empty = tt.TempFileMixin()
277 empty = tt.TempFileMixin()
278 empty.mktmp("")
278 empty.mktmp("")
279
279
280 _ip.magic('run %s' % self.fname)
280 _ip.magic('run %s' % self.fname)
281 _ip.magic('run %s' % empty.fname)
281 _ip.magic('run %s' % empty.fname)
282 nt.assert_equal(_ip.user_ns['afunc'](), 1)
282 nt.assert_equal(_ip.user_ns['afunc'](), 1)
283
283
284 @dec.skip_win32
284 @dec.skip_win32
285 def test_tclass(self):
285 def test_tclass(self):
286 mydir = os.path.dirname(__file__)
286 mydir = os.path.dirname(__file__)
287 tc = os.path.join(mydir, 'tclass')
287 tc = os.path.join(mydir, 'tclass')
288 src = ("%%run '%s' C-first\n"
288 src = ("%%run '%s' C-first\n"
289 "%%run '%s' C-second\n"
289 "%%run '%s' C-second\n"
290 "%%run '%s' C-third\n") % (tc, tc, tc)
290 "%%run '%s' C-third\n") % (tc, tc, tc)
291 self.mktmp(src, '.ipy')
291 self.mktmp(src, '.ipy')
292 out = """\
292 out = """\
293 ARGV 1-: ['C-first']
293 ARGV 1-: ['C-first']
294 ARGV 1-: ['C-second']
294 ARGV 1-: ['C-second']
295 tclass.py: deleting object: C-first
295 tclass.py: deleting object: C-first
296 ARGV 1-: ['C-third']
296 ARGV 1-: ['C-third']
297 tclass.py: deleting object: C-second
297 tclass.py: deleting object: C-second
298 tclass.py: deleting object: C-third
298 tclass.py: deleting object: C-third
299 """
299 """
300 if dec.module_not_available('sqlite3'):
300 if dec.module_not_available('sqlite3'):
301 err = 'WARNING: IPython History requires SQLite, your history will not be saved\n'
301 err = 'WARNING: IPython History requires SQLite, your history will not be saved\n'
302 else:
302 else:
303 err = None
303 err = None
304 tt.ipexec_validate(self.fname, out, err)
304 tt.ipexec_validate(self.fname, out, err)
305
305
306 def test_run_i_after_reset(self):
306 def test_run_i_after_reset(self):
307 """Check that %run -i still works after %reset (gh-693)"""
307 """Check that %run -i still works after %reset (gh-693)"""
308 src = "yy = zz\n"
308 src = "yy = zz\n"
309 self.mktmp(src)
309 self.mktmp(src)
310 _ip.run_cell("zz = 23")
310 _ip.run_cell("zz = 23")
311 _ip.magic('run -i %s' % self.fname)
311 _ip.magic('run -i %s' % self.fname)
312 nt.assert_equal(_ip.user_ns['yy'], 23)
312 nt.assert_equal(_ip.user_ns['yy'], 23)
313 _ip.magic('reset -f')
313 _ip.magic('reset -f')
314 _ip.run_cell("zz = 23")
314 _ip.run_cell("zz = 23")
315 _ip.magic('run -i %s' % self.fname)
315 _ip.magic('run -i %s' % self.fname)
316 nt.assert_equal(_ip.user_ns['yy'], 23)
316 nt.assert_equal(_ip.user_ns['yy'], 23)
317
317
318 def test_unicode(self):
318 def test_unicode(self):
319 """Check that files in odd encodings are accepted."""
319 """Check that files in odd encodings are accepted."""
320 mydir = os.path.dirname(__file__)
320 mydir = os.path.dirname(__file__)
321 na = os.path.join(mydir, 'nonascii.py')
321 na = os.path.join(mydir, 'nonascii.py')
322 _ip.magic('run "%s"' % na)
322 _ip.magic('run "%s"' % na)
323 nt.assert_equal(_ip.user_ns['u'], u'ΠŽΡ‚β„–Π€')
323 nt.assert_equal(_ip.user_ns['u'], u'ΠŽΡ‚β„–Π€')
324
324
325 def test_run_py_file_attribute(self):
325 def test_run_py_file_attribute(self):
326 """Test handling of `__file__` attribute in `%run <file>.py`."""
326 """Test handling of `__file__` attribute in `%run <file>.py`."""
327 src = "t = __file__\n"
327 src = "t = __file__\n"
328 self.mktmp(src)
328 self.mktmp(src)
329 _missing = object()
329 _missing = object()
330 file1 = _ip.user_ns.get('__file__', _missing)
330 file1 = _ip.user_ns.get('__file__', _missing)
331 _ip.magic('run %s' % self.fname)
331 _ip.magic('run %s' % self.fname)
332 file2 = _ip.user_ns.get('__file__', _missing)
332 file2 = _ip.user_ns.get('__file__', _missing)
333
333
334 # Check that __file__ was equal to the filename in the script's
334 # Check that __file__ was equal to the filename in the script's
335 # namespace.
335 # namespace.
336 nt.assert_equal(_ip.user_ns['t'], self.fname)
336 nt.assert_equal(_ip.user_ns['t'], self.fname)
337
337
338 # Check that __file__ was not leaked back into user_ns.
338 # Check that __file__ was not leaked back into user_ns.
339 nt.assert_equal(file1, file2)
339 nt.assert_equal(file1, file2)
340
340
341 def test_run_ipy_file_attribute(self):
341 def test_run_ipy_file_attribute(self):
342 """Test handling of `__file__` attribute in `%run <file.ipy>`."""
342 """Test handling of `__file__` attribute in `%run <file.ipy>`."""
343 src = "t = __file__\n"
343 src = "t = __file__\n"
344 self.mktmp(src, ext='.ipy')
344 self.mktmp(src, ext='.ipy')
345 _missing = object()
345 _missing = object()
346 file1 = _ip.user_ns.get('__file__', _missing)
346 file1 = _ip.user_ns.get('__file__', _missing)
347 _ip.magic('run %s' % self.fname)
347 _ip.magic('run %s' % self.fname)
348 file2 = _ip.user_ns.get('__file__', _missing)
348 file2 = _ip.user_ns.get('__file__', _missing)
349
349
350 # Check that __file__ was equal to the filename in the script's
350 # Check that __file__ was equal to the filename in the script's
351 # namespace.
351 # namespace.
352 nt.assert_equal(_ip.user_ns['t'], self.fname)
352 nt.assert_equal(_ip.user_ns['t'], self.fname)
353
353
354 # Check that __file__ was not leaked back into user_ns.
354 # Check that __file__ was not leaked back into user_ns.
355 nt.assert_equal(file1, file2)
355 nt.assert_equal(file1, file2)
356
356
357 def test_run_formatting(self):
357 def test_run_formatting(self):
358 """ Test that %run -t -N<N> does not raise a TypeError for N > 1."""
358 """ Test that %run -t -N<N> does not raise a TypeError for N > 1."""
359 src = "pass"
359 src = "pass"
360 self.mktmp(src)
360 self.mktmp(src)
361 _ip.magic('run -t -N 1 %s' % self.fname)
361 _ip.magic('run -t -N 1 %s' % self.fname)
362 _ip.magic('run -t -N 10 %s' % self.fname)
362 _ip.magic('run -t -N 10 %s' % self.fname)
363
363
364 def test_ignore_sys_exit(self):
364 def test_ignore_sys_exit(self):
365 """Test the -e option to ignore sys.exit()"""
365 """Test the -e option to ignore sys.exit()"""
366 src = "import sys; sys.exit(1)"
366 src = "import sys; sys.exit(1)"
367 self.mktmp(src)
367 self.mktmp(src)
368 with tt.AssertPrints('SystemExit'):
368 with tt.AssertPrints('SystemExit'):
369 _ip.magic('run %s' % self.fname)
369 _ip.magic('run %s' % self.fname)
370
370
371 with tt.AssertNotPrints('SystemExit'):
371 with tt.AssertNotPrints('SystemExit'):
372 _ip.magic('run -e %s' % self.fname)
372 _ip.magic('run -e %s' % self.fname)
373
373
374 def test_run_nb(self):
375 """Test %run notebook.ipynb"""
376 from IPython.nbformat import current
377 nb = current.new_notebook(
378 worksheets=[
379 current.new_worksheet(cells=[
380 current.new_code_cell("answer=42")
381 ])
382 ]
383 )
384 src = current.writes(nb, 'json')
385 self.mktmp(src, ext='.ipynb')
386
387 _ip.magic("run %s" % self.fname)
388
389 nt.assert_equal(_ip.user_ns['answer'], 42)
390
374
391
375
392
376 class TestMagicRunWithPackage(unittest.TestCase):
393 class TestMagicRunWithPackage(unittest.TestCase):
377
394
378 def writefile(self, name, content):
395 def writefile(self, name, content):
379 path = os.path.join(self.tempdir.name, name)
396 path = os.path.join(self.tempdir.name, name)
380 d = os.path.dirname(path)
397 d = os.path.dirname(path)
381 if not os.path.isdir(d):
398 if not os.path.isdir(d):
382 os.makedirs(d)
399 os.makedirs(d)
383 with open(path, 'w') as f:
400 with open(path, 'w') as f:
384 f.write(textwrap.dedent(content))
401 f.write(textwrap.dedent(content))
385
402
386 def setUp(self):
403 def setUp(self):
387 self.package = package = 'tmp{0}'.format(repr(random.random())[2:])
404 self.package = package = 'tmp{0}'.format(repr(random.random())[2:])
388 """Temporary valid python package name."""
405 """Temporary valid python package name."""
389
406
390 self.value = int(random.random() * 10000)
407 self.value = int(random.random() * 10000)
391
408
392 self.tempdir = TemporaryDirectory()
409 self.tempdir = TemporaryDirectory()
393 self.__orig_cwd = py3compat.getcwd()
410 self.__orig_cwd = py3compat.getcwd()
394 sys.path.insert(0, self.tempdir.name)
411 sys.path.insert(0, self.tempdir.name)
395
412
396 self.writefile(os.path.join(package, '__init__.py'), '')
413 self.writefile(os.path.join(package, '__init__.py'), '')
397 self.writefile(os.path.join(package, 'sub.py'), """
414 self.writefile(os.path.join(package, 'sub.py'), """
398 x = {0!r}
415 x = {0!r}
399 """.format(self.value))
416 """.format(self.value))
400 self.writefile(os.path.join(package, 'relative.py'), """
417 self.writefile(os.path.join(package, 'relative.py'), """
401 from .sub import x
418 from .sub import x
402 """)
419 """)
403 self.writefile(os.path.join(package, 'absolute.py'), """
420 self.writefile(os.path.join(package, 'absolute.py'), """
404 from {0}.sub import x
421 from {0}.sub import x
405 """.format(package))
422 """.format(package))
406
423
407 def tearDown(self):
424 def tearDown(self):
408 os.chdir(self.__orig_cwd)
425 os.chdir(self.__orig_cwd)
409 sys.path[:] = [p for p in sys.path if p != self.tempdir.name]
426 sys.path[:] = [p for p in sys.path if p != self.tempdir.name]
410 self.tempdir.cleanup()
427 self.tempdir.cleanup()
411
428
412 def check_run_submodule(self, submodule, opts=''):
429 def check_run_submodule(self, submodule, opts=''):
413 _ip.user_ns.pop('x', None)
430 _ip.user_ns.pop('x', None)
414 _ip.magic('run {2} -m {0}.{1}'.format(self.package, submodule, opts))
431 _ip.magic('run {2} -m {0}.{1}'.format(self.package, submodule, opts))
415 self.assertEqual(_ip.user_ns['x'], self.value,
432 self.assertEqual(_ip.user_ns['x'], self.value,
416 'Variable `x` is not loaded from module `{0}`.'
433 'Variable `x` is not loaded from module `{0}`.'
417 .format(submodule))
434 .format(submodule))
418
435
419 def test_run_submodule_with_absolute_import(self):
436 def test_run_submodule_with_absolute_import(self):
420 self.check_run_submodule('absolute')
437 self.check_run_submodule('absolute')
421
438
422 def test_run_submodule_with_relative_import(self):
439 def test_run_submodule_with_relative_import(self):
423 """Run submodule that has a relative import statement (#2727)."""
440 """Run submodule that has a relative import statement (#2727)."""
424 self.check_run_submodule('relative')
441 self.check_run_submodule('relative')
425
442
426 def test_prun_submodule_with_absolute_import(self):
443 def test_prun_submodule_with_absolute_import(self):
427 self.check_run_submodule('absolute', '-p')
444 self.check_run_submodule('absolute', '-p')
428
445
429 def test_prun_submodule_with_relative_import(self):
446 def test_prun_submodule_with_relative_import(self):
430 self.check_run_submodule('relative', '-p')
447 self.check_run_submodule('relative', '-p')
431
448
432 def with_fake_debugger(func):
449 def with_fake_debugger(func):
433 @functools.wraps(func)
450 @functools.wraps(func)
434 def wrapper(*args, **kwds):
451 def wrapper(*args, **kwds):
435 with tt.monkeypatch(debugger.Pdb, 'run', staticmethod(eval)):
452 with tt.monkeypatch(debugger.Pdb, 'run', staticmethod(eval)):
436 return func(*args, **kwds)
453 return func(*args, **kwds)
437 return wrapper
454 return wrapper
438
455
439 @with_fake_debugger
456 @with_fake_debugger
440 def test_debug_run_submodule_with_absolute_import(self):
457 def test_debug_run_submodule_with_absolute_import(self):
441 self.check_run_submodule('absolute', '-d')
458 self.check_run_submodule('absolute', '-d')
442
459
443 @with_fake_debugger
460 @with_fake_debugger
444 def test_debug_run_submodule_with_relative_import(self):
461 def test_debug_run_submodule_with_relative_import(self):
445 self.check_run_submodule('relative', '-d')
462 self.check_run_submodule('relative', '-d')
446
463
447 def test_run__name__():
464 def test_run__name__():
448 with TemporaryDirectory() as td:
465 with TemporaryDirectory() as td:
449 path = pjoin(td, 'foo.py')
466 path = pjoin(td, 'foo.py')
450 with open(path, 'w') as f:
467 with open(path, 'w') as f:
451 f.write("q = __name__")
468 f.write("q = __name__")
452
469
453 _ip.user_ns.pop('q', None)
470 _ip.user_ns.pop('q', None)
454 _ip.magic('run {}'.format(path))
471 _ip.magic('run {}'.format(path))
455 nt.assert_equal(_ip.user_ns.pop('q'), '__main__')
472 nt.assert_equal(_ip.user_ns.pop('q'), '__main__')
456
473
457 _ip.magic('run -n {}'.format(path))
474 _ip.magic('run -n {}'.format(path))
458 nt.assert_equal(_ip.user_ns.pop('q'), 'foo')
475 nt.assert_equal(_ip.user_ns.pop('q'), 'foo')
General Comments 0
You need to be logged in to leave comments. Login now