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