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