##// END OF EJS Templates
ENH: extensions: port autoreload to current API
Pauli Virtanen -
Show More
@@ -219,132 +219,140 b' def superreload(module, reload=reload, old_objects={}):'
219
219
220 return module
220 return module
221
221
222 reloader = ModuleReloader()
223
224 #------------------------------------------------------------------------------
222 #------------------------------------------------------------------------------
225 # IPython connectivity
223 # IPython connectivity
226 #------------------------------------------------------------------------------
224 #------------------------------------------------------------------------------
227 from IPython.core import ipapi
228 from IPython.core.error import TryNext
229
230 ip = ipapi.get()
231
232 autoreload_enabled = False
233
234 def runcode_hook(self):
235 if not autoreload_enabled:
236 raise TryNext
237 try:
238 reloader.check()
239 except:
240 pass
241
242 def enable_autoreload():
243 global autoreload_enabled
244 autoreload_enabled = True
245
246 def disable_autoreload():
247 global autoreload_enabled
248 autoreload_enabled = False
249
250 def autoreload_f(self, parameter_s=''):
251 r""" %autoreload => Reload modules automatically
252
253 %autoreload
254 Reload all modules (except those excluded by %aimport) automatically now.
255
256 %autoreload 0
257 Disable automatic reloading.
258
259 %autoreload 1
260 Reload all modules imported with %aimport every time before executing
261 the Python code typed.
262
263 %autoreload 2
264 Reload all modules (except those excluded by %aimport) every time
265 before executing the Python code typed.
266
267 Reloading Python modules in a reliable way is in general
268 difficult, and unexpected things may occur. %autoreload tries to
269 work around common pitfalls by replacing function code objects and
270 parts of classes previously in the module with new versions. This
271 makes the following things to work:
272
225
273 - Functions and classes imported via 'from xxx import foo' are upgraded
226 from IPython.core.plugin import Plugin
274 to new versions when 'xxx' is reloaded.
227 from IPython.core.hooks import TryNext
275
228
276 - Methods and properties of classes are upgraded on reload, so that
229 class Autoreload(Plugin):
277 calling 'c.foo()' on an object 'c' created before the reload causes
230 def __init__(self, shell=None, config=None):
278 the new code for 'foo' to be executed.
231 super(Autoreload, self).__init__(shell=shell, config=config)
279
232
280 Some of the known remaining caveats are:
233 self.shell.define_magic('autoreload', self.magic_autoreload)
234 self.shell.define_magic('aimport', self.magic_aimport)
235 self.shell.set_hook('pre_run_code_hook', self.pre_run_code_hook)
281
236
282 - Replacing code objects does not always succeed: changing a @property
237 self._enabled = False
283 in a class to an ordinary method or a method to a member variable
238 self._reloader = ModuleReloader()
284 can cause problems (but in old objects only).
239 self._reloader.check_all = False
285
240
286 - Functions that are removed (eg. via monkey-patching) from a module
241 def pre_run_code_hook(self, ipself):
287 before it is reloaded are not upgraded.
242 if not self._enabled:
288
243 raise TryNext
289 - C extension modules cannot be reloaded, and so cannot be
244 try:
290 autoreloaded.
245 self._reloader.check()
291
246 except:
292 """
247 pass
293 if parameter_s == '':
294 reloader.check(True)
295 elif parameter_s == '0':
296 disable_autoreload()
297 elif parameter_s == '1':
298 reloader.check_all = False
299 enable_autoreload()
300 elif parameter_s == '2':
301 reloader.check_all = True
302 enable_autoreload()
303
304 def aimport_f(self, parameter_s=''):
305 """%aimport => Import modules for automatic reloading.
306
248
307 %aimport
249 def magic_autoreload(self, ipself, parameter_s=''):
308 List modules to automatically import and not to import.
250 r"""%autoreload => Reload modules automatically
251
252 %autoreload
253 Reload all modules (except those excluded by %aimport) automatically
254 now.
255
256 %autoreload 0
257 Disable automatic reloading.
258
259 %autoreload 1
260 Reload all modules imported with %aimport every time before executing
261 the Python code typed.
262
263 %autoreload 2
264 Reload all modules (except those excluded by %aimport) every time
265 before executing the Python code typed.
266
267 Reloading Python modules in a reliable way is in general
268 difficult, and unexpected things may occur. %autoreload tries to
269 work around common pitfalls by replacing function code objects and
270 parts of classes previously in the module with new versions. This
271 makes the following things to work:
272
273 - Functions and classes imported via 'from xxx import foo' are upgraded
274 to new versions when 'xxx' is reloaded.
275
276 - Methods and properties of classes are upgraded on reload, so that
277 calling 'c.foo()' on an object 'c' created before the reload causes
278 the new code for 'foo' to be executed.
279
280 Some of the known remaining caveats are:
281
282 - Replacing code objects does not always succeed: changing a @property
283 in a class to an ordinary method or a method to a member variable
284 can cause problems (but in old objects only).
285
286 - Functions that are removed (eg. via monkey-patching) from a module
287 before it is reloaded are not upgraded.
288
289 - C extension modules cannot be reloaded, and so cannot be
290 autoreloaded.
291
292 """
293 if parameter_s == '':
294 self._reloader.check(True)
295 elif parameter_s == '0':
296 self._enabled = False
297 elif parameter_s == '1':
298 self._reloader.check_all = False
299 self._enabled = True
300 elif parameter_s == '2':
301 self._reloader.check_all = True
302 self._enabled = True
303
304 def magic_aimport(self, ipself, parameter_s=''):
305 """%aimport => Import modules for automatic reloading.
306
307 %aimport
308 List modules to automatically import and not to import.
309
310 %aimport foo
311 Import module 'foo' and mark it to be autoreloaded for %autoreload 1
312
313 %aimport -foo
314 Mark module 'foo' to not be autoreloaded for %autoreload 1
315
316 """
317
318 modname = parameter_s
319 if not modname:
320 to_reload = self._reloader.modules.keys()
321 to_reload.sort()
322 to_skip = self._reloader.skip_modules.keys()
323 to_skip.sort()
324 if self._reloader.check_all:
325 print "Modules to reload:\nall-expect-skipped"
326 else:
327 print "Modules to reload:\n%s" % ' '.join(to_reload)
328 print "\nModules to skip:\n%s" % ' '.join(to_skip)
329 elif modname.startswith('-'):
330 modname = modname[1:]
331 try:
332 del self._reloader.modules[modname]
333 except KeyError:
334 pass
335 self._reloader.skip_modules[modname] = True
336 else:
337 try:
338 del self._reloader.skip_modules[modname]
339 except KeyError:
340 pass
341 self._reloader.modules[modname] = True
309
342
310 %aimport foo
343 # Inject module to user namespace; handle also submodules properly
311 Import module 'foo' and mark it to be autoreloaded for %autoreload 1
344 __import__(modname)
345 basename = modname.split('.')[0]
346 mod = sys.modules[basename]
347 ipself.push({basename: mod})
312
348
313 %aimport -foo
314 Mark module 'foo' to not be autoreloaded for %autoreload 1
315
349
316 """
350 _loaded = False
317
351
318 modname = parameter_s
352 def load_ipython_extension(ip):
319 if not modname:
353 """Load the extension in IPython."""
320 to_reload = reloader.modules.keys()
354 global _loaded
321 to_reload.sort()
355 if not _loaded:
322 to_skip = reloader.skip_modules.keys()
356 plugin = Autoreload(shell=ip, config=ip.config)
323 to_skip.sort()
357 ip.plugin_manager.register_plugin('autoreload', plugin)
324 if reloader.check_all:
358 _loaded = True
325 print "Modules to reload:\nall-expect-skipped"
326 else:
327 print "Modules to reload:\n%s" % ' '.join(to_reload)
328 print "\nModules to skip:\n%s" % ' '.join(to_skip)
329 elif modname.startswith('-'):
330 modname = modname[1:]
331 try: del reloader.modules[modname]
332 except KeyError: pass
333 reloader.skip_modules[modname] = True
334 else:
335 try: del reloader.skip_modules[modname]
336 except KeyError: pass
337 reloader.modules[modname] = True
338
339 # Inject module to user namespace; handle also submodules properly
340 __import__(modname)
341 basename = modname.split('.')[0]
342 mod = sys.modules[basename]
343 ip.push({basename: mod})
344
345 def init():
346 ip.define_magic('autoreload', autoreload_f)
347 ip.define_magic('aimport', aimport_f)
348 ip.set_hook('pre_runcode_hook', runcode_hook)
349
350 init()
General Comments 0
You need to be logged in to leave comments. Login now