builtin_trap.py
114 lines
| 4.2 KiB
| text/x-python
|
PythonLexer
Brian Granger
|
r2227 | """ | ||
A context manager for managing things injected into :mod:`__builtin__`. | ||||
Authors: | ||||
* Brian Granger | ||||
Fernando Perez
|
r2957 | * Fernando Perez | ||
Brian Granger
|
r2227 | """ | ||
#----------------------------------------------------------------------------- | ||||
Matthias BUSSONNIER
|
r5390 | # Copyright (C) 2010-2011 The IPython Development Team. | ||
Fernando Perez
|
r2957 | # | ||
# Distributed under the terms of the BSD License. | ||||
Brian Granger
|
r2227 | # | ||
Fernando Perez
|
r2957 | # Complete license in the file COPYING.txt, distributed with this software. | ||
Brian Granger
|
r2227 | #----------------------------------------------------------------------------- | ||
#----------------------------------------------------------------------------- | ||||
# Imports | ||||
#----------------------------------------------------------------------------- | ||||
Min RK
|
r21253 | from traitlets.config.configurable import Configurable | ||
Brian Granger
|
r2227 | |||
Thomas Kluyver
|
r13361 | from IPython.utils.py3compat import builtin_mod, iteritems | ||
Min RK
|
r21253 | from traitlets import Instance | ||
Brian Granger
|
r2229 | |||
Brian Granger
|
r2227 | #----------------------------------------------------------------------------- | ||
# Classes and functions | ||||
#----------------------------------------------------------------------------- | ||||
Fernando Perez
|
r2404 | class __BuiltinUndefined(object): pass | ||
BuiltinUndefined = __BuiltinUndefined() | ||||
Brian Granger
|
r2227 | |||
Erik Tollerud
|
r3185 | class __HideBuiltin(object): pass | ||
HideBuiltin = __HideBuiltin() | ||||
Brian Granger
|
r2227 | |||
Brian Granger
|
r2731 | class BuiltinTrap(Configurable): | ||
Brian Granger
|
r2227 | |||
Sylvain Corlay
|
r20940 | shell = Instance('IPython.core.interactiveshell.InteractiveShellABC', | ||
allow_none=True) | ||||
Brian Granger
|
r2731 | |||
Brian Granger
|
r2740 | def __init__(self, shell=None): | ||
super(BuiltinTrap, self).__init__(shell=shell, config=None) | ||||
Brian Granger
|
r2244 | self._orig_builtins = {} | ||
Brian Granger
|
r2245 | # We define this to track if a single BuiltinTrap is nested. | ||
# Only turn off the trap when the outermost call to __exit__ is made. | ||||
self._nested_level = 0 | ||||
Brian Granger
|
r2731 | self.shell = shell | ||
Erik Tollerud
|
r3185 | # builtins we always add - if set to HideBuiltin, they will just | ||
# be removed instead of being replaced by something else | ||||
self.auto_builtins = {'exit': HideBuiltin, | ||||
'quit': HideBuiltin, | ||||
Fernando Perez
|
r2957 | 'get_ipython': self.shell.get_ipython, | ||
} | ||||
# Recursive reload function | ||||
try: | ||||
from IPython.lib import deepreload | ||||
if self.shell.deep_reload: | ||||
Matthias Bussonnier
|
r21407 | from warnings import warn | ||
Matthias Bussonnier
|
r22406 | warn("Automatically replacing builtin `reload` by `deepreload.reload` is deprecated since IPython 4.0, please import `reload` explicitly from `IPython.lib.deepreload", DeprecationWarning) | ||
Matthias Bussonnier
|
r21407 | self.auto_builtins['reload'] = deepreload._dreload | ||
Fernando Perez
|
r2957 | else: | ||
Matthias Bussonnier
|
r21407 | self.auto_builtins['dreload']= deepreload._dreload | ||
Fernando Perez
|
r2957 | except ImportError: | ||
pass | ||||
Brian Granger
|
r2227 | |||
def __enter__(self): | ||||
Brian Granger
|
r2245 | if self._nested_level == 0: | ||
Fernando Perez
|
r2957 | self.activate() | ||
Brian Granger
|
r2245 | self._nested_level += 1 | ||
Brian Granger
|
r2227 | # I return self, so callers can use add_builtin in a with clause. | ||
return self | ||||
def __exit__(self, type, value, traceback): | ||||
Brian Granger
|
r2245 | if self._nested_level == 1: | ||
Fernando Perez
|
r2957 | self.deactivate() | ||
Brian Granger
|
r2245 | self._nested_level -= 1 | ||
Brian Granger
|
r2281 | # Returning False will cause exceptions to propagate | ||
return False | ||||
Brian Granger
|
r2227 | |||
def add_builtin(self, key, value): | ||||
"""Add a builtin and save the original.""" | ||||
Thomas Kluyver
|
r13351 | bdict = builtin_mod.__dict__ | ||
Fernando Perez
|
r2957 | orig = bdict.get(key, BuiltinUndefined) | ||
Erik Tollerud
|
r3185 | if value is HideBuiltin: | ||
Erik Tollerud
|
r3191 | if orig is not BuiltinUndefined: #same as 'key in bdict' | ||
self._orig_builtins[key] = orig | ||||
del bdict[key] | ||||
Erik Tollerud
|
r3185 | else: | ||
Erik Tollerud
|
r3191 | self._orig_builtins[key] = orig | ||
Erik Tollerud
|
r3185 | bdict[key] = value | ||
Brian Granger
|
r2227 | |||
Fernando Perez
|
r5491 | def remove_builtin(self, key, orig): | ||
Brian Granger
|
r2227 | """Remove an added builtin and re-set the original.""" | ||
Fernando Perez
|
r5491 | if orig is BuiltinUndefined: | ||
Thomas Kluyver
|
r13351 | del builtin_mod.__dict__[key] | ||
Brian Granger
|
r2227 | else: | ||
Thomas Kluyver
|
r13351 | builtin_mod.__dict__[key] = orig | ||
Brian Granger
|
r2227 | |||
Fernando Perez
|
r2957 | def activate(self): | ||
Brian Granger
|
r2227 | """Store ipython references in the __builtin__ namespace.""" | ||
Fernando Perez
|
r2957 | add_builtin = self.add_builtin | ||
Thomas Kluyver
|
r13361 | for name, func in iteritems(self.auto_builtins): | ||
Fernando Perez
|
r2957 | add_builtin(name, func) | ||
Brian Granger
|
r2227 | |||
Fernando Perez
|
r2957 | def deactivate(self): | ||
Brian Granger
|
r2227 | """Remove any builtins which might have been added by add_builtins, or | ||
restore overwritten ones to their previous values.""" | ||||
Fernando Perez
|
r2957 | remove_builtin = self.remove_builtin | ||
Thomas Kluyver
|
r13361 | for key, val in iteritems(self._orig_builtins): | ||
Fernando Perez
|
r5491 | remove_builtin(key, val) | ||
Brian Granger
|
r2227 | self._orig_builtins.clear() | ||
self._builtins_added = False | ||||