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