##// END OF EJS Templates
Merging Brian's work on branch: lp:~ipython-dev/ipython/kernel-config...
Merging Brian's work on branch: lp:~ipython-dev/ipython/kernel-config This makes trunk significantly more usable again.

File last commit:

r2312:fff2b380
r2352:48bf2e26 merge
Show More
builtin_trap.py
118 lines | 4.0 KiB | text/x-python | PythonLexer
#!/usr/bin/env python
# encoding: utf-8
"""
A context manager for managing things injected into :mod:`__builtin__`.
Authors:
* Brian Granger
"""
#-----------------------------------------------------------------------------
# Copyright (C) 2008-2009 The IPython Development Team
#
# Distributed under the terms of the BSD License. The full license is in
# the file COPYING, distributed as part of this software.
#-----------------------------------------------------------------------------
#-----------------------------------------------------------------------------
# Imports
#-----------------------------------------------------------------------------
import __builtin__
from IPython.core.component import Component
from IPython.core.quitter import Quitter
from IPython.utils.autoattr import auto_attr
#-----------------------------------------------------------------------------
# Classes and functions
#-----------------------------------------------------------------------------
class BuiltinUndefined(object): pass
BuiltinUndefined = BuiltinUndefined()
class BuiltinTrap(Component):
def __init__(self, parent):
super(BuiltinTrap, self).__init__(parent, None, 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
@auto_attr
def shell(self):
return Component.get_instances(
root=self.root,
klass='IPython.core.iplib.InteractiveShell')[0]
def __enter__(self):
if self._nested_level == 0:
self.set()
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.unset()
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."""
orig = __builtin__.__dict__.get(key, BuiltinUndefined)
self._orig_builtins[key] = orig
__builtin__.__dict__[key] = value
def remove_builtin(self, key):
"""Remove an added builtin and re-set the original."""
try:
orig = self._orig_builtins.pop(key)
except KeyError:
pass
else:
if orig is BuiltinUndefined:
del __builtin__.__dict__[key]
else:
__builtin__.__dict__[key] = orig
def set(self):
"""Store ipython references in the __builtin__ namespace."""
self.add_builtin('exit', Quitter(self.shell, 'exit'))
self.add_builtin('quit', Quitter(self.shell, 'quit'))
self.add_builtin('get_ipython', self.shell.get_ipython)
# Recursive reload function
try:
from IPython.lib import deepreload
if self.shell.deep_reload:
self.add_builtin('reload', deepreload.reload)
else:
self.add_builtin('dreload', deepreload.reload)
del deepreload
except ImportError:
pass
# Keep in the builtins a flag for when IPython is active. We set it
# with setdefault so that multiple nested IPythons don't clobber one
# another. Each will increase its value by one upon being activated,
# which also gives us a way to determine the nesting level.
__builtin__.__dict__.setdefault('__IPYTHON__active',0)
def unset(self):
"""Remove any builtins which might have been added by add_builtins, or
restore overwritten ones to their previous values."""
for key in self._orig_builtins.keys():
self.remove_builtin(key)
self._orig_builtins.clear()
self._builtins_added = False
try:
del __builtin__.__dict__['__IPYTHON__active']
except KeyError:
pass