##// END OF EJS Templates
Speedup builtin_trap enter/exit by reducing object creation....
Fernando Perez -
Show More
@@ -1,18 +1,17 b''
1 #!/usr/bin/env python
2 # encoding: utf-8
3 """
1 """
4 A context manager for managing things injected into :mod:`__builtin__`.
2 A context manager for managing things injected into :mod:`__builtin__`.
5
3
6 Authors:
4 Authors:
7
5
8 * Brian Granger
6 * Brian Granger
7 * Fernando Perez
9 """
8 """
10
11 #-----------------------------------------------------------------------------
9 #-----------------------------------------------------------------------------
12 # Copyright (C) 2008-2009 The IPython Development Team
10 # Copyright (C) 2010 The IPython Development Team.
11 #
12 # Distributed under the terms of the BSD License.
13 #
13 #
14 # Distributed under the terms of the BSD License. The full license is in
14 # Complete license in the file COPYING.txt, distributed with this software.
15 # the file COPYING, distributed as part of this software.
16 #-----------------------------------------------------------------------------
15 #-----------------------------------------------------------------------------
17
16
18 #-----------------------------------------------------------------------------
17 #-----------------------------------------------------------------------------
@@ -30,7 +29,6 b' from IPython.utils.traitlets import Instance'
30 # Classes and functions
29 # Classes and functions
31 #-----------------------------------------------------------------------------
30 #-----------------------------------------------------------------------------
32
31
33
34 class __BuiltinUndefined(object): pass
32 class __BuiltinUndefined(object): pass
35 BuiltinUndefined = __BuiltinUndefined()
33 BuiltinUndefined = __BuiltinUndefined()
36
34
@@ -46,26 +44,41 b' class BuiltinTrap(Configurable):'
46 # Only turn off the trap when the outermost call to __exit__ is made.
44 # Only turn off the trap when the outermost call to __exit__ is made.
47 self._nested_level = 0
45 self._nested_level = 0
48 self.shell = shell
46 self.shell = shell
47 # builtins we always add
48 self.auto_builtins = {'exit': Quitter(self.shell, 'exit'),
49 'quit': Quitter(self.shell, 'quit'),
50 'get_ipython': self.shell.get_ipython,
51 }
52 # Recursive reload function
53 try:
54 from IPython.lib import deepreload
55 if self.shell.deep_reload:
56 self.auto_builtins['reload'] = deepreload.reload
57 else:
58 self.auto_builtins['dreload']= deepreload.reload
59 except ImportError:
60 pass
49
61
50 def __enter__(self):
62 def __enter__(self):
51 if self._nested_level == 0:
63 if self._nested_level == 0:
52 self.set()
64 self.activate()
53 self._nested_level += 1
65 self._nested_level += 1
54 # I return self, so callers can use add_builtin in a with clause.
66 # I return self, so callers can use add_builtin in a with clause.
55 return self
67 return self
56
68
57 def __exit__(self, type, value, traceback):
69 def __exit__(self, type, value, traceback):
58 if self._nested_level == 1:
70 if self._nested_level == 1:
59 self.unset()
71 self.deactivate()
60 self._nested_level -= 1
72 self._nested_level -= 1
61 # Returning False will cause exceptions to propagate
73 # Returning False will cause exceptions to propagate
62 return False
74 return False
63
75
64 def add_builtin(self, key, value):
76 def add_builtin(self, key, value):
65 """Add a builtin and save the original."""
77 """Add a builtin and save the original."""
66 orig = __builtin__.__dict__.get(key, BuiltinUndefined)
78 bdict = __builtin__.__dict__
79 orig = bdict.get(key, BuiltinUndefined)
67 self._orig_builtins[key] = orig
80 self._orig_builtins[key] = orig
68 __builtin__.__dict__[key] = value
81 bdict[key] = value
69
82
70 def remove_builtin(self, key):
83 def remove_builtin(self, key):
71 """Remove an added builtin and re-set the original."""
84 """Remove an added builtin and re-set the original."""
@@ -79,34 +92,26 b' class BuiltinTrap(Configurable):'
79 else:
92 else:
80 __builtin__.__dict__[key] = orig
93 __builtin__.__dict__[key] = orig
81
94
82 def set(self):
95 def activate(self):
83 """Store ipython references in the __builtin__ namespace."""
96 """Store ipython references in the __builtin__ namespace."""
84 self.add_builtin('exit', Quitter(self.shell, 'exit'))
85 self.add_builtin('quit', Quitter(self.shell, 'quit'))
86 self.add_builtin('get_ipython', self.shell.get_ipython)
87
97
88 # Recursive reload function
98 add_builtin = self.add_builtin
89 try:
99 for name, func in self.auto_builtins.iteritems():
90 from IPython.lib import deepreload
100 add_builtin(name, func)
91 if self.shell.deep_reload:
92 self.add_builtin('reload', deepreload.reload)
93 else:
94 self.add_builtin('dreload', deepreload.reload)
95 del deepreload
96 except ImportError:
97 pass
98
101
99 # Keep in the builtins a flag for when IPython is active. We set it
102 # Keep in the builtins a flag for when IPython is active. We set it
100 # with setdefault so that multiple nested IPythons don't clobber one
103 # with setdefault so that multiple nested IPythons don't clobber one
101 # another. Each will increase its value by one upon being activated,
104 # another.
102 # which also gives us a way to determine the nesting level.
103 __builtin__.__dict__.setdefault('__IPYTHON__active',0)
105 __builtin__.__dict__.setdefault('__IPYTHON__active', 0)
104
106
105 def unset(self):
107 def deactivate(self):
106 """Remove any builtins which might have been added by add_builtins, or
108 """Remove any builtins which might have been added by add_builtins, or
107 restore overwritten ones to their previous values."""
109 restore overwritten ones to their previous values."""
110 # Note: must iterate over a static keys() list because we'll be
111 # mutating the dict itself
112 remove_builtin = self.remove_builtin
108 for key in self._orig_builtins.keys():
113 for key in self._orig_builtins.keys():
109 self.remove_builtin(key)
114 remove_builtin(key)
110 self._orig_builtins.clear()
115 self._orig_builtins.clear()
111 self._builtins_added = False
116 self._builtins_added = False
112 try:
117 try:
@@ -144,7 +144,7 b' def start_ipython():'
144
144
145 # These traps are normally only active for interactive use, set them
145 # These traps are normally only active for interactive use, set them
146 # permanently since we'll be mocking interactive sessions.
146 # permanently since we'll be mocking interactive sessions.
147 shell.builtin_trap.set()
147 shell.builtin_trap.activate()
148
148
149 # Modify the IPython system call with one that uses getoutput, so that we
149 # Modify the IPython system call with one that uses getoutput, so that we
150 # can capture subcommands and print them to Python's stdout, otherwise the
150 # can capture subcommands and print them to Python's stdout, otherwise the
General Comments 0
You need to be logged in to leave comments. Login now