##// END OF EJS Templates
Update autoreload: new magics api, various format fixes.
Fernando Perez -
Show More
@@ -1,6 +1,7 b''
1 """
2 ``autoreload`` is an IPython extension that reloads modules
3 automatically before executing the line of code typed.
1 """IPython extension to reload modules before executing user code.
2
3 ``autoreload`` reloads modules automatically before entering the execution of
4 code typed at the IPython prompt.
4 5
5 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 21 In [6]: some_function()
21 22 Out[6]: 43
22 23
23 The module was reloaded without reloading it explicitly, and the
24 object imported with ``from foo import ...`` was also updated.
24 The module was reloaded without reloading it explicitly, and the object
25 imported with ``from foo import ...`` was also updated.
25 26
26 27 Usage
27 28 =====
@@ -84,26 +85,39 b' Some of the known remaining caveats are:'
84 85 - Functions that are removed (eg. via monkey-patching) from a module
85 86 before it is reloaded are not upgraded.
86 87
87 - C extension modules cannot be reloaded, and so cannot be
88 autoreloaded.
89
88 - C extension modules cannot be reloaded, and so cannot be autoreloaded.
90 89 """
91 90
92 91 skip_doctest = True
93 92
94 # Pauli Virtanen <pav@iki.fi>, 2008.
95 # Thomas Heller, 2000.
93 #-----------------------------------------------------------------------------
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 102 # This IPython module is written by Pauli Virtanen, based on the autoreload
98 103 # code by Thomas Heller.
99 104
100 #------------------------------------------------------------------------------
101 # Autoreload functionality
102 #------------------------------------------------------------------------------
103
104 import time, os, threading, sys, types, imp, inspect, traceback, atexit
105 #-----------------------------------------------------------------------------
106 # Imports
107 #-----------------------------------------------------------------------------
108 import 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 117 import weakref
118
106 119 try:
120 # Reload is not defined by default in Python3.
107 121 reload
108 122 except NameError:
109 123 from imp import reload
@@ -111,14 +125,20 b' except NameError:'
111 125 from IPython.utils import pyfile
112 126 from IPython.utils.py3compat import PY3
113 127
128 #------------------------------------------------------------------------------
129 # Autoreload functionality
130 #------------------------------------------------------------------------------
131
114 132 def _get_compiled_ext():
115 133 """Official way to get the extension of compiled files (.pyc or .pyo)"""
116 134 for ext, mode, typ in imp.get_suffixes():
117 135 if typ == imp.PY_COMPILED:
118 136 return ext
119 137
138
120 139 PY_COMPILED_EXT = _get_compiled_ext()
121 140
141
122 142 class ModuleReloader(object):
123 143 enabled = False
124 144 """Whether this reloader is enabled"""
@@ -239,6 +259,7 b' else:'
239 259 func_attrs = ['func_code', 'func_defaults', 'func_doc',
240 260 'func_closure', 'func_globals', 'func_dict']
241 261
262
242 263 def update_function(old, new):
243 264 """Upgrade the code object of a function"""
244 265 for name in func_attrs:
@@ -247,6 +268,7 b' def update_function(old, new):'
247 268 except (AttributeError, TypeError):
248 269 pass
249 270
271
250 272 def update_class(old, new):
251 273 """Replace stuff in the __dict__ of a class, and upgrade
252 274 method code objects"""
@@ -270,15 +292,18 b' def update_class(old, new):'
270 292 except (AttributeError, TypeError):
271 293 pass # skip non-writable attributes
272 294
295
273 296 def update_property(old, new):
274 297 """Replace get/set/del functions of a property"""
275 298 update_generic(old.fdel, new.fdel)
276 299 update_generic(old.fget, new.fget)
277 300 update_generic(old.fset, new.fset)
278 301
302
279 303 def isinstance2(a, b, typ):
280 304 return isinstance(a, typ) and isinstance(b, typ)
281 305
306
282 307 UPDATE_RULES = [
283 308 (lambda a, b: isinstance2(a, b, type),
284 309 update_class),
@@ -288,6 +313,7 b' UPDATE_RULES = ['
288 313 update_property),
289 314 ]
290 315
316
291 317 if PY3:
292 318 UPDATE_RULES.extend([(lambda a, b: isinstance2(a, b, types.MethodType),
293 319 lambda a, b: update_function(a.__func__, b.__func__)),
@@ -307,12 +333,14 b' def update_generic(a, b):'
307 333 return True
308 334 return False
309 335
336
310 337 class StrongRef(object):
311 338 def __init__(self, obj):
312 339 self.obj = obj
313 340 def __call__(self):
314 341 return self.obj
315 342
343
316 344 def superreload(module, reload=reload, old_objects={}):
317 345 """Enhanced version of the builtin reload function.
318 346
@@ -377,16 +405,19 b' def superreload(module, reload=reload, old_objects={}):'
377 405 # IPython connectivity
378 406 #------------------------------------------------------------------------------
379 407
380 from IPython.core.plugin import Plugin
381 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 414 def __init__(self, *a, **kw):
385 super(AutoreloadInterface, self).__init__(*a, **kw)
415 super(AutoreloadMagics, self).__init__(*a, **kw)
386 416 self._reloader = ModuleReloader()
387 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 421 r"""%autoreload => Reload modules automatically
391 422
392 423 %autoreload
@@ -441,7 +472,8 b' class AutoreloadInterface(object):'
441 472 self._reloader.check_all = True
442 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 477 """%aimport => Import modules for automatic reloading.
446 478
447 479 %aimport
@@ -475,7 +507,7 b' class AutoreloadInterface(object):'
475 507 top_module, top_name = self._reloader.aimport_module(modname)
476 508
477 509 # Inject module to user namespace
478 ipself.push({top_name: top_module})
510 self.shell.push({top_name: top_module})
479 511
480 512 def pre_run_code_hook(self, ipself):
481 513 if not self._reloader.enabled:
@@ -485,16 +517,18 b' class AutoreloadInterface(object):'
485 517 except:
486 518 pass
487 519
488 class AutoreloadPlugin(AutoreloadInterface, Plugin):
520
521 class AutoreloadPlugin(Plugin):
489 522 def __init__(self, shell=None, config=None):
490 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 529 _loaded = False
497 530
531
498 532 def load_ipython_extension(ip):
499 533 """Load the extension in IPython."""
500 534 global _loaded
General Comments 0
You need to be logged in to leave comments. Login now