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