""" A context manager for managing things injected into :mod:`builtins`. """ # Copyright (c) IPython Development Team. # Distributed under the terms of the Modified BSD License. import builtins as builtin_mod from traitlets.config.configurable import Configurable from traitlets import Instance class __BuiltinUndefined(object): pass BuiltinUndefined = __BuiltinUndefined() class __HideBuiltin(object): pass HideBuiltin = __HideBuiltin() class BuiltinTrap(Configurable): shell = Instance('IPython.core.interactiveshell.InteractiveShellABC', allow_none=True) def __init__(self, shell=None): super(BuiltinTrap, self).__init__(shell=shell, config=None) self._orig_builtins = {} # 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 self.shell = shell # 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, 'get_ipython': self.shell.get_ipython, } def __enter__(self): if self._nested_level == 0: self.activate() self._nested_level += 1 # I return self, so callers can use add_builtin in a with clause. return self def __exit__(self, type, value, traceback): if self._nested_level == 1: self.deactivate() self._nested_level -= 1 # Returning False will cause exceptions to propagate return False def add_builtin(self, key, value): """Add a builtin and save the original.""" bdict = builtin_mod.__dict__ orig = bdict.get(key, BuiltinUndefined) if value is HideBuiltin: if orig is not BuiltinUndefined: #same as 'key in bdict' self._orig_builtins[key] = orig del bdict[key] else: self._orig_builtins[key] = orig bdict[key] = value def remove_builtin(self, key, orig): """Remove an added builtin and re-set the original.""" if orig is BuiltinUndefined: del builtin_mod.__dict__[key] else: builtin_mod.__dict__[key] = orig def activate(self): """Store ipython references in the __builtin__ namespace.""" add_builtin = self.add_builtin for name, func in self.auto_builtins.items(): add_builtin(name, func) def deactivate(self): """Remove any builtins which might have been added by add_builtins, or restore overwritten ones to their previous values.""" remove_builtin = self.remove_builtin for key, val in self._orig_builtins.items(): remove_builtin(key, val) self._orig_builtins.clear() self._builtins_added = False