##// END OF EJS Templates
Add test for `__file__` behavior in `%run`.
Bradley M. Froehle -
Show More
@@ -1,250 +1,282 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 @py3compat.doctest_refactor_print
90 90 def doctest_reset_del():
91 91 """Test that resetting doesn't cause errors in __del__ methods.
92 92
93 93 In [2]: class A(object):
94 94 ...: def __del__(self):
95 95 ...: print str("Hi")
96 96 ...:
97 97
98 98 In [3]: a = A()
99 99
100 100 In [4]: get_ipython().reset()
101 101 Hi
102 102
103 103 In [5]: 1+1
104 104 Out[5]: 2
105 105 """
106 106
107 107 # For some tests, it will be handy to organize them in a class with a common
108 108 # setup that makes a temp file
109 109
110 110 class TestMagicRunPass(tt.TempFileMixin):
111 111
112 112 def setup(self):
113 113 """Make a valid python temp file."""
114 114 self.mktmp('pass\n')
115 115
116 116 def run_tmpfile(self):
117 117 _ip = get_ipython()
118 118 # This fails on Windows if self.tmpfile.name has spaces or "~" in it.
119 119 # See below and ticket https://bugs.launchpad.net/bugs/366353
120 120 _ip.magic('run %s' % self.fname)
121 121
122 122 def run_tmpfile_p(self):
123 123 _ip = get_ipython()
124 124 # This fails on Windows if self.tmpfile.name has spaces or "~" in it.
125 125 # See below and ticket https://bugs.launchpad.net/bugs/366353
126 126 _ip.magic('run -p %s' % self.fname)
127 127
128 128 def test_builtins_id(self):
129 129 """Check that %run doesn't damage __builtins__ """
130 130 _ip = get_ipython()
131 131 # Test that the id of __builtins__ is not modified by %run
132 132 bid1 = id(_ip.user_ns['__builtins__'])
133 133 self.run_tmpfile()
134 134 bid2 = id(_ip.user_ns['__builtins__'])
135 135 nt.assert_equal(bid1, bid2)
136 136
137 137 def test_builtins_type(self):
138 138 """Check that the type of __builtins__ doesn't change with %run.
139 139
140 140 However, the above could pass if __builtins__ was already modified to
141 141 be a dict (it should be a module) by a previous use of %run. So we
142 142 also check explicitly that it really is a module:
143 143 """
144 144 _ip = get_ipython()
145 145 self.run_tmpfile()
146 146 nt.assert_equal(type(_ip.user_ns['__builtins__']),type(sys))
147 147
148 148 def test_prompts(self):
149 149 """Test that prompts correctly generate after %run"""
150 150 self.run_tmpfile()
151 151 _ip = get_ipython()
152 152 p2 = _ip.prompt_manager.render('in2').strip()
153 153 nt.assert_equal(p2[:3], '...')
154 154
155 155 def test_run_profile( self ):
156 156 """Test that the option -p, which invokes the profiler, do not
157 157 crash by invoking execfile"""
158 158 _ip = get_ipython()
159 159 self.run_tmpfile_p()
160 160
161 161
162 162 class TestMagicRunSimple(tt.TempFileMixin):
163 163
164 164 def test_simpledef(self):
165 165 """Test that simple class definitions work."""
166 166 src = ("class foo: pass\n"
167 167 "def f(): return foo()")
168 168 self.mktmp(src)
169 169 _ip.magic('run %s' % self.fname)
170 170 _ip.run_cell('t = isinstance(f(), foo)')
171 171 nt.assert_true(_ip.user_ns['t'])
172 172
173 173 def test_obj_del(self):
174 174 """Test that object's __del__ methods are called on exit."""
175 175 if sys.platform == 'win32':
176 176 try:
177 177 import win32api
178 178 except ImportError:
179 179 raise SkipTest("Test requires pywin32")
180 180 src = ("class A(object):\n"
181 181 " def __del__(self):\n"
182 182 " print 'object A deleted'\n"
183 183 "a = A()\n")
184 184 self.mktmp(py3compat.doctest_refactor_print(src))
185 185 if dec.module_not_available('sqlite3'):
186 186 err = 'WARNING: IPython History requires SQLite, your history will not be saved\n'
187 187 else:
188 188 err = None
189 189 tt.ipexec_validate(self.fname, 'object A deleted', err)
190 190
191 191 @dec.skip_known_failure
192 192 def test_aggressive_namespace_cleanup(self):
193 193 """Test that namespace cleanup is not too aggressive GH-238
194 194
195 195 Returning from another run magic deletes the namespace"""
196 196 # see ticket https://github.com/ipython/ipython/issues/238
197 197 class secondtmp(tt.TempFileMixin): pass
198 198 empty = secondtmp()
199 199 empty.mktmp('')
200 200 src = ("ip = get_ipython()\n"
201 201 "for i in range(5):\n"
202 202 " try:\n"
203 203 " ip.magic('run %s')\n"
204 204 " except NameError as e:\n"
205 205 " print i;break\n" % empty.fname)
206 206 self.mktmp(py3compat.doctest_refactor_print(src))
207 207 _ip.magic('run %s' % self.fname)
208 208 _ip.run_cell('ip == get_ipython()')
209 209 nt.assert_equal(_ip.user_ns['i'], 5)
210 210
211 211 @dec.skip_win32
212 212 def test_tclass(self):
213 213 mydir = os.path.dirname(__file__)
214 214 tc = os.path.join(mydir, 'tclass')
215 215 src = ("%%run '%s' C-first\n"
216 216 "%%run '%s' C-second\n"
217 217 "%%run '%s' C-third\n") % (tc, tc, tc)
218 218 self.mktmp(src, '.ipy')
219 219 out = """\
220 220 ARGV 1-: ['C-first']
221 221 ARGV 1-: ['C-second']
222 222 tclass.py: deleting object: C-first
223 223 ARGV 1-: ['C-third']
224 224 tclass.py: deleting object: C-second
225 225 tclass.py: deleting object: C-third
226 226 """
227 227 if dec.module_not_available('sqlite3'):
228 228 err = 'WARNING: IPython History requires SQLite, your history will not be saved\n'
229 229 else:
230 230 err = None
231 231 tt.ipexec_validate(self.fname, out, err)
232 232
233 233 def test_run_i_after_reset(self):
234 234 """Check that %run -i still works after %reset (gh-693)"""
235 235 src = "yy = zz\n"
236 236 self.mktmp(src)
237 237 _ip.run_cell("zz = 23")
238 238 _ip.magic('run -i %s' % self.fname)
239 239 nt.assert_equal(_ip.user_ns['yy'], 23)
240 240 _ip.magic('reset -f')
241 241 _ip.run_cell("zz = 23")
242 242 _ip.magic('run -i %s' % self.fname)
243 243 nt.assert_equal(_ip.user_ns['yy'], 23)
244 244
245 245 def test_unicode(self):
246 246 """Check that files in odd encodings are accepted."""
247 247 mydir = os.path.dirname(__file__)
248 248 na = os.path.join(mydir, 'nonascii.py')
249 249 _ip.magic('run "%s"' % na)
250 250 nt.assert_equal(_ip.user_ns['u'], u'Ўт№Ф')
251
252 def test_run_py_file_attribute(self):
253 """Test handling of `__file__` attribute in `%run <file>.py`."""
254 src = "t = __file__\n"
255 self.mktmp(src)
256 _missing = object()
257 file1 = _ip.user_ns.get('__file__', _missing)
258 _ip.magic('run %s' % self.fname)
259 file2 = _ip.user_ns.get('__file__', _missing)
260
261 # Check that __file__ was equal to the filename in the script's
262 # namespace.
263 nt.assert_equal(_ip.user_ns['t'], self.fname)
264
265 # Check that __file__ was not leaked back into user_ns.
266 nt.assert_equal(file1, file2)
267
268 def test_run_ipy_file_attribute(self):
269 """Test handling of `__file__` attribute in `%run <file.ipy>`."""
270 src = "t = __file__\n"
271 self.mktmp(src, ext='.ipy')
272 _missing = object()
273 file1 = _ip.user_ns.get('__file__', _missing)
274 _ip.magic('run %s' % self.fname)
275 file2 = _ip.user_ns.get('__file__', _missing)
276
277 # Check that __file__ was equal to the filename in the script's
278 # namespace.
279 nt.assert_equal(_ip.user_ns['t'], self.fname)
280
281 # Check that __file__ was not leaked back into user_ns.
282 nt.assert_equal(file1, file2)
General Comments 0
You need to be logged in to leave comments. Login now