##// END OF EJS Templates
fix the test case
Srinivas Reddy Thatiparthy -
Show More
@@ -1,528 +1,528 b''
1 """IPython extension to reload modules before executing user code.
1 """IPython extension to reload modules before executing user code.
2
2
3 ``autoreload`` reloads modules automatically before entering the execution of
3 ``autoreload`` reloads modules automatically before entering the execution of
4 code typed at the IPython prompt.
4 code typed at the IPython prompt.
5
5
6 This makes for example the following workflow possible:
6 This makes for example the following workflow possible:
7
7
8 .. sourcecode:: ipython
8 .. sourcecode:: ipython
9
9
10 In [1]: %load_ext autoreload
10 In [1]: %load_ext autoreload
11
11
12 In [2]: %autoreload 2
12 In [2]: %autoreload 2
13
13
14 In [3]: from foo import some_function
14 In [3]: from foo import some_function
15
15
16 In [4]: some_function()
16 In [4]: some_function()
17 Out[4]: 42
17 Out[4]: 42
18
18
19 In [5]: # open foo.py in an editor and change some_function to return 43
19 In [5]: # open foo.py in an editor and change some_function to return 43
20
20
21 In [6]: some_function()
21 In [6]: some_function()
22 Out[6]: 43
22 Out[6]: 43
23
23
24 The module was reloaded without reloading it explicitly, and the object
24 The module was reloaded without reloading it explicitly, and the object
25 imported with ``from foo import ...`` was also updated.
25 imported with ``from foo import ...`` was also updated.
26
26
27 Usage
27 Usage
28 =====
28 =====
29
29
30 The following magic commands are provided:
30 The following magic commands are provided:
31
31
32 ``%autoreload``
32 ``%autoreload``
33
33
34 Reload all modules (except those excluded by ``%aimport``)
34 Reload all modules (except those excluded by ``%aimport``)
35 automatically now.
35 automatically now.
36
36
37 ``%autoreload 0``
37 ``%autoreload 0``
38
38
39 Disable automatic reloading.
39 Disable automatic reloading.
40
40
41 ``%autoreload 1``
41 ``%autoreload 1``
42
42
43 Reload all modules imported with ``%aimport`` every time before
43 Reload all modules imported with ``%aimport`` every time before
44 executing the Python code typed.
44 executing the Python code typed.
45
45
46 ``%autoreload 2``
46 ``%autoreload 2``
47
47
48 Reload all modules (except those excluded by ``%aimport``) every
48 Reload all modules (except those excluded by ``%aimport``) every
49 time before executing the Python code typed.
49 time before executing the Python code typed.
50
50
51 ``%aimport``
51 ``%aimport``
52
52
53 List modules which are to be automatically imported or not to be imported.
53 List modules which are to be automatically imported or not to be imported.
54
54
55 ``%aimport foo``
55 ``%aimport foo``
56
56
57 Import module 'foo' and mark it to be autoreloaded for ``%autoreload 1``
57 Import module 'foo' and mark it to be autoreloaded for ``%autoreload 1``
58
58
59 ``%aimport foo, bar``
59 ``%aimport foo, bar``
60
60
61 Import modules 'foo', 'bar' and mark them to be autoreloaded for ``%autoreload 1``
61 Import modules 'foo', 'bar' and mark them to be autoreloaded for ``%autoreload 1``
62
62
63 ``%aimport -foo``
63 ``%aimport -foo``
64
64
65 Mark module 'foo' to not be autoreloaded.
65 Mark module 'foo' to not be autoreloaded.
66
66
67 Caveats
67 Caveats
68 =======
68 =======
69
69
70 Reloading Python modules in a reliable way is in general difficult,
70 Reloading Python modules in a reliable way is in general difficult,
71 and unexpected things may occur. ``%autoreload`` tries to work around
71 and unexpected things may occur. ``%autoreload`` tries to work around
72 common pitfalls by replacing function code objects and parts of
72 common pitfalls by replacing function code objects and parts of
73 classes previously in the module with new versions. This makes the
73 classes previously in the module with new versions. This makes the
74 following things to work:
74 following things to work:
75
75
76 - Functions and classes imported via 'from xxx import foo' are upgraded
76 - Functions and classes imported via 'from xxx import foo' are upgraded
77 to new versions when 'xxx' is reloaded.
77 to new versions when 'xxx' is reloaded.
78
78
79 - Methods and properties of classes are upgraded on reload, so that
79 - Methods and properties of classes are upgraded on reload, so that
80 calling 'c.foo()' on an object 'c' created before the reload causes
80 calling 'c.foo()' on an object 'c' created before the reload causes
81 the new code for 'foo' to be executed.
81 the new code for 'foo' to be executed.
82
82
83 Some of the known remaining caveats are:
83 Some of the known remaining caveats are:
84
84
85 - Replacing code objects does not always succeed: changing a @property
85 - Replacing code objects does not always succeed: changing a @property
86 in a class to an ordinary method or a method to a member variable
86 in a class to an ordinary method or a method to a member variable
87 can cause problems (but in old objects only).
87 can cause problems (but in old objects only).
88
88
89 - Functions that are removed (eg. via monkey-patching) from a module
89 - Functions that are removed (eg. via monkey-patching) from a module
90 before it is reloaded are not upgraded.
90 before it is reloaded are not upgraded.
91
91
92 - C extension modules cannot be reloaded, and so cannot be autoreloaded.
92 - C extension modules cannot be reloaded, and so cannot be autoreloaded.
93 """
93 """
94
94
95 skip_doctest = True
95 skip_doctest = True
96
96
97 #-----------------------------------------------------------------------------
97 #-----------------------------------------------------------------------------
98 # Copyright (C) 2000 Thomas Heller
98 # Copyright (C) 2000 Thomas Heller
99 # Copyright (C) 2008 Pauli Virtanen <pav@iki.fi>
99 # Copyright (C) 2008 Pauli Virtanen <pav@iki.fi>
100 # Copyright (C) 2012 The IPython Development Team
100 # Copyright (C) 2012 The IPython Development Team
101 #
101 #
102 # Distributed under the terms of the BSD License. The full license is in
102 # Distributed under the terms of the BSD License. The full license is in
103 # the file COPYING, distributed as part of this software.
103 # the file COPYING, distributed as part of this software.
104 #-----------------------------------------------------------------------------
104 #-----------------------------------------------------------------------------
105 #
105 #
106 # This IPython module is written by Pauli Virtanen, based on the autoreload
106 # This IPython module is written by Pauli Virtanen, based on the autoreload
107 # code by Thomas Heller.
107 # code by Thomas Heller.
108
108
109 #-----------------------------------------------------------------------------
109 #-----------------------------------------------------------------------------
110 # Imports
110 # Imports
111 #-----------------------------------------------------------------------------
111 #-----------------------------------------------------------------------------
112
112
113 import os
113 import os
114 import sys
114 import sys
115 import traceback
115 import traceback
116 import types
116 import types
117 import weakref
117 import weakref
118 from importlib import import_module
118 from importlib import import_module
119
119 from IPython.utils.py3compat import PY3
120 try:
120 try:
121 # Reload is not defined by default in Python3.
121 # Reload is not defined by default in Python3.
122 reload
122 reload
123 except NameError:
123 except NameError:
124 from imp import reload
124 from imp import reload
125
125
126 from IPython.utils import openpy
126 from IPython.utils import openpy
127
127
128 #------------------------------------------------------------------------------
128 #------------------------------------------------------------------------------
129 # Autoreload functionality
129 # Autoreload functionality
130 #------------------------------------------------------------------------------
130 #------------------------------------------------------------------------------
131
131
132 class ModuleReloader(object):
132 class ModuleReloader(object):
133 enabled = False
133 enabled = False
134 """Whether this reloader is enabled"""
134 """Whether this reloader is enabled"""
135
135
136 check_all = True
136 check_all = True
137 """Autoreload all modules, not just those listed in 'modules'"""
137 """Autoreload all modules, not just those listed in 'modules'"""
138
138
139 def __init__(self):
139 def __init__(self):
140 # Modules that failed to reload: {module: mtime-on-failed-reload, ...}
140 # Modules that failed to reload: {module: mtime-on-failed-reload, ...}
141 self.failed = {}
141 self.failed = {}
142 # Modules specially marked as autoreloadable.
142 # Modules specially marked as autoreloadable.
143 self.modules = {}
143 self.modules = {}
144 # Modules specially marked as not autoreloadable.
144 # Modules specially marked as not autoreloadable.
145 self.skip_modules = {}
145 self.skip_modules = {}
146 # (module-name, name) -> weakref, for replacing old code objects
146 # (module-name, name) -> weakref, for replacing old code objects
147 self.old_objects = {}
147 self.old_objects = {}
148 # Module modification timestamps
148 # Module modification timestamps
149 self.modules_mtimes = {}
149 self.modules_mtimes = {}
150
150
151 # Cache module modification times
151 # Cache module modification times
152 self.check(check_all=True, do_reload=False)
152 self.check(check_all=True, do_reload=False)
153
153
154 def mark_module_skipped(self, module_name):
154 def mark_module_skipped(self, module_name):
155 """Skip reloading the named module in the future"""
155 """Skip reloading the named module in the future"""
156 try:
156 try:
157 del self.modules[module_name]
157 del self.modules[module_name]
158 except KeyError:
158 except KeyError:
159 pass
159 pass
160 self.skip_modules[module_name] = True
160 self.skip_modules[module_name] = True
161
161
162 def mark_module_reloadable(self, module_name):
162 def mark_module_reloadable(self, module_name):
163 """Reload the named module in the future (if it is imported)"""
163 """Reload the named module in the future (if it is imported)"""
164 try:
164 try:
165 del self.skip_modules[module_name]
165 del self.skip_modules[module_name]
166 except KeyError:
166 except KeyError:
167 pass
167 pass
168 self.modules[module_name] = True
168 self.modules[module_name] = True
169
169
170 def aimport_module(self, module_name):
170 def aimport_module(self, module_name):
171 """Import a module, and mark it reloadable
171 """Import a module, and mark it reloadable
172
172
173 Returns
173 Returns
174 -------
174 -------
175 top_module : module
175 top_module : module
176 The imported module if it is top-level, or the top-level
176 The imported module if it is top-level, or the top-level
177 top_name : module
177 top_name : module
178 Name of top_module
178 Name of top_module
179
179
180 """
180 """
181 self.mark_module_reloadable(module_name)
181 self.mark_module_reloadable(module_name)
182
182
183 import_module(module_name)
183 import_module(module_name)
184 top_name = module_name.split('.')[0]
184 top_name = module_name.split('.')[0]
185 top_module = sys.modules[top_name]
185 top_module = sys.modules[top_name]
186 return top_module, top_name
186 return top_module, top_name
187
187
188 def filename_and_mtime(self, module):
188 def filename_and_mtime(self, module):
189 if not hasattr(module, '__file__') or module.__file__ is None:
189 if not hasattr(module, '__file__') or module.__file__ is None:
190 return None, None
190 return None, None
191
191
192 if getattr(module, '__name__', None) == '__main__':
192 if getattr(module, '__name__', None) == '__main__':
193 # we cannot reload(__main__)
193 # we cannot reload(__main__)
194 return None, None
194 return None, None
195
195
196 filename = module.__file__
196 filename = module.__file__
197 path, ext = os.path.splitext(filename)
197 path, ext = os.path.splitext(filename)
198
198
199 if ext.lower() == '.py':
199 if ext.lower() == '.py':
200 py_filename = filename
200 py_filename = filename
201 else:
201 else:
202 try:
202 try:
203 py_filename = openpy.source_from_cache(filename)
203 py_filename = openpy.source_from_cache(filename)
204 except ValueError:
204 except ValueError:
205 return None, None
205 return None, None
206
206
207 try:
207 try:
208 pymtime = os.stat(py_filename).st_mtime
208 pymtime = os.stat(py_filename).st_mtime
209 except OSError:
209 except OSError:
210 return None, None
210 return None, None
211
211
212 return py_filename, pymtime
212 return py_filename, pymtime
213
213
214 def check(self, check_all=False, do_reload=True):
214 def check(self, check_all=False, do_reload=True):
215 """Check whether some modules need to be reloaded."""
215 """Check whether some modules need to be reloaded."""
216
216
217 if not self.enabled and not check_all:
217 if not self.enabled and not check_all:
218 return
218 return
219
219
220 if check_all or self.check_all:
220 if check_all or self.check_all:
221 modules = list(sys.modules.keys())
221 modules = list(sys.modules.keys())
222 else:
222 else:
223 modules = list(self.modules.keys())
223 modules = list(self.modules.keys())
224
224
225 for modname in modules:
225 for modname in modules:
226 m = sys.modules.get(modname, None)
226 m = sys.modules.get(modname, None)
227
227
228 if modname in self.skip_modules:
228 if modname in self.skip_modules:
229 continue
229 continue
230
230
231 py_filename, pymtime = self.filename_and_mtime(m)
231 py_filename, pymtime = self.filename_and_mtime(m)
232 if py_filename is None:
232 if py_filename is None:
233 continue
233 continue
234
234
235 try:
235 try:
236 if pymtime <= self.modules_mtimes[modname]:
236 if pymtime <= self.modules_mtimes[modname]:
237 continue
237 continue
238 except KeyError:
238 except KeyError:
239 self.modules_mtimes[modname] = pymtime
239 self.modules_mtimes[modname] = pymtime
240 continue
240 continue
241 else:
241 else:
242 if self.failed.get(py_filename, None) == pymtime:
242 if self.failed.get(py_filename, None) == pymtime:
243 continue
243 continue
244
244
245 self.modules_mtimes[modname] = pymtime
245 self.modules_mtimes[modname] = pymtime
246
246
247 # If we've reached this point, we should try to reload the module
247 # If we've reached this point, we should try to reload the module
248 if do_reload:
248 if do_reload:
249 try:
249 try:
250 superreload(m, reload, self.old_objects)
250 superreload(m, reload, self.old_objects)
251 if py_filename in self.failed:
251 if py_filename in self.failed:
252 del self.failed[py_filename]
252 del self.failed[py_filename]
253 except:
253 except:
254 print("[autoreload of %s failed: %s]" % (
254 print("[autoreload of %s failed: %s]" % (
255 modname, traceback.format_exc(1)), file=sys.stderr)
255 modname, traceback.format_exc(1)), file=sys.stderr)
256 self.failed[py_filename] = pymtime
256 self.failed[py_filename] = pymtime
257
257
258 #------------------------------------------------------------------------------
258 #------------------------------------------------------------------------------
259 # superreload
259 # superreload
260 #------------------------------------------------------------------------------
260 #------------------------------------------------------------------------------
261
261
262
262
263 func_attrs = ['__code__', '__defaults__', '__doc__',
263 func_attrs = ['__code__', '__defaults__', '__doc__',
264 '__closure__', '__globals__', '__dict__']
264 '__closure__', '__globals__', '__dict__']
265
265
266
266
267 def update_function(old, new):
267 def update_function(old, new):
268 """Upgrade the code object of a function"""
268 """Upgrade the code object of a function"""
269 for name in func_attrs:
269 for name in func_attrs:
270 try:
270 try:
271 setattr(old, name, getattr(new, name))
271 setattr(old, name, getattr(new, name))
272 except (AttributeError, TypeError):
272 except (AttributeError, TypeError):
273 pass
273 pass
274
274
275
275
276 def update_class(old, new):
276 def update_class(old, new):
277 """Replace stuff in the __dict__ of a class, and upgrade
277 """Replace stuff in the __dict__ of a class, and upgrade
278 method code objects"""
278 method code objects"""
279 for key in list(old.__dict__.keys()):
279 for key in list(old.__dict__.keys()):
280 old_obj = getattr(old, key)
280 old_obj = getattr(old, key)
281
281
282 try:
282 try:
283 new_obj = getattr(new, key)
283 new_obj = getattr(new, key)
284 except AttributeError:
284 except AttributeError:
285 # obsolete attribute: remove it
285 # obsolete attribute: remove it
286 try:
286 try:
287 delattr(old, key)
287 delattr(old, key)
288 except (AttributeError, TypeError):
288 except (AttributeError, TypeError):
289 pass
289 pass
290 continue
290 continue
291
291
292 if update_generic(old_obj, new_obj): continue
292 if update_generic(old_obj, new_obj): continue
293
293
294 try:
294 try:
295 setattr(old, key, getattr(new, key))
295 setattr(old, key, getattr(new, key))
296 except (AttributeError, TypeError):
296 except (AttributeError, TypeError):
297 pass # skip non-writable attributes
297 pass # skip non-writable attributes
298
298
299
299
300 def update_property(old, new):
300 def update_property(old, new):
301 """Replace get/set/del functions of a property"""
301 """Replace get/set/del functions of a property"""
302 update_generic(old.fdel, new.fdel)
302 update_generic(old.fdel, new.fdel)
303 update_generic(old.fget, new.fget)
303 update_generic(old.fget, new.fget)
304 update_generic(old.fset, new.fset)
304 update_generic(old.fset, new.fset)
305
305
306
306
307 def isinstance2(a, b, typ):
307 def isinstance2(a, b, typ):
308 return isinstance(a, typ) and isinstance(b, typ)
308 return isinstance(a, typ) and isinstance(b, typ)
309
309
310
310
311 UPDATE_RULES = [
311 UPDATE_RULES = [
312 (lambda a, b: isinstance2(a, b, type),
312 (lambda a, b: isinstance2(a, b, type),
313 update_class),
313 update_class),
314 (lambda a, b: isinstance2(a, b, types.FunctionType),
314 (lambda a, b: isinstance2(a, b, types.FunctionType),
315 update_function),
315 update_function),
316 (lambda a, b: isinstance2(a, b, property),
316 (lambda a, b: isinstance2(a, b, property),
317 update_property),
317 update_property),
318 ]
318 ]
319 UPDATE_RULES.extend([(lambda a, b: isinstance2(a, b, types.MethodType),
319 UPDATE_RULES.extend([(lambda a, b: isinstance2(a, b, types.MethodType),
320 lambda a, b: update_function(a.__func__, b.__func__)),
320 lambda a, b: update_function(a.__func__, b.__func__)),
321 ])
321 ])
322
322
323
323
324 def update_generic(a, b):
324 def update_generic(a, b):
325 for type_check, update in UPDATE_RULES:
325 for type_check, update in UPDATE_RULES:
326 if type_check(a, b):
326 if type_check(a, b):
327 update(a, b)
327 update(a, b)
328 return True
328 return True
329 return False
329 return False
330
330
331
331
332 class StrongRef(object):
332 class StrongRef(object):
333 def __init__(self, obj):
333 def __init__(self, obj):
334 self.obj = obj
334 self.obj = obj
335 def __call__(self):
335 def __call__(self):
336 return self.obj
336 return self.obj
337
337
338
338
339 def superreload(module, reload=reload, old_objects={}):
339 def superreload(module, reload=reload, old_objects={}):
340 """Enhanced version of the builtin reload function.
340 """Enhanced version of the builtin reload function.
341
341
342 superreload remembers objects previously in the module, and
342 superreload remembers objects previously in the module, and
343
343
344 - upgrades the class dictionary of every old class in the module
344 - upgrades the class dictionary of every old class in the module
345 - upgrades the code object of every old function and method
345 - upgrades the code object of every old function and method
346 - clears the module's namespace before reloading
346 - clears the module's namespace before reloading
347
347
348 """
348 """
349
349
350 # collect old objects in the module
350 # collect old objects in the module
351 for name, obj in list(module.__dict__.items()):
351 for name, obj in list(module.__dict__.items()):
352 if not hasattr(obj, '__module__') or obj.__module__ != module.__name__:
352 if not hasattr(obj, '__module__') or obj.__module__ != module.__name__:
353 continue
353 continue
354 key = (module.__name__, name)
354 key = (module.__name__, name)
355 try:
355 try:
356 old_objects.setdefault(key, []).append(weakref.ref(obj))
356 old_objects.setdefault(key, []).append(weakref.ref(obj))
357 except TypeError:
357 except TypeError:
358 pass
358 pass
359
359
360 # reload module
360 # reload module
361 try:
361 try:
362 # clear namespace first from old cruft
362 # clear namespace first from old cruft
363 old_dict = module.__dict__.copy()
363 old_dict = module.__dict__.copy()
364 old_name = module.__name__
364 old_name = module.__name__
365 module.__dict__.clear()
365 module.__dict__.clear()
366 module.__dict__['__name__'] = old_name
366 module.__dict__['__name__'] = old_name
367 module.__dict__['__loader__'] = old_dict['__loader__']
367 module.__dict__['__loader__'] = old_dict['__loader__']
368 except (TypeError, AttributeError, KeyError):
368 except (TypeError, AttributeError, KeyError):
369 pass
369 pass
370
370
371 try:
371 try:
372 module = reload(module)
372 module = reload(module)
373 except:
373 except:
374 # restore module dictionary on failed reload
374 # restore module dictionary on failed reload
375 module.__dict__.update(old_dict)
375 module.__dict__.update(old_dict)
376 raise
376 raise
377
377
378 # iterate over all objects and update functions & classes
378 # iterate over all objects and update functions & classes
379 for name, new_obj in list(module.__dict__.items()):
379 for name, new_obj in list(module.__dict__.items()):
380 key = (module.__name__, name)
380 key = (module.__name__, name)
381 if key not in old_objects: continue
381 if key not in old_objects: continue
382
382
383 new_refs = []
383 new_refs = []
384 for old_ref in old_objects[key]:
384 for old_ref in old_objects[key]:
385 old_obj = old_ref()
385 old_obj = old_ref()
386 if old_obj is None: continue
386 if old_obj is None: continue
387 new_refs.append(old_ref)
387 new_refs.append(old_ref)
388 update_generic(old_obj, new_obj)
388 update_generic(old_obj, new_obj)
389
389
390 if new_refs:
390 if new_refs:
391 old_objects[key] = new_refs
391 old_objects[key] = new_refs
392 else:
392 else:
393 del old_objects[key]
393 del old_objects[key]
394
394
395 return module
395 return module
396
396
397 #------------------------------------------------------------------------------
397 #------------------------------------------------------------------------------
398 # IPython connectivity
398 # IPython connectivity
399 #------------------------------------------------------------------------------
399 #------------------------------------------------------------------------------
400
400
401 from IPython.core.magic import Magics, magics_class, line_magic
401 from IPython.core.magic import Magics, magics_class, line_magic
402
402
403 @magics_class
403 @magics_class
404 class AutoreloadMagics(Magics):
404 class AutoreloadMagics(Magics):
405 def __init__(self, *a, **kw):
405 def __init__(self, *a, **kw):
406 super(AutoreloadMagics, self).__init__(*a, **kw)
406 super(AutoreloadMagics, self).__init__(*a, **kw)
407 self._reloader = ModuleReloader()
407 self._reloader = ModuleReloader()
408 self._reloader.check_all = False
408 self._reloader.check_all = False
409 self.loaded_modules = set(sys.modules)
409 self.loaded_modules = set(sys.modules)
410
410
411 @line_magic
411 @line_magic
412 def autoreload(self, parameter_s=''):
412 def autoreload(self, parameter_s=''):
413 r"""%autoreload => Reload modules automatically
413 r"""%autoreload => Reload modules automatically
414
414
415 %autoreload
415 %autoreload
416 Reload all modules (except those excluded by %aimport) automatically
416 Reload all modules (except those excluded by %aimport) automatically
417 now.
417 now.
418
418
419 %autoreload 0
419 %autoreload 0
420 Disable automatic reloading.
420 Disable automatic reloading.
421
421
422 %autoreload 1
422 %autoreload 1
423 Reload all modules imported with %aimport every time before executing
423 Reload all modules imported with %aimport every time before executing
424 the Python code typed.
424 the Python code typed.
425
425
426 %autoreload 2
426 %autoreload 2
427 Reload all modules (except those excluded by %aimport) every time
427 Reload all modules (except those excluded by %aimport) every time
428 before executing the Python code typed.
428 before executing the Python code typed.
429
429
430 Reloading Python modules in a reliable way is in general
430 Reloading Python modules in a reliable way is in general
431 difficult, and unexpected things may occur. %autoreload tries to
431 difficult, and unexpected things may occur. %autoreload tries to
432 work around common pitfalls by replacing function code objects and
432 work around common pitfalls by replacing function code objects and
433 parts of classes previously in the module with new versions. This
433 parts of classes previously in the module with new versions. This
434 makes the following things to work:
434 makes the following things to work:
435
435
436 - Functions and classes imported via 'from xxx import foo' are upgraded
436 - Functions and classes imported via 'from xxx import foo' are upgraded
437 to new versions when 'xxx' is reloaded.
437 to new versions when 'xxx' is reloaded.
438
438
439 - Methods and properties of classes are upgraded on reload, so that
439 - Methods and properties of classes are upgraded on reload, so that
440 calling 'c.foo()' on an object 'c' created before the reload causes
440 calling 'c.foo()' on an object 'c' created before the reload causes
441 the new code for 'foo' to be executed.
441 the new code for 'foo' to be executed.
442
442
443 Some of the known remaining caveats are:
443 Some of the known remaining caveats are:
444
444
445 - Replacing code objects does not always succeed: changing a @property
445 - Replacing code objects does not always succeed: changing a @property
446 in a class to an ordinary method or a method to a member variable
446 in a class to an ordinary method or a method to a member variable
447 can cause problems (but in old objects only).
447 can cause problems (but in old objects only).
448
448
449 - Functions that are removed (eg. via monkey-patching) from a module
449 - Functions that are removed (eg. via monkey-patching) from a module
450 before it is reloaded are not upgraded.
450 before it is reloaded are not upgraded.
451
451
452 - C extension modules cannot be reloaded, and so cannot be
452 - C extension modules cannot be reloaded, and so cannot be
453 autoreloaded.
453 autoreloaded.
454
454
455 """
455 """
456 if parameter_s == '':
456 if parameter_s == '':
457 self._reloader.check(True)
457 self._reloader.check(True)
458 elif parameter_s == '0':
458 elif parameter_s == '0':
459 self._reloader.enabled = False
459 self._reloader.enabled = False
460 elif parameter_s == '1':
460 elif parameter_s == '1':
461 self._reloader.check_all = False
461 self._reloader.check_all = False
462 self._reloader.enabled = True
462 self._reloader.enabled = True
463 elif parameter_s == '2':
463 elif parameter_s == '2':
464 self._reloader.check_all = True
464 self._reloader.check_all = True
465 self._reloader.enabled = True
465 self._reloader.enabled = True
466
466
467 @line_magic
467 @line_magic
468 def aimport(self, parameter_s='', stream=None):
468 def aimport(self, parameter_s='', stream=None):
469 """%aimport => Import modules for automatic reloading.
469 """%aimport => Import modules for automatic reloading.
470
470
471 %aimport
471 %aimport
472 List modules to automatically import and not to import.
472 List modules to automatically import and not to import.
473
473
474 %aimport foo
474 %aimport foo
475 Import module 'foo' and mark it to be autoreloaded for %autoreload 1
475 Import module 'foo' and mark it to be autoreloaded for %autoreload 1
476
476
477 %aimport foo, bar
477 %aimport foo, bar
478 Import modules 'foo', 'bar' and mark them to be autoreloaded for %autoreload 1
478 Import modules 'foo', 'bar' and mark them to be autoreloaded for %autoreload 1
479
479
480 %aimport -foo
480 %aimport -foo
481 Mark module 'foo' to not be autoreloaded for %autoreload 1
481 Mark module 'foo' to not be autoreloaded for %autoreload 1
482 """
482 """
483 modname = parameter_s
483 modname = parameter_s
484 if not modname:
484 if not modname:
485 to_reload = sorted(self._reloader.modules.keys())
485 to_reload = sorted(self._reloader.modules.keys())
486 to_skip = sorted(self._reloader.skip_modules.keys())
486 to_skip = sorted(self._reloader.skip_modules.keys())
487 if stream is None:
487 if stream is None:
488 stream = sys.stdout
488 stream = sys.stdout
489 if self._reloader.check_all:
489 if self._reloader.check_all:
490 stream.write("Modules to reload:\nall-except-skipped\n")
490 stream.write("Modules to reload:\nall-except-skipped\n")
491 else:
491 else:
492 stream.write("Modules to reload:\n%s\n" % ' '.join(to_reload))
492 stream.write("Modules to reload:\n%s\n" % ' '.join(to_reload))
493 stream.write("\nModules to skip:\n%s\n" % ' '.join(to_skip))
493 stream.write("\nModules to skip:\n%s\n" % ' '.join(to_skip))
494 elif modname.startswith('-'):
494 elif modname.startswith('-'):
495 modname = modname[1:]
495 modname = modname[1:]
496 self._reloader.mark_module_skipped(modname)
496 self._reloader.mark_module_skipped(modname)
497 else:
497 else:
498 for _module in ([_.strip() for _ in modname.split(',')]):
498 for _module in ([_.strip() for _ in modname.split(',')]):
499 top_module, top_name = self._reloader.aimport_module(_module)
499 top_module, top_name = self._reloader.aimport_module(_module)
500
500
501 # Inject module to user namespace
501 # Inject module to user namespace
502 self.shell.push({top_name: top_module})
502 self.shell.push({top_name: top_module})
503
503
504 def pre_run_cell(self):
504 def pre_run_cell(self):
505 if self._reloader.enabled:
505 if self._reloader.enabled:
506 try:
506 try:
507 self._reloader.check()
507 self._reloader.check()
508 except:
508 except:
509 pass
509 pass
510
510
511 def post_execute_hook(self):
511 def post_execute_hook(self):
512 """Cache the modification times of any modules imported in this execution
512 """Cache the modification times of any modules imported in this execution
513 """
513 """
514 newly_loaded_modules = set(sys.modules) - self.loaded_modules
514 newly_loaded_modules = set(sys.modules) - self.loaded_modules
515 for modname in newly_loaded_modules:
515 for modname in newly_loaded_modules:
516 _, pymtime = self._reloader.filename_and_mtime(sys.modules[modname])
516 _, pymtime = self._reloader.filename_and_mtime(sys.modules[modname])
517 if pymtime is not None:
517 if pymtime is not None:
518 self._reloader.modules_mtimes[modname] = pymtime
518 self._reloader.modules_mtimes[modname] = pymtime
519
519
520 self.loaded_modules.update(newly_loaded_modules)
520 self.loaded_modules.update(newly_loaded_modules)
521
521
522
522
523 def load_ipython_extension(ip):
523 def load_ipython_extension(ip):
524 """Load the extension in IPython."""
524 """Load the extension in IPython."""
525 auto_reload = AutoreloadMagics(ip)
525 auto_reload = AutoreloadMagics(ip)
526 ip.register_magics(auto_reload)
526 ip.register_magics(auto_reload)
527 ip.events.register('pre_run_cell', auto_reload.pre_run_cell)
527 ip.events.register('pre_run_cell', auto_reload.pre_run_cell)
528 ip.events.register('post_execute', auto_reload.post_execute_hook)
528 ip.events.register('post_execute', auto_reload.post_execute_hook)
General Comments 0
You need to be logged in to leave comments. Login now