##// END OF EJS Templates
rlmv - Added test for issue #2784...
Robert Marchman -
Show More
@@ -1,332 +1,339 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 os
17 17 import sys
18 18 import tempfile
19 19
20 20 import nose.tools as nt
21 21 from nose import SkipTest
22 22
23 23 from IPython.testing import decorators as dec
24 24 from IPython.testing import tools as tt
25 25 from IPython.utils import py3compat
26 26
27 27 #-----------------------------------------------------------------------------
28 28 # Test functions begin
29 29 #-----------------------------------------------------------------------------
30 30
31 31 def doctest_refbug():
32 32 """Very nasty problem with references held by multiple runs of a script.
33 33 See: https://github.com/ipython/ipython/issues/141
34 34
35 35 In [1]: _ip.clear_main_mod_cache()
36 36 # random
37 37
38 38 In [2]: %run refbug
39 39
40 40 In [3]: call_f()
41 41 lowercased: hello
42 42
43 43 In [4]: %run refbug
44 44
45 45 In [5]: call_f()
46 46 lowercased: hello
47 47 lowercased: hello
48 48 """
49 49
50 50
51 51 def doctest_run_builtins():
52 52 r"""Check that %run doesn't damage __builtins__.
53 53
54 54 In [1]: import tempfile
55 55
56 56 In [2]: bid1 = id(__builtins__)
57 57
58 58 In [3]: fname = tempfile.mkstemp('.py')[1]
59 59
60 60 In [3]: f = open(fname,'w')
61 61
62 62 In [4]: dummy= f.write('pass\n')
63 63
64 64 In [5]: f.flush()
65 65
66 66 In [6]: t1 = type(__builtins__)
67 67
68 68 In [7]: %run $fname
69 69
70 70 In [7]: f.close()
71 71
72 72 In [8]: bid2 = id(__builtins__)
73 73
74 74 In [9]: t2 = type(__builtins__)
75 75
76 76 In [10]: t1 == t2
77 77 Out[10]: True
78 78
79 79 In [10]: bid1 == bid2
80 80 Out[10]: True
81 81
82 82 In [12]: try:
83 83 ....: os.unlink(fname)
84 84 ....: except:
85 85 ....: pass
86 86 ....:
87 87 """
88 88
89 89
90 90 def doctest_run_option_parser():
91 91 r"""Test option parser in %run.
92 92
93 93 In [1]: %run print_argv.py
94 94 []
95 95
96 96 In [2]: %run print_argv.py print*.py
97 97 ['print_argv.py']
98 98
99 99 In [3]: %run -G print_argv.py print*.py
100 100 ['print*.py']
101 101
102 102 """
103 103
104 104
105 105 @dec.skip_win32
106 106 def doctest_run_option_parser_for_posix():
107 107 r"""Test option parser in %run (Linux/OSX specific).
108 108
109 109 You need double quote to escape glob in POSIX systems:
110 110
111 111 In [1]: %run print_argv.py print\\*.py
112 112 ['print*.py']
113 113
114 114 You can't use quote to escape glob in POSIX systems:
115 115
116 116 In [2]: %run print_argv.py 'print*.py'
117 117 ['print_argv.py']
118 118
119 119 """
120 120
121 121
122 122 @dec.skip_if_not_win32
123 123 def doctest_run_option_parser_for_windows():
124 124 r"""Test option parser in %run (Windows specific).
125 125
126 126 In Windows, you can't escape ``*` `by backslash:
127 127
128 128 In [1]: %run print_argv.py print\\*.py
129 129 ['print\\*.py']
130 130
131 131 You can use quote to escape glob:
132 132
133 133 In [2]: %run print_argv.py 'print*.py'
134 134 ['print*.py']
135 135
136 136 """
137 137
138 138
139 139 @py3compat.doctest_refactor_print
140 140 def doctest_reset_del():
141 141 """Test that resetting doesn't cause errors in __del__ methods.
142 142
143 143 In [2]: class A(object):
144 144 ...: def __del__(self):
145 145 ...: print str("Hi")
146 146 ...:
147 147
148 148 In [3]: a = A()
149 149
150 150 In [4]: get_ipython().reset()
151 151 Hi
152 152
153 153 In [5]: 1+1
154 154 Out[5]: 2
155 155 """
156 156
157 157 # For some tests, it will be handy to organize them in a class with a common
158 158 # setup that makes a temp file
159 159
160 160 class TestMagicRunPass(tt.TempFileMixin):
161 161
162 162 def setup(self):
163 163 """Make a valid python temp file."""
164 164 self.mktmp('pass\n')
165 165
166 166 def run_tmpfile(self):
167 167 _ip = get_ipython()
168 168 # This fails on Windows if self.tmpfile.name has spaces or "~" in it.
169 169 # See below and ticket https://bugs.launchpad.net/bugs/366353
170 170 _ip.magic('run %s' % self.fname)
171 171
172 172 def run_tmpfile_p(self):
173 173 _ip = get_ipython()
174 174 # This fails on Windows if self.tmpfile.name has spaces or "~" in it.
175 175 # See below and ticket https://bugs.launchpad.net/bugs/366353
176 176 _ip.magic('run -p %s' % self.fname)
177 177
178 178 def test_builtins_id(self):
179 179 """Check that %run doesn't damage __builtins__ """
180 180 _ip = get_ipython()
181 181 # Test that the id of __builtins__ is not modified by %run
182 182 bid1 = id(_ip.user_ns['__builtins__'])
183 183 self.run_tmpfile()
184 184 bid2 = id(_ip.user_ns['__builtins__'])
185 185 nt.assert_equal(bid1, bid2)
186 186
187 187 def test_builtins_type(self):
188 188 """Check that the type of __builtins__ doesn't change with %run.
189 189
190 190 However, the above could pass if __builtins__ was already modified to
191 191 be a dict (it should be a module) by a previous use of %run. So we
192 192 also check explicitly that it really is a module:
193 193 """
194 194 _ip = get_ipython()
195 195 self.run_tmpfile()
196 196 nt.assert_equal(type(_ip.user_ns['__builtins__']),type(sys))
197 197
198 198 def test_prompts(self):
199 199 """Test that prompts correctly generate after %run"""
200 200 self.run_tmpfile()
201 201 _ip = get_ipython()
202 202 p2 = _ip.prompt_manager.render('in2').strip()
203 203 nt.assert_equal(p2[:3], '...')
204 204
205 205 def test_run_profile( self ):
206 206 """Test that the option -p, which invokes the profiler, do not
207 207 crash by invoking execfile"""
208 208 _ip = get_ipython()
209 209 self.run_tmpfile_p()
210 210
211 211
212 212 class TestMagicRunSimple(tt.TempFileMixin):
213 213
214 214 def test_simpledef(self):
215 215 """Test that simple class definitions work."""
216 216 src = ("class foo: pass\n"
217 217 "def f(): return foo()")
218 218 self.mktmp(src)
219 219 _ip.magic('run %s' % self.fname)
220 220 _ip.run_cell('t = isinstance(f(), foo)')
221 221 nt.assert_true(_ip.user_ns['t'])
222 222
223 223 def test_obj_del(self):
224 224 """Test that object's __del__ methods are called on exit."""
225 225 if sys.platform == 'win32':
226 226 try:
227 227 import win32api
228 228 except ImportError:
229 229 raise SkipTest("Test requires pywin32")
230 230 src = ("class A(object):\n"
231 231 " def __del__(self):\n"
232 232 " print 'object A deleted'\n"
233 233 "a = A()\n")
234 234 self.mktmp(py3compat.doctest_refactor_print(src))
235 235 if dec.module_not_available('sqlite3'):
236 236 err = 'WARNING: IPython History requires SQLite, your history will not be saved\n'
237 237 else:
238 238 err = None
239 239 tt.ipexec_validate(self.fname, 'object A deleted', err)
240 240
241 241 @dec.skip_known_failure
242 242 def test_aggressive_namespace_cleanup(self):
243 243 """Test that namespace cleanup is not too aggressive GH-238
244 244
245 245 Returning from another run magic deletes the namespace"""
246 246 # see ticket https://github.com/ipython/ipython/issues/238
247 247 class secondtmp(tt.TempFileMixin): pass
248 248 empty = secondtmp()
249 249 empty.mktmp('')
250 250 src = ("ip = get_ipython()\n"
251 251 "for i in range(5):\n"
252 252 " try:\n"
253 253 " ip.magic('run %s')\n"
254 254 " except NameError as e:\n"
255 255 " print i;break\n" % empty.fname)
256 256 self.mktmp(py3compat.doctest_refactor_print(src))
257 257 _ip.magic('run %s' % self.fname)
258 258 _ip.run_cell('ip == get_ipython()')
259 259 nt.assert_equal(_ip.user_ns['i'], 5)
260 260
261 261 @dec.skip_win32
262 262 def test_tclass(self):
263 263 mydir = os.path.dirname(__file__)
264 264 tc = os.path.join(mydir, 'tclass')
265 265 src = ("%%run '%s' C-first\n"
266 266 "%%run '%s' C-second\n"
267 267 "%%run '%s' C-third\n") % (tc, tc, tc)
268 268 self.mktmp(src, '.ipy')
269 269 out = """\
270 270 ARGV 1-: ['C-first']
271 271 ARGV 1-: ['C-second']
272 272 tclass.py: deleting object: C-first
273 273 ARGV 1-: ['C-third']
274 274 tclass.py: deleting object: C-second
275 275 tclass.py: deleting object: C-third
276 276 """
277 277 if dec.module_not_available('sqlite3'):
278 278 err = 'WARNING: IPython History requires SQLite, your history will not be saved\n'
279 279 else:
280 280 err = None
281 281 tt.ipexec_validate(self.fname, out, err)
282 282
283 283 def test_run_i_after_reset(self):
284 284 """Check that %run -i still works after %reset (gh-693)"""
285 285 src = "yy = zz\n"
286 286 self.mktmp(src)
287 287 _ip.run_cell("zz = 23")
288 288 _ip.magic('run -i %s' % self.fname)
289 289 nt.assert_equal(_ip.user_ns['yy'], 23)
290 290 _ip.magic('reset -f')
291 291 _ip.run_cell("zz = 23")
292 292 _ip.magic('run -i %s' % self.fname)
293 293 nt.assert_equal(_ip.user_ns['yy'], 23)
294 294
295 295 def test_unicode(self):
296 296 """Check that files in odd encodings are accepted."""
297 297 mydir = os.path.dirname(__file__)
298 298 na = os.path.join(mydir, 'nonascii.py')
299 299 _ip.magic('run "%s"' % na)
300 300 nt.assert_equal(_ip.user_ns['u'], u'ΠŽΡ‚β„–Π€')
301 301
302 302 def test_run_py_file_attribute(self):
303 303 """Test handling of `__file__` attribute in `%run <file>.py`."""
304 304 src = "t = __file__\n"
305 305 self.mktmp(src)
306 306 _missing = object()
307 307 file1 = _ip.user_ns.get('__file__', _missing)
308 308 _ip.magic('run %s' % self.fname)
309 309 file2 = _ip.user_ns.get('__file__', _missing)
310 310
311 311 # Check that __file__ was equal to the filename in the script's
312 312 # namespace.
313 313 nt.assert_equal(_ip.user_ns['t'], self.fname)
314 314
315 315 # Check that __file__ was not leaked back into user_ns.
316 316 nt.assert_equal(file1, file2)
317 317
318 318 def test_run_ipy_file_attribute(self):
319 319 """Test handling of `__file__` attribute in `%run <file.ipy>`."""
320 320 src = "t = __file__\n"
321 321 self.mktmp(src, ext='.ipy')
322 322 _missing = object()
323 323 file1 = _ip.user_ns.get('__file__', _missing)
324 324 _ip.magic('run %s' % self.fname)
325 325 file2 = _ip.user_ns.get('__file__', _missing)
326 326
327 327 # Check that __file__ was equal to the filename in the script's
328 328 # namespace.
329 329 nt.assert_equal(_ip.user_ns['t'], self.fname)
330 330
331 331 # Check that __file__ was not leaked back into user_ns.
332 332 nt.assert_equal(file1, file2)
333
334 def test_run_formatting(self):
335 """ Test that %run -t -N<N> does not raise a TypeError for N > 1."""
336 src = "pass"
337 self.mktmp(src)
338 _ip.magic('run -t -N 1 %s' % self.fname)
339 _ip.magic('run -t -N 10 %s' % self.fname)
General Comments 0
You need to be logged in to leave comments. Login now