Show More
@@ -219,132 +219,140 b' def superreload(module, reload=reload, old_objects={}):' | |||
|
219 | 219 | |
|
220 | 220 | return module |
|
221 | 221 | |
|
222 | reloader = ModuleReloader() | |
|
223 | ||
|
224 | 222 | #------------------------------------------------------------------------------ |
|
225 | 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 | |
|
274 | to new versions when 'xxx' is reloaded. | |
|
226 | from IPython.core.plugin import Plugin | |
|
227 | from IPython.core.hooks import TryNext | |
|
275 | 228 | |
|
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. | |
|
229 | class Autoreload(Plugin): | |
|
230 | def __init__(self, shell=None, config=None): | |
|
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 | |
|
283 | in a class to an ordinary method or a method to a member variable | |
|
284 | can cause problems (but in old objects only). | |
|
237 | self._enabled = False | |
|
238 | self._reloader = ModuleReloader() | |
|
239 | self._reloader.check_all = False | |
|
285 | 240 | |
|
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 | 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. | |
|
241 | def pre_run_code_hook(self, ipself): | |
|
242 | if not self._enabled: | |
|
243 | raise TryNext | |
|
244 | try: | |
|
245 | self._reloader.check() | |
|
246 | except: | |
|
247 | pass | |
|
306 | 248 | |
|
307 | %aimport | |
|
308 | List modules to automatically import and not to import. | |
|
249 | def magic_autoreload(self, ipself, parameter_s=''): | |
|
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 | |
|
311 | Import module 'foo' and mark it to be autoreloaded for %autoreload 1 | |
|
343 | # Inject module to user namespace; handle also submodules properly | |
|
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 | |
|
319 | if not modname: | |
|
320 | to_reload = reloader.modules.keys() | |
|
321 | to_reload.sort() | |
|
322 | to_skip = reloader.skip_modules.keys() | |
|
323 | to_skip.sort() | |
|
324 | if 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: 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() | |
|
352 | def load_ipython_extension(ip): | |
|
353 | """Load the extension in IPython.""" | |
|
354 | global _loaded | |
|
355 | if not _loaded: | |
|
356 | plugin = Autoreload(shell=ip, config=ip.config) | |
|
357 | ip.plugin_manager.register_plugin('autoreload', plugin) | |
|
358 | _loaded = True |
General Comments 0
You need to be logged in to leave comments.
Login now