##// END OF EJS Templates
fixed bug introduced into builtin_trap due to 'quit' being removed twice - test suit now passes
Erik Tollerud -
Show More
@@ -1,126 +1,128 b''
1 """
1 """
2 A context manager for managing things injected into :mod:`__builtin__`.
2 A context manager for managing things injected into :mod:`__builtin__`.
3
3
4 Authors:
4 Authors:
5
5
6 * Brian Granger
6 * Brian Granger
7 * Fernando Perez
7 * Fernando Perez
8 """
8 """
9 #-----------------------------------------------------------------------------
9 #-----------------------------------------------------------------------------
10 # Copyright (C) 2010 The IPython Development Team.
10 # Copyright (C) 2010 The IPython Development Team.
11 #
11 #
12 # Distributed under the terms of the BSD License.
12 # Distributed under the terms of the BSD License.
13 #
13 #
14 # Complete license in the file COPYING.txt, distributed with this software.
14 # Complete license in the file COPYING.txt, distributed with this software.
15 #-----------------------------------------------------------------------------
15 #-----------------------------------------------------------------------------
16
16
17 #-----------------------------------------------------------------------------
17 #-----------------------------------------------------------------------------
18 # Imports
18 # Imports
19 #-----------------------------------------------------------------------------
19 #-----------------------------------------------------------------------------
20
20
21 import __builtin__
21 import __builtin__
22
22
23 from IPython.config.configurable import Configurable
23 from IPython.config.configurable import Configurable
24
24
25 from IPython.utils.traitlets import Instance
25 from IPython.utils.traitlets import Instance
26
26
27 #-----------------------------------------------------------------------------
27 #-----------------------------------------------------------------------------
28 # Classes and functions
28 # Classes and functions
29 #-----------------------------------------------------------------------------
29 #-----------------------------------------------------------------------------
30
30
31 class __BuiltinUndefined(object): pass
31 class __BuiltinUndefined(object): pass
32 BuiltinUndefined = __BuiltinUndefined()
32 BuiltinUndefined = __BuiltinUndefined()
33
33
34 class __HideBuiltin(object): pass
34 class __HideBuiltin(object): pass
35 HideBuiltin = __HideBuiltin()
35 HideBuiltin = __HideBuiltin()
36
36
37
37
38 class BuiltinTrap(Configurable):
38 class BuiltinTrap(Configurable):
39
39
40 shell = Instance('IPython.core.interactiveshell.InteractiveShellABC')
40 shell = Instance('IPython.core.interactiveshell.InteractiveShellABC')
41
41
42 def __init__(self, shell=None):
42 def __init__(self, shell=None):
43 super(BuiltinTrap, self).__init__(shell=shell, config=None)
43 super(BuiltinTrap, self).__init__(shell=shell, config=None)
44 self._orig_builtins = {}
44 self._orig_builtins = {}
45 # We define this to track if a single BuiltinTrap is nested.
45 # We define this to track if a single BuiltinTrap is nested.
46 # Only turn off the trap when the outermost call to __exit__ is made.
46 # Only turn off the trap when the outermost call to __exit__ is made.
47 self._nested_level = 0
47 self._nested_level = 0
48 self.shell = shell
48 self.shell = shell
49 # builtins we always add - if set to HideBuiltin, they will just
49 # builtins we always add - if set to HideBuiltin, they will just
50 # be removed instead of being replaced by something else
50 # be removed instead of being replaced by something else
51 self.auto_builtins = {'exit': HideBuiltin,
51 self.auto_builtins = {'exit': HideBuiltin,
52 'quit': HideBuiltin,
52 'quit': HideBuiltin,
53 'get_ipython': self.shell.get_ipython,
53 'get_ipython': self.shell.get_ipython,
54 }
54 }
55 # Recursive reload function
55 # Recursive reload function
56 try:
56 try:
57 from IPython.lib import deepreload
57 from IPython.lib import deepreload
58 if self.shell.deep_reload:
58 if self.shell.deep_reload:
59 self.auto_builtins['reload'] = deepreload.reload
59 self.auto_builtins['reload'] = deepreload.reload
60 else:
60 else:
61 self.auto_builtins['dreload']= deepreload.reload
61 self.auto_builtins['dreload']= deepreload.reload
62 except ImportError:
62 except ImportError:
63 pass
63 pass
64
64
65 def __enter__(self):
65 def __enter__(self):
66 if self._nested_level == 0:
66 if self._nested_level == 0:
67 self.activate()
67 self.activate()
68 self._nested_level += 1
68 self._nested_level += 1
69 # I return self, so callers can use add_builtin in a with clause.
69 # I return self, so callers can use add_builtin in a with clause.
70 return self
70 return self
71
71
72 def __exit__(self, type, value, traceback):
72 def __exit__(self, type, value, traceback):
73 if self._nested_level == 1:
73 if self._nested_level == 1:
74 self.deactivate()
74 self.deactivate()
75 self._nested_level -= 1
75 self._nested_level -= 1
76 # Returning False will cause exceptions to propagate
76 # Returning False will cause exceptions to propagate
77 return False
77 return False
78
78
79 def add_builtin(self, key, value):
79 def add_builtin(self, key, value):
80 """Add a builtin and save the original."""
80 """Add a builtin and save the original."""
81 bdict = __builtin__.__dict__
81 bdict = __builtin__.__dict__
82 orig = bdict.get(key, BuiltinUndefined)
82 orig = bdict.get(key, BuiltinUndefined)
83 self._orig_builtins[key] = orig
84 if value is HideBuiltin:
83 if value is HideBuiltin:
85 del bdict[key]
84 if orig is not BuiltinUndefined: #same as 'key in bdict'
85 self._orig_builtins[key] = orig
86 del bdict[key]
86 else:
87 else:
88 self._orig_builtins[key] = orig
87 bdict[key] = value
89 bdict[key] = value
88
90
89 def remove_builtin(self, key):
91 def remove_builtin(self, key):
90 """Remove an added builtin and re-set the original."""
92 """Remove an added builtin and re-set the original."""
91 try:
93 try:
92 orig = self._orig_builtins.pop(key)
94 orig = self._orig_builtins.pop(key)
93 except KeyError:
95 except KeyError:
94 pass
96 pass
95 else:
97 else:
96 if orig is BuiltinUndefined:
98 if orig is BuiltinUndefined:
97 del __builtin__.__dict__[key]
99 del __builtin__.__dict__[key]
98 else:
100 else:
99 __builtin__.__dict__[key] = orig
101 __builtin__.__dict__[key] = orig
100
102
101 def activate(self):
103 def activate(self):
102 """Store ipython references in the __builtin__ namespace."""
104 """Store ipython references in the __builtin__ namespace."""
103
105
104 add_builtin = self.add_builtin
106 add_builtin = self.add_builtin
105 for name, func in self.auto_builtins.iteritems():
107 for name, func in self.auto_builtins.iteritems():
106 add_builtin(name, func)
108 add_builtin(name, func)
107
109
108 # Keep in the builtins a flag for when IPython is active. We set it
110 # Keep in the builtins a flag for when IPython is active. We set it
109 # with setdefault so that multiple nested IPythons don't clobber one
111 # with setdefault so that multiple nested IPythons don't clobber one
110 # another.
112 # another.
111 __builtin__.__dict__.setdefault('__IPYTHON__active', 0)
113 __builtin__.__dict__.setdefault('__IPYTHON__active', 0)
112
114
113 def deactivate(self):
115 def deactivate(self):
114 """Remove any builtins which might have been added by add_builtins, or
116 """Remove any builtins which might have been added by add_builtins, or
115 restore overwritten ones to their previous values."""
117 restore overwritten ones to their previous values."""
116 # Note: must iterate over a static keys() list because we'll be
118 # Note: must iterate over a static keys() list because we'll be
117 # mutating the dict itself
119 # mutating the dict itself
118 remove_builtin = self.remove_builtin
120 remove_builtin = self.remove_builtin
119 for key in self._orig_builtins.keys():
121 for key in self._orig_builtins.keys():
120 remove_builtin(key)
122 remove_builtin(key)
121 self._orig_builtins.clear()
123 self._orig_builtins.clear()
122 self._builtins_added = False
124 self._builtins_added = False
123 try:
125 try:
124 del __builtin__.__dict__['__IPYTHON__active']
126 del __builtin__.__dict__['__IPYTHON__active']
125 except KeyError:
127 except KeyError:
126 pass
128 pass
General Comments 0
You need to be logged in to leave comments. Login now