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