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