##// END OF EJS Templates
test for GH-238 %run's aggressive name cleaning
Paul Ivanov -
Show More
@@ -1,186 +1,205 b''
1 1 """Tests for code execution (%run and related), which is particularly tricky.
2 2
3 3 Because of how %run manages namespaces, and the fact that we are trying here to
4 4 verify subtle object deletion and reference counting issues, the %run tests
5 5 will be kept in this separate file. This makes it easier to aggregate in one
6 6 place the tricks needed to handle it; most other magics are much easier to test
7 7 and we do so in a common test_magic file.
8 8 """
9 9 from __future__ import absolute_import
10 10
11 11 #-----------------------------------------------------------------------------
12 12 # Imports
13 13 #-----------------------------------------------------------------------------
14 14
15 15 import os
16 16 import sys
17 17 import tempfile
18 18
19 19 import nose.tools as nt
20 20
21 21 from IPython.testing import decorators as dec
22 22 from IPython.testing import tools as tt
23 23
24 24 #-----------------------------------------------------------------------------
25 25 # Test functions begin
26 26 #-----------------------------------------------------------------------------
27 27
28 28 def doctest_refbug():
29 29 """Very nasty problem with references held by multiple runs of a script.
30 30 See: https://bugs.launchpad.net/ipython/+bug/269966
31 31
32 32 In [1]: _ip.clear_main_mod_cache()
33 33 # random
34 34
35 35 In [2]: %run refbug
36 36
37 37 In [3]: call_f()
38 38 lowercased: hello
39 39
40 40 In [4]: %run refbug
41 41
42 42 In [5]: call_f()
43 43 lowercased: hello
44 44 lowercased: hello
45 45 """
46 46
47 47
48 48 def doctest_run_builtins():
49 49 r"""Check that %run doesn't damage __builtins__.
50 50
51 51 In [1]: import tempfile
52 52
53 53 In [2]: bid1 = id(__builtins__)
54 54
55 55 In [3]: fname = tempfile.mkstemp('.py')[1]
56 56
57 57 In [3]: f = open(fname,'w')
58 58
59 59 In [4]: f.write('pass\n')
60 60
61 61 In [5]: f.flush()
62 62
63 63 In [6]: t1 = type(__builtins__)
64 64
65 65 In [7]: %run $fname
66 66
67 67 In [7]: f.close()
68 68
69 69 In [8]: bid2 = id(__builtins__)
70 70
71 71 In [9]: t2 = type(__builtins__)
72 72
73 73 In [10]: t1 == t2
74 74 Out[10]: True
75 75
76 76 In [10]: bid1 == bid2
77 77 Out[10]: True
78 78
79 79 In [12]: try:
80 80 ....: os.unlink(fname)
81 81 ....: except:
82 82 ....: pass
83 83 ....:
84 84 """
85 85
86 86 def doctest_reset_del():
87 87 """Test that resetting doesn't cause errors in __del__ methods.
88 88
89 89 In [2]: class A(object):
90 90 ...: def __del__(self):
91 91 ...: print str("Hi")
92 92 ...:
93 93
94 94 In [3]: a = A()
95 95
96 96 In [4]: get_ipython().reset()
97 97 Hi
98 98
99 99 In [5]: 1+1
100 100 Out[5]: 2
101 101 """
102 102
103 103 # For some tests, it will be handy to organize them in a class with a common
104 104 # setup that makes a temp file
105 105
106 106 class TestMagicRunPass(tt.TempFileMixin):
107 107
108 108 def setup(self):
109 109 """Make a valid python temp file."""
110 110 self.mktmp('pass\n')
111 111
112 112 def run_tmpfile(self):
113 113 _ip = get_ipython()
114 114 # This fails on Windows if self.tmpfile.name has spaces or "~" in it.
115 115 # See below and ticket https://bugs.launchpad.net/bugs/366353
116 116 _ip.magic('run %s' % self.fname)
117 117
118 118 def test_builtins_id(self):
119 119 """Check that %run doesn't damage __builtins__ """
120 120 _ip = get_ipython()
121 121 # Test that the id of __builtins__ is not modified by %run
122 122 bid1 = id(_ip.user_ns['__builtins__'])
123 123 self.run_tmpfile()
124 124 bid2 = id(_ip.user_ns['__builtins__'])
125 125 tt.assert_equals(bid1, bid2)
126 126
127 127 def test_builtins_type(self):
128 128 """Check that the type of __builtins__ doesn't change with %run.
129 129
130 130 However, the above could pass if __builtins__ was already modified to
131 131 be a dict (it should be a module) by a previous use of %run. So we
132 132 also check explicitly that it really is a module:
133 133 """
134 134 _ip = get_ipython()
135 135 self.run_tmpfile()
136 136 tt.assert_equals(type(_ip.user_ns['__builtins__']),type(sys))
137 137
138 138 def test_prompts(self):
139 139 """Test that prompts correctly generate after %run"""
140 140 self.run_tmpfile()
141 141 _ip = get_ipython()
142 142 p2 = str(_ip.displayhook.prompt2).strip()
143 143 nt.assert_equals(p2[:3], '...')
144 144
145 145
146 146 class TestMagicRunSimple(tt.TempFileMixin):
147 147
148 148 def test_simpledef(self):
149 149 """Test that simple class definitions work."""
150 150 src = ("class foo: pass\n"
151 151 "def f(): return foo()")
152 152 self.mktmp(src)
153 153 _ip.magic('run %s' % self.fname)
154 154 _ip.runlines('t = isinstance(f(), foo)')
155 155 nt.assert_true(_ip.user_ns['t'])
156 156
157 157 # We have to skip these in win32 because getoutputerr() crashes,
158 158 # due to the fact that subprocess does not support close_fds when
159 159 # redirecting stdout/err. So unless someone who knows more tells us how to
160 160 # implement getoutputerr() in win32, we're stuck avoiding these.
161 161 @dec.skip_win32
162 162 def test_obj_del(self):
163 163 """Test that object's __del__ methods are called on exit."""
164 164
165 165 # This test is known to fail on win32.
166 166 # See ticket https://bugs.launchpad.net/bugs/366334
167 167 src = ("class A(object):\n"
168 168 " def __del__(self):\n"
169 169 " print 'object A deleted'\n"
170 170 "a = A()\n")
171 171 self.mktmp(src)
172 172 tt.ipexec_validate(self.fname, 'object A deleted')
173
174 def test_aggressive_namespace_cleanup(self):
175 """Test that namespace cleanup is not too aggressive GH-238
176
177 returning from another run magic deletes the namespace"""
178 # see ticket https://github.com/ipython/ipython/issues/238
179 class secondtmp(tt.TempFileMixin): pass
180 empty = secondtmp()
181 empty.mktmp('')
182 src = ("ip = get_ipython()\n"
183 "for i in range(5):\n"
184 " try:\n"
185 " ip.magic('run %s')\n"
186 " except NameError, e:\n"
187 " print i;break\n" % empty.fname)
188 self.mktmp(src)
189 _ip.magic('run %s' % self.fname)
190 _ip.runlines('ip == get_ipython()')
191 tt.assert_equals(_ip.user_ns['i'], 5)
173 192
174 193 @dec.skip_win32
175 194 def test_tclass(self):
176 195 mydir = os.path.dirname(__file__)
177 196 tc = os.path.join(mydir, 'tclass')
178 197 src = ("%%run '%s' C-first\n"
179 198 "%%run '%s' C-second\n") % (tc, tc)
180 199 self.mktmp(src, '.ipy')
181 200 out = """\
182 201 ARGV 1-: [u'C-first']
183 202 ARGV 1-: [u'C-second']
184 203 tclass.py: deleting object: C-first
185 204 """
186 205 tt.ipexec_validate(self.fname, out)
General Comments 0
You need to be logged in to leave comments. Login now