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