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