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