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