##// END OF EJS Templates
[extensions][tests][autoreload] Remove nose
Samuel Gaist -
Show More
@@ -1,555 +1,554 b''
1 """Tests for autoreload extension.
1 """Tests for autoreload extension.
2 """
2 """
3 # -----------------------------------------------------------------------------
3 # -----------------------------------------------------------------------------
4 # Copyright (c) 2012 IPython Development Team.
4 # Copyright (c) 2012 IPython Development Team.
5 #
5 #
6 # Distributed under the terms of the Modified BSD License.
6 # Distributed under the terms of the Modified BSD License.
7 #
7 #
8 # The full license is in the file COPYING.txt, distributed with this software.
8 # The full license is in the file COPYING.txt, distributed with this software.
9 # -----------------------------------------------------------------------------
9 # -----------------------------------------------------------------------------
10
10
11 # -----------------------------------------------------------------------------
11 # -----------------------------------------------------------------------------
12 # Imports
12 # Imports
13 # -----------------------------------------------------------------------------
13 # -----------------------------------------------------------------------------
14
14
15 import os
15 import os
16 import sys
16 import sys
17 import tempfile
17 import tempfile
18 import textwrap
18 import textwrap
19 import shutil
19 import shutil
20 import random
20 import random
21 import time
21 import time
22 from io import StringIO
22 from io import StringIO
23
23
24 import nose.tools as nt
25 import IPython.testing.tools as tt
24 import IPython.testing.tools as tt
26
25
27 from unittest import TestCase
26 from unittest import TestCase
28
27
29 from IPython.extensions.autoreload import AutoreloadMagics
28 from IPython.extensions.autoreload import AutoreloadMagics
30 from IPython.core.events import EventManager, pre_run_cell
29 from IPython.core.events import EventManager, pre_run_cell
31
30
32 # -----------------------------------------------------------------------------
31 # -----------------------------------------------------------------------------
33 # Test fixture
32 # Test fixture
34 # -----------------------------------------------------------------------------
33 # -----------------------------------------------------------------------------
35
34
36 noop = lambda *a, **kw: None
35 noop = lambda *a, **kw: None
37
36
38
37
39 class FakeShell:
38 class FakeShell:
40 def __init__(self):
39 def __init__(self):
41 self.ns = {}
40 self.ns = {}
42 self.user_ns = self.ns
41 self.user_ns = self.ns
43 self.user_ns_hidden = {}
42 self.user_ns_hidden = {}
44 self.events = EventManager(self, {"pre_run_cell", pre_run_cell})
43 self.events = EventManager(self, {"pre_run_cell", pre_run_cell})
45 self.auto_magics = AutoreloadMagics(shell=self)
44 self.auto_magics = AutoreloadMagics(shell=self)
46 self.events.register("pre_run_cell", self.auto_magics.pre_run_cell)
45 self.events.register("pre_run_cell", self.auto_magics.pre_run_cell)
47
46
48 register_magics = set_hook = noop
47 register_magics = set_hook = noop
49
48
50 def run_code(self, code):
49 def run_code(self, code):
51 self.events.trigger("pre_run_cell")
50 self.events.trigger("pre_run_cell")
52 exec(code, self.user_ns)
51 exec(code, self.user_ns)
53 self.auto_magics.post_execute_hook()
52 self.auto_magics.post_execute_hook()
54
53
55 def push(self, items):
54 def push(self, items):
56 self.ns.update(items)
55 self.ns.update(items)
57
56
58 def magic_autoreload(self, parameter):
57 def magic_autoreload(self, parameter):
59 self.auto_magics.autoreload(parameter)
58 self.auto_magics.autoreload(parameter)
60
59
61 def magic_aimport(self, parameter, stream=None):
60 def magic_aimport(self, parameter, stream=None):
62 self.auto_magics.aimport(parameter, stream=stream)
61 self.auto_magics.aimport(parameter, stream=stream)
63 self.auto_magics.post_execute_hook()
62 self.auto_magics.post_execute_hook()
64
63
65
64
66 class Fixture(TestCase):
65 class Fixture(TestCase):
67 """Fixture for creating test module files"""
66 """Fixture for creating test module files"""
68
67
69 test_dir = None
68 test_dir = None
70 old_sys_path = None
69 old_sys_path = None
71 filename_chars = "abcdefghijklmopqrstuvwxyz0123456789"
70 filename_chars = "abcdefghijklmopqrstuvwxyz0123456789"
72
71
73 def setUp(self):
72 def setUp(self):
74 self.test_dir = tempfile.mkdtemp()
73 self.test_dir = tempfile.mkdtemp()
75 self.old_sys_path = list(sys.path)
74 self.old_sys_path = list(sys.path)
76 sys.path.insert(0, self.test_dir)
75 sys.path.insert(0, self.test_dir)
77 self.shell = FakeShell()
76 self.shell = FakeShell()
78
77
79 def tearDown(self):
78 def tearDown(self):
80 shutil.rmtree(self.test_dir)
79 shutil.rmtree(self.test_dir)
81 sys.path = self.old_sys_path
80 sys.path = self.old_sys_path
82
81
83 self.test_dir = None
82 self.test_dir = None
84 self.old_sys_path = None
83 self.old_sys_path = None
85 self.shell = None
84 self.shell = None
86
85
87 def get_module(self):
86 def get_module(self):
88 module_name = "tmpmod_" + "".join(random.sample(self.filename_chars, 20))
87 module_name = "tmpmod_" + "".join(random.sample(self.filename_chars, 20))
89 if module_name in sys.modules:
88 if module_name in sys.modules:
90 del sys.modules[module_name]
89 del sys.modules[module_name]
91 file_name = os.path.join(self.test_dir, module_name + ".py")
90 file_name = os.path.join(self.test_dir, module_name + ".py")
92 return module_name, file_name
91 return module_name, file_name
93
92
94 def write_file(self, filename, content):
93 def write_file(self, filename, content):
95 """
94 """
96 Write a file, and force a timestamp difference of at least one second
95 Write a file, and force a timestamp difference of at least one second
97
96
98 Notes
97 Notes
99 -----
98 -----
100 Python's .pyc files record the timestamp of their compilation
99 Python's .pyc files record the timestamp of their compilation
101 with a time resolution of one second.
100 with a time resolution of one second.
102
101
103 Therefore, we need to force a timestamp difference between .py
102 Therefore, we need to force a timestamp difference between .py
104 and .pyc, without having the .py file be timestamped in the
103 and .pyc, without having the .py file be timestamped in the
105 future, and without changing the timestamp of the .pyc file
104 future, and without changing the timestamp of the .pyc file
106 (because that is stored in the file). The only reliable way
105 (because that is stored in the file). The only reliable way
107 to achieve this seems to be to sleep.
106 to achieve this seems to be to sleep.
108 """
107 """
109 content = textwrap.dedent(content)
108 content = textwrap.dedent(content)
110 # Sleep one second + eps
109 # Sleep one second + eps
111 time.sleep(1.05)
110 time.sleep(1.05)
112
111
113 # Write
112 # Write
114 with open(filename, "w") as f:
113 with open(filename, "w") as f:
115 f.write(content)
114 f.write(content)
116
115
117 def new_module(self, code):
116 def new_module(self, code):
118 code = textwrap.dedent(code)
117 code = textwrap.dedent(code)
119 mod_name, mod_fn = self.get_module()
118 mod_name, mod_fn = self.get_module()
120 with open(mod_fn, "w") as f:
119 with open(mod_fn, "w") as f:
121 f.write(code)
120 f.write(code)
122 return mod_name, mod_fn
121 return mod_name, mod_fn
123
122
124
123
125 # -----------------------------------------------------------------------------
124 # -----------------------------------------------------------------------------
126 # Test automatic reloading
125 # Test automatic reloading
127 # -----------------------------------------------------------------------------
126 # -----------------------------------------------------------------------------
128
127
129
128
130 def pickle_get_current_class(obj):
129 def pickle_get_current_class(obj):
131 """
130 """
132 Original issue comes from pickle; hence the name.
131 Original issue comes from pickle; hence the name.
133 """
132 """
134 name = obj.__class__.__name__
133 name = obj.__class__.__name__
135 module_name = getattr(obj, "__module__", None)
134 module_name = getattr(obj, "__module__", None)
136 obj2 = sys.modules[module_name]
135 obj2 = sys.modules[module_name]
137 for subpath in name.split("."):
136 for subpath in name.split("."):
138 obj2 = getattr(obj2, subpath)
137 obj2 = getattr(obj2, subpath)
139 return obj2
138 return obj2
140
139
141
140
142 class TestAutoreload(Fixture):
141 class TestAutoreload(Fixture):
143 def test_reload_enums(self):
142 def test_reload_enums(self):
144 mod_name, mod_fn = self.new_module(
143 mod_name, mod_fn = self.new_module(
145 textwrap.dedent(
144 textwrap.dedent(
146 """
145 """
147 from enum import Enum
146 from enum import Enum
148 class MyEnum(Enum):
147 class MyEnum(Enum):
149 A = 'A'
148 A = 'A'
150 B = 'B'
149 B = 'B'
151 """
150 """
152 )
151 )
153 )
152 )
154 self.shell.magic_autoreload("2")
153 self.shell.magic_autoreload("2")
155 self.shell.magic_aimport(mod_name)
154 self.shell.magic_aimport(mod_name)
156 self.write_file(
155 self.write_file(
157 mod_fn,
156 mod_fn,
158 textwrap.dedent(
157 textwrap.dedent(
159 """
158 """
160 from enum import Enum
159 from enum import Enum
161 class MyEnum(Enum):
160 class MyEnum(Enum):
162 A = 'A'
161 A = 'A'
163 B = 'B'
162 B = 'B'
164 C = 'C'
163 C = 'C'
165 """
164 """
166 ),
165 ),
167 )
166 )
168 with tt.AssertNotPrints(
167 with tt.AssertNotPrints(
169 ("[autoreload of %s failed:" % mod_name), channel="stderr"
168 ("[autoreload of %s failed:" % mod_name), channel="stderr"
170 ):
169 ):
171 self.shell.run_code("pass") # trigger another reload
170 self.shell.run_code("pass") # trigger another reload
172
171
173 def test_reload_class_type(self):
172 def test_reload_class_type(self):
174 self.shell.magic_autoreload("2")
173 self.shell.magic_autoreload("2")
175 mod_name, mod_fn = self.new_module(
174 mod_name, mod_fn = self.new_module(
176 """
175 """
177 class Test():
176 class Test():
178 def meth(self):
177 def meth(self):
179 return "old"
178 return "old"
180 """
179 """
181 )
180 )
182 assert "test" not in self.shell.ns
181 assert "test" not in self.shell.ns
183 assert "result" not in self.shell.ns
182 assert "result" not in self.shell.ns
184
183
185 self.shell.run_code("from %s import Test" % mod_name)
184 self.shell.run_code("from %s import Test" % mod_name)
186 self.shell.run_code("test = Test()")
185 self.shell.run_code("test = Test()")
187
186
188 self.write_file(
187 self.write_file(
189 mod_fn,
188 mod_fn,
190 """
189 """
191 class Test():
190 class Test():
192 def meth(self):
191 def meth(self):
193 return "new"
192 return "new"
194 """,
193 """,
195 )
194 )
196
195
197 test_object = self.shell.ns["test"]
196 test_object = self.shell.ns["test"]
198
197
199 # important to trigger autoreload logic !
198 # important to trigger autoreload logic !
200 self.shell.run_code("pass")
199 self.shell.run_code("pass")
201
200
202 test_class = pickle_get_current_class(test_object)
201 test_class = pickle_get_current_class(test_object)
203 assert isinstance(test_object, test_class)
202 assert isinstance(test_object, test_class)
204
203
205 # extra check.
204 # extra check.
206 self.shell.run_code("import pickle")
205 self.shell.run_code("import pickle")
207 self.shell.run_code("p = pickle.dumps(test)")
206 self.shell.run_code("p = pickle.dumps(test)")
208
207
209 def test_reload_class_attributes(self):
208 def test_reload_class_attributes(self):
210 self.shell.magic_autoreload("2")
209 self.shell.magic_autoreload("2")
211 mod_name, mod_fn = self.new_module(
210 mod_name, mod_fn = self.new_module(
212 textwrap.dedent(
211 textwrap.dedent(
213 """
212 """
214 class MyClass:
213 class MyClass:
215
214
216 def __init__(self, a=10):
215 def __init__(self, a=10):
217 self.a = a
216 self.a = a
218 self.b = 22
217 self.b = 22
219 # self.toto = 33
218 # self.toto = 33
220
219
221 def square(self):
220 def square(self):
222 print('compute square')
221 print('compute square')
223 return self.a*self.a
222 return self.a*self.a
224 """
223 """
225 )
224 )
226 )
225 )
227 self.shell.run_code("from %s import MyClass" % mod_name)
226 self.shell.run_code("from %s import MyClass" % mod_name)
228 self.shell.run_code("first = MyClass(5)")
227 self.shell.run_code("first = MyClass(5)")
229 self.shell.run_code("first.square()")
228 self.shell.run_code("first.square()")
230 with nt.assert_raises(AttributeError):
229 with self.assertRaises(AttributeError):
231 self.shell.run_code("first.cube()")
230 self.shell.run_code("first.cube()")
232 with nt.assert_raises(AttributeError):
231 with self.assertRaises(AttributeError):
233 self.shell.run_code("first.power(5)")
232 self.shell.run_code("first.power(5)")
234 self.shell.run_code("first.b")
233 self.shell.run_code("first.b")
235 with nt.assert_raises(AttributeError):
234 with self.assertRaises(AttributeError):
236 self.shell.run_code("first.toto")
235 self.shell.run_code("first.toto")
237
236
238 # remove square, add power
237 # remove square, add power
239
238
240 self.write_file(
239 self.write_file(
241 mod_fn,
240 mod_fn,
242 textwrap.dedent(
241 textwrap.dedent(
243 """
242 """
244 class MyClass:
243 class MyClass:
245
244
246 def __init__(self, a=10):
245 def __init__(self, a=10):
247 self.a = a
246 self.a = a
248 self.b = 11
247 self.b = 11
249
248
250 def power(self, p):
249 def power(self, p):
251 print('compute power '+str(p))
250 print('compute power '+str(p))
252 return self.a**p
251 return self.a**p
253 """
252 """
254 ),
253 ),
255 )
254 )
256
255
257 self.shell.run_code("second = MyClass(5)")
256 self.shell.run_code("second = MyClass(5)")
258
257
259 for object_name in {"first", "second"}:
258 for object_name in {"first", "second"}:
260 self.shell.run_code(f"{object_name}.power(5)")
259 self.shell.run_code(f"{object_name}.power(5)")
261 with nt.assert_raises(AttributeError):
260 with self.assertRaises(AttributeError):
262 self.shell.run_code(f"{object_name}.cube()")
261 self.shell.run_code(f"{object_name}.cube()")
263 with nt.assert_raises(AttributeError):
262 with self.assertRaises(AttributeError):
264 self.shell.run_code(f"{object_name}.square()")
263 self.shell.run_code(f"{object_name}.square()")
265 self.shell.run_code(f"{object_name}.b")
264 self.shell.run_code(f"{object_name}.b")
266 self.shell.run_code(f"{object_name}.a")
265 self.shell.run_code(f"{object_name}.a")
267 with nt.assert_raises(AttributeError):
266 with self.assertRaises(AttributeError):
268 self.shell.run_code(f"{object_name}.toto")
267 self.shell.run_code(f"{object_name}.toto")
269
268
270 def test_autoload_newly_added_objects(self):
269 def test_autoload_newly_added_objects(self):
271 self.shell.magic_autoreload("3")
270 self.shell.magic_autoreload("3")
272 mod_code = """
271 mod_code = """
273 def func1(): pass
272 def func1(): pass
274 """
273 """
275 mod_name, mod_fn = self.new_module(textwrap.dedent(mod_code))
274 mod_name, mod_fn = self.new_module(textwrap.dedent(mod_code))
276 self.shell.run_code(f"from {mod_name} import *")
275 self.shell.run_code(f"from {mod_name} import *")
277 self.shell.run_code("func1()")
276 self.shell.run_code("func1()")
278 with nt.assert_raises(NameError):
277 with self.assertRaises(NameError):
279 self.shell.run_code("func2()")
278 self.shell.run_code("func2()")
280 with nt.assert_raises(NameError):
279 with self.assertRaises(NameError):
281 self.shell.run_code("t = Test()")
280 self.shell.run_code("t = Test()")
282 with nt.assert_raises(NameError):
281 with self.assertRaises(NameError):
283 self.shell.run_code("number")
282 self.shell.run_code("number")
284
283
285 # ----------- TEST NEW OBJ LOADED --------------------------
284 # ----------- TEST NEW OBJ LOADED --------------------------
286
285
287 new_code = """
286 new_code = """
288 def func1(): pass
287 def func1(): pass
289 def func2(): pass
288 def func2(): pass
290 class Test: pass
289 class Test: pass
291 number = 0
290 number = 0
292 from enum import Enum
291 from enum import Enum
293 class TestEnum(Enum):
292 class TestEnum(Enum):
294 A = 'a'
293 A = 'a'
295 """
294 """
296 self.write_file(mod_fn, textwrap.dedent(new_code))
295 self.write_file(mod_fn, textwrap.dedent(new_code))
297
296
298 # test function now exists in shell's namespace namespace
297 # test function now exists in shell's namespace namespace
299 self.shell.run_code("func2()")
298 self.shell.run_code("func2()")
300 # test function now exists in module's dict
299 # test function now exists in module's dict
301 self.shell.run_code(f"import sys; sys.modules['{mod_name}'].func2()")
300 self.shell.run_code(f"import sys; sys.modules['{mod_name}'].func2()")
302 # test class now exists
301 # test class now exists
303 self.shell.run_code("t = Test()")
302 self.shell.run_code("t = Test()")
304 # test global built-in var now exists
303 # test global built-in var now exists
305 self.shell.run_code("number")
304 self.shell.run_code("number")
306 # test the enumerations gets loaded successfully
305 # test the enumerations gets loaded successfully
307 self.shell.run_code("TestEnum.A")
306 self.shell.run_code("TestEnum.A")
308
307
309 # ----------- TEST NEW OBJ CAN BE CHANGED --------------------
308 # ----------- TEST NEW OBJ CAN BE CHANGED --------------------
310
309
311 new_code = """
310 new_code = """
312 def func1(): return 'changed'
311 def func1(): return 'changed'
313 def func2(): return 'changed'
312 def func2(): return 'changed'
314 class Test:
313 class Test:
315 def new_func(self):
314 def new_func(self):
316 return 'changed'
315 return 'changed'
317 number = 1
316 number = 1
318 from enum import Enum
317 from enum import Enum
319 class TestEnum(Enum):
318 class TestEnum(Enum):
320 A = 'a'
319 A = 'a'
321 B = 'added'
320 B = 'added'
322 """
321 """
323 self.write_file(mod_fn, textwrap.dedent(new_code))
322 self.write_file(mod_fn, textwrap.dedent(new_code))
324 self.shell.run_code("assert func1() == 'changed'")
323 self.shell.run_code("assert func1() == 'changed'")
325 self.shell.run_code("assert func2() == 'changed'")
324 self.shell.run_code("assert func2() == 'changed'")
326 self.shell.run_code("t = Test(); assert t.new_func() == 'changed'")
325 self.shell.run_code("t = Test(); assert t.new_func() == 'changed'")
327 self.shell.run_code("assert number == 1")
326 self.shell.run_code("assert number == 1")
328 self.shell.run_code("assert TestEnum.B.value == 'added'")
327 self.shell.run_code("assert TestEnum.B.value == 'added'")
329
328
330 # ----------- TEST IMPORT FROM MODULE --------------------------
329 # ----------- TEST IMPORT FROM MODULE --------------------------
331
330
332 new_mod_code = """
331 new_mod_code = """
333 from enum import Enum
332 from enum import Enum
334 class Ext(Enum):
333 class Ext(Enum):
335 A = 'ext'
334 A = 'ext'
336 def ext_func():
335 def ext_func():
337 return 'ext'
336 return 'ext'
338 class ExtTest:
337 class ExtTest:
339 def meth(self):
338 def meth(self):
340 return 'ext'
339 return 'ext'
341 ext_int = 2
340 ext_int = 2
342 """
341 """
343 new_mod_name, new_mod_fn = self.new_module(textwrap.dedent(new_mod_code))
342 new_mod_name, new_mod_fn = self.new_module(textwrap.dedent(new_mod_code))
344 current_mod_code = f"""
343 current_mod_code = f"""
345 from {new_mod_name} import *
344 from {new_mod_name} import *
346 """
345 """
347 self.write_file(mod_fn, textwrap.dedent(current_mod_code))
346 self.write_file(mod_fn, textwrap.dedent(current_mod_code))
348 self.shell.run_code("assert Ext.A.value == 'ext'")
347 self.shell.run_code("assert Ext.A.value == 'ext'")
349 self.shell.run_code("assert ext_func() == 'ext'")
348 self.shell.run_code("assert ext_func() == 'ext'")
350 self.shell.run_code("t = ExtTest(); assert t.meth() == 'ext'")
349 self.shell.run_code("t = ExtTest(); assert t.meth() == 'ext'")
351 self.shell.run_code("assert ext_int == 2")
350 self.shell.run_code("assert ext_int == 2")
352
351
353 def _check_smoketest(self, use_aimport=True):
352 def _check_smoketest(self, use_aimport=True):
354 """
353 """
355 Functional test for the automatic reloader using either
354 Functional test for the automatic reloader using either
356 '%autoreload 1' or '%autoreload 2'
355 '%autoreload 1' or '%autoreload 2'
357 """
356 """
358
357
359 mod_name, mod_fn = self.new_module(
358 mod_name, mod_fn = self.new_module(
360 """
359 """
361 x = 9
360 x = 9
362
361
363 z = 123 # this item will be deleted
362 z = 123 # this item will be deleted
364
363
365 def foo(y):
364 def foo(y):
366 return y + 3
365 return y + 3
367
366
368 class Baz(object):
367 class Baz(object):
369 def __init__(self, x):
368 def __init__(self, x):
370 self.x = x
369 self.x = x
371 def bar(self, y):
370 def bar(self, y):
372 return self.x + y
371 return self.x + y
373 @property
372 @property
374 def quux(self):
373 def quux(self):
375 return 42
374 return 42
376 def zzz(self):
375 def zzz(self):
377 '''This method will be deleted below'''
376 '''This method will be deleted below'''
378 return 99
377 return 99
379
378
380 class Bar: # old-style class: weakref doesn't work for it on Python < 2.7
379 class Bar: # old-style class: weakref doesn't work for it on Python < 2.7
381 def foo(self):
380 def foo(self):
382 return 1
381 return 1
383 """
382 """
384 )
383 )
385
384
386 #
385 #
387 # Import module, and mark for reloading
386 # Import module, and mark for reloading
388 #
387 #
389 if use_aimport:
388 if use_aimport:
390 self.shell.magic_autoreload("1")
389 self.shell.magic_autoreload("1")
391 self.shell.magic_aimport(mod_name)
390 self.shell.magic_aimport(mod_name)
392 stream = StringIO()
391 stream = StringIO()
393 self.shell.magic_aimport("", stream=stream)
392 self.shell.magic_aimport("", stream=stream)
394 nt.assert_in(("Modules to reload:\n%s" % mod_name), stream.getvalue())
393 self.assertIn(("Modules to reload:\n%s" % mod_name), stream.getvalue())
395
394
396 with nt.assert_raises(ImportError):
395 with self.assertRaises(ImportError):
397 self.shell.magic_aimport("tmpmod_as318989e89ds")
396 self.shell.magic_aimport("tmpmod_as318989e89ds")
398 else:
397 else:
399 self.shell.magic_autoreload("2")
398 self.shell.magic_autoreload("2")
400 self.shell.run_code("import %s" % mod_name)
399 self.shell.run_code("import %s" % mod_name)
401 stream = StringIO()
400 stream = StringIO()
402 self.shell.magic_aimport("", stream=stream)
401 self.shell.magic_aimport("", stream=stream)
403 nt.assert_true(
402 self.assertTrue(
404 "Modules to reload:\nall-except-skipped" in stream.getvalue()
403 "Modules to reload:\nall-except-skipped" in stream.getvalue()
405 )
404 )
406 nt.assert_in(mod_name, self.shell.ns)
405 self.assertIn(mod_name, self.shell.ns)
407
406
408 mod = sys.modules[mod_name]
407 mod = sys.modules[mod_name]
409
408
410 #
409 #
411 # Test module contents
410 # Test module contents
412 #
411 #
413 old_foo = mod.foo
412 old_foo = mod.foo
414 old_obj = mod.Baz(9)
413 old_obj = mod.Baz(9)
415 old_obj2 = mod.Bar()
414 old_obj2 = mod.Bar()
416
415
417 def check_module_contents():
416 def check_module_contents():
418 nt.assert_equal(mod.x, 9)
417 self.assertEqual(mod.x, 9)
419 nt.assert_equal(mod.z, 123)
418 self.assertEqual(mod.z, 123)
420
419
421 nt.assert_equal(old_foo(0), 3)
420 self.assertEqual(old_foo(0), 3)
422 nt.assert_equal(mod.foo(0), 3)
421 self.assertEqual(mod.foo(0), 3)
423
422
424 obj = mod.Baz(9)
423 obj = mod.Baz(9)
425 nt.assert_equal(old_obj.bar(1), 10)
424 self.assertEqual(old_obj.bar(1), 10)
426 nt.assert_equal(obj.bar(1), 10)
425 self.assertEqual(obj.bar(1), 10)
427 nt.assert_equal(obj.quux, 42)
426 self.assertEqual(obj.quux, 42)
428 nt.assert_equal(obj.zzz(), 99)
427 self.assertEqual(obj.zzz(), 99)
429
428
430 obj2 = mod.Bar()
429 obj2 = mod.Bar()
431 nt.assert_equal(old_obj2.foo(), 1)
430 self.assertEqual(old_obj2.foo(), 1)
432 nt.assert_equal(obj2.foo(), 1)
431 self.assertEqual(obj2.foo(), 1)
433
432
434 check_module_contents()
433 check_module_contents()
435
434
436 #
435 #
437 # Simulate a failed reload: no reload should occur and exactly
436 # Simulate a failed reload: no reload should occur and exactly
438 # one error message should be printed
437 # one error message should be printed
439 #
438 #
440 self.write_file(
439 self.write_file(
441 mod_fn,
440 mod_fn,
442 """
441 """
443 a syntax error
442 a syntax error
444 """,
443 """,
445 )
444 )
446
445
447 with tt.AssertPrints(
446 with tt.AssertPrints(
448 ("[autoreload of %s failed:" % mod_name), channel="stderr"
447 ("[autoreload of %s failed:" % mod_name), channel="stderr"
449 ):
448 ):
450 self.shell.run_code("pass") # trigger reload
449 self.shell.run_code("pass") # trigger reload
451 with tt.AssertNotPrints(
450 with tt.AssertNotPrints(
452 ("[autoreload of %s failed:" % mod_name), channel="stderr"
451 ("[autoreload of %s failed:" % mod_name), channel="stderr"
453 ):
452 ):
454 self.shell.run_code("pass") # trigger another reload
453 self.shell.run_code("pass") # trigger another reload
455 check_module_contents()
454 check_module_contents()
456
455
457 #
456 #
458 # Rewrite module (this time reload should succeed)
457 # Rewrite module (this time reload should succeed)
459 #
458 #
460 self.write_file(
459 self.write_file(
461 mod_fn,
460 mod_fn,
462 """
461 """
463 x = 10
462 x = 10
464
463
465 def foo(y):
464 def foo(y):
466 return y + 4
465 return y + 4
467
466
468 class Baz(object):
467 class Baz(object):
469 def __init__(self, x):
468 def __init__(self, x):
470 self.x = x
469 self.x = x
471 def bar(self, y):
470 def bar(self, y):
472 return self.x + y + 1
471 return self.x + y + 1
473 @property
472 @property
474 def quux(self):
473 def quux(self):
475 return 43
474 return 43
476
475
477 class Bar: # old-style class
476 class Bar: # old-style class
478 def foo(self):
477 def foo(self):
479 return 2
478 return 2
480 """,
479 """,
481 )
480 )
482
481
483 def check_module_contents():
482 def check_module_contents():
484 nt.assert_equal(mod.x, 10)
483 self.assertEqual(mod.x, 10)
485 nt.assert_false(hasattr(mod, "z"))
484 self.assertFalse(hasattr(mod, "z"))
486
485
487 nt.assert_equal(old_foo(0), 4) # superreload magic!
486 self.assertEqual(old_foo(0), 4) # superreload magic!
488 nt.assert_equal(mod.foo(0), 4)
487 self.assertEqual(mod.foo(0), 4)
489
488
490 obj = mod.Baz(9)
489 obj = mod.Baz(9)
491 nt.assert_equal(old_obj.bar(1), 11) # superreload magic!
490 self.assertEqual(old_obj.bar(1), 11) # superreload magic!
492 nt.assert_equal(obj.bar(1), 11)
491 self.assertEqual(obj.bar(1), 11)
493
492
494 nt.assert_equal(old_obj.quux, 43)
493 self.assertEqual(old_obj.quux, 43)
495 nt.assert_equal(obj.quux, 43)
494 self.assertEqual(obj.quux, 43)
496
495
497 nt.assert_false(hasattr(old_obj, "zzz"))
496 self.assertFalse(hasattr(old_obj, "zzz"))
498 nt.assert_false(hasattr(obj, "zzz"))
497 self.assertFalse(hasattr(obj, "zzz"))
499
498
500 obj2 = mod.Bar()
499 obj2 = mod.Bar()
501 nt.assert_equal(old_obj2.foo(), 2)
500 self.assertEqual(old_obj2.foo(), 2)
502 nt.assert_equal(obj2.foo(), 2)
501 self.assertEqual(obj2.foo(), 2)
503
502
504 self.shell.run_code("pass") # trigger reload
503 self.shell.run_code("pass") # trigger reload
505 check_module_contents()
504 check_module_contents()
506
505
507 #
506 #
508 # Another failure case: deleted file (shouldn't reload)
507 # Another failure case: deleted file (shouldn't reload)
509 #
508 #
510 os.unlink(mod_fn)
509 os.unlink(mod_fn)
511
510
512 self.shell.run_code("pass") # trigger reload
511 self.shell.run_code("pass") # trigger reload
513 check_module_contents()
512 check_module_contents()
514
513
515 #
514 #
516 # Disable autoreload and rewrite module: no reload should occur
515 # Disable autoreload and rewrite module: no reload should occur
517 #
516 #
518 if use_aimport:
517 if use_aimport:
519 self.shell.magic_aimport("-" + mod_name)
518 self.shell.magic_aimport("-" + mod_name)
520 stream = StringIO()
519 stream = StringIO()
521 self.shell.magic_aimport("", stream=stream)
520 self.shell.magic_aimport("", stream=stream)
522 nt.assert_true(("Modules to skip:\n%s" % mod_name) in stream.getvalue())
521 self.assertTrue(("Modules to skip:\n%s" % mod_name) in stream.getvalue())
523
522
524 # This should succeed, although no such module exists
523 # This should succeed, although no such module exists
525 self.shell.magic_aimport("-tmpmod_as318989e89ds")
524 self.shell.magic_aimport("-tmpmod_as318989e89ds")
526 else:
525 else:
527 self.shell.magic_autoreload("0")
526 self.shell.magic_autoreload("0")
528
527
529 self.write_file(
528 self.write_file(
530 mod_fn,
529 mod_fn,
531 """
530 """
532 x = -99
531 x = -99
533 """,
532 """,
534 )
533 )
535
534
536 self.shell.run_code("pass") # trigger reload
535 self.shell.run_code("pass") # trigger reload
537 self.shell.run_code("pass")
536 self.shell.run_code("pass")
538 check_module_contents()
537 check_module_contents()
539
538
540 #
539 #
541 # Re-enable autoreload: reload should now occur
540 # Re-enable autoreload: reload should now occur
542 #
541 #
543 if use_aimport:
542 if use_aimport:
544 self.shell.magic_aimport(mod_name)
543 self.shell.magic_aimport(mod_name)
545 else:
544 else:
546 self.shell.magic_autoreload("")
545 self.shell.magic_autoreload("")
547
546
548 self.shell.run_code("pass") # trigger reload
547 self.shell.run_code("pass") # trigger reload
549 nt.assert_equal(mod.x, -99)
548 self.assertEqual(mod.x, -99)
550
549
551 def test_smoketest_aimport(self):
550 def test_smoketest_aimport(self):
552 self._check_smoketest(use_aimport=True)
551 self._check_smoketest(use_aimport=True)
553
552
554 def test_smoketest_autoreload(self):
553 def test_smoketest_autoreload(self):
555 self._check_smoketest(use_aimport=False)
554 self._check_smoketest(use_aimport=False)
General Comments 0
You need to be logged in to leave comments. Login now