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