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