##// END OF EJS Templates
Update autoreload: new magics api, various format fixes.
Fernando Perez -
Show More
@@ -1,6 +1,7 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
@@ -20,8 +21,8 b' This makes for example the following workflow possible:'
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 =====
@@ -84,26 +85,39 b' Some of the known remaining caveats are:'
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
@@ -111,14 +125,20 b' except NameError:'
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"""
@@ -239,6 +259,7 b' 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:
@@ -247,6 +268,7 b' def update_function(old, new):'
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"""
@@ -270,15 +292,18 b' def update_class(old, new):'
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),
@@ -288,6 +313,7 b' UPDATE_RULES = ['
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__)),
@@ -307,12 +333,14 b' def update_generic(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
@@ -377,16 +405,19 b' def superreload(module, reload=reload, old_objects={}):'
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
@@ -441,7 +472,8 b' class AutoreloadInterface(object):'
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
@@ -475,7 +507,7 b' class AutoreloadInterface(object):'
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:
@@ -485,16 +517,18 b' class AutoreloadInterface(object):'
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
General Comments 0
You need to be logged in to leave comments. Login now