##// END OF EJS Templates
Created context manager for the things injected into __builtin__.
Brian Granger -
Show More
@@ -0,0 +1,104 b''
1 #!/usr/bin/env python
2 # encoding: utf-8
3 """
4 A context manager for managing things injected into :mod:`__builtin__`.
5
6 Authors:
7
8 * Brian Granger
9 """
10
11 #-----------------------------------------------------------------------------
12 # Copyright (C) 2008-2009 The IPython Development Team
13 #
14 # Distributed under the terms of the BSD License. The full license is in
15 # the file COPYING, distributed as part of this software.
16 #-----------------------------------------------------------------------------
17
18 #-----------------------------------------------------------------------------
19 # Imports
20 #-----------------------------------------------------------------------------
21
22 import __builtin__
23
24 from IPython.core.component import Component
25 from IPython.core.quitter import Quitter
26
27 #-----------------------------------------------------------------------------
28 # Classes and functions
29 #-----------------------------------------------------------------------------
30
31
32 class BuiltinUndefined(object): pass
33 BuiltinUndefined = BuiltinUndefined()
34
35
36 class BuiltinTrap(Component):
37
38 def __init__(self, parent, name=None, config=None):
39 super(BuiltinTrap, self).__init__(parent, name, config)
40 # Don't just grab parent!!!
41 from IPython.core.iplib import InteractiveShell
42 self.shell = InteractiveShell.get_instances(root=self.root)[0]
43 self._orig_builtins = {}
44
45 def __enter__(self):
46 self.set()
47 # I return self, so callers can use add_builtin in a with clause.
48 return self
49
50 def __exit__(self, type, value, traceback):
51 self.unset()
52 return True
53
54 def add_builtin(self, key, value):
55 """Add a builtin and save the original."""
56 orig = __builtin__.__dict__.get(key, BuiltinUndefined)
57 self._orig_builtins[key] = orig
58 __builtin__.__dict__[key] = value
59
60 def remove_builtin(self, key):
61 """Remove an added builtin and re-set the original."""
62 try:
63 orig = self._orig_builtins.pop(key)
64 except KeyError:
65 pass
66 else:
67 if orig is BuiltinUndefined:
68 del __builtin__.__dict__[key]
69 else:
70 __builtin__.__dict__[key] = orig
71
72 def set(self):
73 """Store ipython references in the __builtin__ namespace."""
74 self.add_builtin('exit', Quitter(self.shell, 'exit'))
75 self.add_builtin('quit', Quitter(self.shell, 'quit'))
76
77 # Recursive reload function
78 try:
79 from IPython.lib import deepreload
80 if self.shell.deep_reload:
81 self.add_builtin('reload', deepreload.reload)
82 else:
83 self.add_builtin('dreload', deepreload.reload)
84 del deepreload
85 except ImportError:
86 pass
87
88 # Keep in the builtins a flag for when IPython is active. We set it
89 # with setdefault so that multiple nested IPythons don't clobber one
90 # another. Each will increase its value by one upon being activated,
91 # which also gives us a way to determine the nesting level.
92 __builtin__.__dict__.setdefault('__IPYTHON__active',0)
93
94 def unset(self):
95 """Remove any builtins which might have been added by add_builtins, or
96 restore overwritten ones to their previous values."""
97 for key in self._orig_builtins.keys():
98 self.remove_builtin(key)
99 self._orig_builtins.clear()
100 self._builtins_added = False
101 try:
102 del __builtin__.__dict__['__IPYTHON__active']
103 except KeyError:
104 pass No newline at end of file
@@ -0,0 +1,38 b''
1 #!/usr/bin/env python
2 # encoding: utf-8
3 """
4 A simple class for quitting IPython.
5
6 Authors:
7
8 * Brian Granger
9 """
10
11 #-----------------------------------------------------------------------------
12 # Copyright (C) 2008-2009 The IPython Development Team
13 #
14 # Distributed under the terms of the BSD License. The full license is in
15 # the file COPYING, distributed as part of this software.
16 #-----------------------------------------------------------------------------
17
18 #-----------------------------------------------------------------------------
19 # Imports
20 #-----------------------------------------------------------------------------
21
22
23 class Quitter(object):
24 """Simple class to handle exit, similar to Python 2.5's.
25
26 It handles exiting in an ipython-safe manner, which the one in Python 2.5
27 doesn't do (obviously, since it doesn't know about ipython)."""
28
29 def __init__(self, shell, name):
30 self.shell = shell
31 self.name = name
32
33 def __repr__(self):
34 return 'Type %s() to exit.' % self.name
35 __str__ = __repr__
36
37 def __call__(self):
38 self.shell.exit() No newline at end of file
@@ -52,15 +52,19 b' class MetaComponentTracker(type):'
52 When a Component or subclass is instantiated, this is called and
52 When a Component or subclass is instantiated, this is called and
53 the instance is saved in a WeakValueDictionary for tracking.
53 the instance is saved in a WeakValueDictionary for tracking.
54 """
54 """
55
55 instance = cls.__new__(cls, *args, **kw)
56 instance = super(MetaComponentTracker, cls).__call__(*args, **kw)
56 # Do this before __init__ is called so get_instances works inside
57 # __init__ methods!
57 for c in cls.__mro__:
58 for c in cls.__mro__:
58 if issubclass(cls, c) and issubclass(c, Component):
59 if issubclass(cls, c) and issubclass(c, Component):
59 c.__numcreated += 1
60 c.__numcreated += 1
60 c.__instance_refs[c.__numcreated] = instance
61 c.__instance_refs[c.__numcreated] = instance
62 if isinstance(instance, cls):
63 cls.__init__(instance, *args, **kw)
64
61 return instance
65 return instance
62
66
63 def get_instances(cls, name=None, root=None):
67 def get_instances(cls, name=None, root=None, classname=None):
64 """Get all instances of cls and its subclasses.
68 """Get all instances of cls and its subclasses.
65
69
66 Parameters
70 Parameters
@@ -69,21 +73,26 b' class MetaComponentTracker(type):'
69 Limit to components with this name.
73 Limit to components with this name.
70 root : Component or subclass
74 root : Component or subclass
71 Limit to components having this root.
75 Limit to components having this root.
76 classname : str
77 The string name of a class to match exactly.
72 """
78 """
73 instances = cls.__instance_refs.values()
79 instances = cls.__instance_refs.values()
74 if name is not None:
80 if name is not None:
75 instances = [i for i in instances if i.name == name]
81 instances = [i for i in instances if i.name == name]
82 if classname is not None:
83 instances = [i for i in instances if i.__class__.__name__ == classname]
76 if root is not None:
84 if root is not None:
77 instances = [i for i in instances if i.root == root]
85 instances = [i for i in instances if i.root == root]
78 return instances
86 return instances
79
87
80 def get_instances_by_condition(cls, call, name=None, root=None):
88 def get_instances_by_condition(cls, call, name=None, root=None,
89 classname=None):
81 """Get all instances of cls, i such that call(i)==True.
90 """Get all instances of cls, i such that call(i)==True.
82
91
83 This also takes the ``name`` and ``root`` arguments of
92 This also takes the ``name`` and ``root`` and ``classname``
84 :meth:`get_instance`
93 arguments of :meth:`get_instance`
85 """
94 """
86 return [i for i in cls.get_instances(name, root) if call(i)]
95 return [i for i in cls.get_instances(name, root, classname) if call(i)]
87
96
88
97
89 class ComponentNameGenerator(object):
98 class ComponentNameGenerator(object):
@@ -23,6 +23,8 b' Notes'
23 # Imports
23 # Imports
24 #-----------------------------------------------------------------------------
24 #-----------------------------------------------------------------------------
25
25
26 from __future__ import with_statement
27
26 import sys
28 import sys
27
29
28 from IPython.core import ultratb
30 from IPython.core import ultratb
@@ -63,7 +65,7 b' class InteractiveShellEmbed(InteractiveShell):'
63 def __init__(self, parent=None, config=None, ipythondir=None, usage=None,
65 def __init__(self, parent=None, config=None, ipythondir=None, usage=None,
64 user_ns=None, user_global_ns=None,
66 user_ns=None, user_global_ns=None,
65 banner1=None, banner2=None,
67 banner1=None, banner2=None,
66 custom_exceptions=((),None), exit_msg=None):
68 custom_exceptions=((),None), exit_msg=''):
67
69
68 # First we need to save the state of sys.displayhook and
70 # First we need to save the state of sys.displayhook and
69 # sys.ipcompleter so we can restore it when we are done.
71 # sys.ipcompleter so we can restore it when we are done.
@@ -172,7 +174,7 b' class InteractiveShellEmbed(InteractiveShell):'
172
174
173 # Call the embedding code with a stack depth of 1 so it can skip over
175 # Call the embedding code with a stack depth of 1 so it can skip over
174 # our call and get the original caller's namespaces.
176 # our call and get the original caller's namespaces.
175 self.embed_mainloop(banner, local_ns, global_ns,
177 self.mainloop(banner, local_ns, global_ns,
176 stack_depth=stack_depth)
178 stack_depth=stack_depth)
177
179
178 if self.exit_msg is not None:
180 if self.exit_msg is not None:
@@ -182,6 +184,71 b' class InteractiveShellEmbed(InteractiveShell):'
182 self.restore_sys_displayhook()
184 self.restore_sys_displayhook()
183 self.restore_sys_ipcompleter()
185 self.restore_sys_ipcompleter()
184
186
187 def mainloop(self,header='',local_ns=None,global_ns=None,stack_depth=0):
188 """Embeds IPython into a running python program.
189
190 Input:
191
192 - header: An optional header message can be specified.
193
194 - local_ns, global_ns: working namespaces. If given as None, the
195 IPython-initialized one is updated with __main__.__dict__, so that
196 program variables become visible but user-specific configuration
197 remains possible.
198
199 - stack_depth: specifies how many levels in the stack to go to
200 looking for namespaces (when local_ns and global_ns are None). This
201 allows an intermediate caller to make sure that this function gets
202 the namespace from the intended level in the stack. By default (0)
203 it will get its locals and globals from the immediate caller.
204
205 Warning: it's possible to use this in a program which is being run by
206 IPython itself (via %run), but some funny things will happen (a few
207 globals get overwritten). In the future this will be cleaned up, as
208 there is no fundamental reason why it can't work perfectly."""
209
210 # Get locals and globals from caller
211 if local_ns is None or global_ns is None:
212 call_frame = sys._getframe(stack_depth).f_back
213
214 if local_ns is None:
215 local_ns = call_frame.f_locals
216 if global_ns is None:
217 global_ns = call_frame.f_globals
218
219 # Update namespaces and fire up interpreter
220
221 # The global one is easy, we can just throw it in
222 self.user_global_ns = global_ns
223
224 # but the user/local one is tricky: ipython needs it to store internal
225 # data, but we also need the locals. We'll copy locals in the user
226 # one, but will track what got copied so we can delete them at exit.
227 # This is so that a later embedded call doesn't see locals from a
228 # previous call (which most likely existed in a separate scope).
229 local_varnames = local_ns.keys()
230 self.user_ns.update(local_ns)
231 #self.user_ns['local_ns'] = local_ns # dbg
232
233 # Patch for global embedding to make sure that things don't overwrite
234 # user globals accidentally. Thanks to Richard <rxe@renre-europe.com>
235 # FIXME. Test this a bit more carefully (the if.. is new)
236 if local_ns is None and global_ns is None:
237 self.user_global_ns.update(__main__.__dict__)
238
239 # make sure the tab-completer has the correct frame information, so it
240 # actually completes using the frame's locals/globals
241 self.set_completer_frame()
242
243 with self.builtin_trap:
244 self.interact(header)
245
246 # now, purge out the user namespace from anything we might have added
247 # from the caller's local namespace
248 delvar = self.user_ns.pop
249 for var in local_varnames:
250 delvar(var,None)
251
185
252
186 _embedded_shell = None
253 _embedded_shell = None
187
254
@@ -16,6 +16,8 b' Main IPython Component'
16 # Imports
16 # Imports
17 #-----------------------------------------------------------------------------
17 #-----------------------------------------------------------------------------
18
18
19 from __future__ import with_statement
20
19 import __main__
21 import __main__
20 import __builtin__
22 import __builtin__
21 import StringIO
23 import StringIO
@@ -38,6 +40,7 b' from IPython.core import shadowns'
38 from IPython.core import history as ipcorehist
40 from IPython.core import history as ipcorehist
39 from IPython.core import prefilter
41 from IPython.core import prefilter
40 from IPython.core.autocall import IPyAutocall
42 from IPython.core.autocall import IPyAutocall
43 from IPython.core.builtin_trap import BuiltinTrap
41 from IPython.core.fakemodule import FakeModule, init_fakemod_dict
44 from IPython.core.fakemodule import FakeModule, init_fakemod_dict
42 from IPython.core.logger import Logger
45 from IPython.core.logger import Logger
43 from IPython.core.magic import Magic
46 from IPython.core.magic import Magic
@@ -112,28 +115,6 b' class SpaceInInput(exceptions.Exception): pass'
112
115
113 class Bunch: pass
116 class Bunch: pass
114
117
115 class BuiltinUndefined: pass
116 BuiltinUndefined = BuiltinUndefined()
117
118
119 class Quitter(object):
120 """Simple class to handle exit, similar to Python 2.5's.
121
122 It handles exiting in an ipython-safe manner, which the one in Python 2.5
123 doesn't do (obviously, since it doesn't know about ipython)."""
124
125 def __init__(self, shell, name):
126 self.shell = shell
127 self.name = name
128
129 def __repr__(self):
130 return 'Type %s() to exit.' % self.name
131 __str__ = __repr__
132
133 def __call__(self):
134 self.shell.exit()
135
136
137 class InputList(list):
118 class InputList(list):
138 """Class to store user input.
119 """Class to store user input.
139
120
@@ -340,7 +321,6 b' class InteractiveShell(Component, Magic):'
340 self.hooks.late_startup_hook()
321 self.hooks.late_startup_hook()
341
322
342 def cleanup(self):
323 def cleanup(self):
343 self.remove_builtins()
344 self.restore_sys_module_state()
324 self.restore_sys_module_state()
345
325
346 #-------------------------------------------------------------------------
326 #-------------------------------------------------------------------------
@@ -834,10 +814,7 b' class InteractiveShell(Component, Magic):'
834 self.magic_alias(alias)
814 self.magic_alias(alias)
835
815
836 def init_builtins(self):
816 def init_builtins(self):
837 # track which builtins we add, so we can clean up later
817 self.builtin_trap = BuiltinTrap(self)
838 self._orig_builtins = {}
839 self._builtins_added = False
840 self.add_builtins()
841
818
842 def init_shadow_hist(self):
819 def init_shadow_hist(self):
843 try:
820 try:
@@ -1075,60 +1052,6 b' class InteractiveShell(Component, Magic):'
1075 except ImportError:
1052 except ImportError:
1076 warn('help() not available - check site.py')
1053 warn('help() not available - check site.py')
1077
1054
1078 def add_builtin(self, key, value):
1079 """Add a builtin and save the original."""
1080 orig = __builtin__.__dict__.get(key, BuiltinUndefined)
1081 self._orig_builtins[key] = orig
1082 __builtin__.__dict__[key] = value
1083
1084 def remove_builtin(self, key):
1085 """Remove an added builtin and re-set the original."""
1086 try:
1087 orig = self._orig_builtins.pop(key)
1088 except KeyError:
1089 pass
1090 else:
1091 if orig is BuiltinUndefined:
1092 del __builtin__.__dict__[key]
1093 else:
1094 __builtin__.__dict__[key] = orig
1095
1096 def add_builtins(self):
1097 """Store ipython references into the __builtin__ namespace.
1098
1099 We strive to modify the __builtin__ namespace as little as possible.
1100 """
1101 if not self._builtins_added:
1102 self.add_builtin('exit', Quitter(self,'exit'))
1103 self.add_builtin('quit', Quitter(self,'quit'))
1104
1105 # Recursive reload function
1106 try:
1107 from IPython.lib import deepreload
1108 if self.deep_reload:
1109 self.add_builtin('reload', deepreload.reload)
1110 else:
1111 self.add_builtin('dreload', deepreload.reload)
1112 del deepreload
1113 except ImportError:
1114 pass
1115
1116 # Keep in the builtins a flag for when IPython is active. We set it
1117 # with setdefault so that multiple nested IPythons don't clobber one
1118 # another. Each will increase its value by one upon being activated,
1119 # which also gives us a way to determine the nesting level.
1120 __builtin__.__dict__.setdefault('__IPYTHON__active',0)
1121 self._builtins_added = True
1122
1123 def remove_builtins(self):
1124 """Remove any builtins which might have been added by add_builtins, or
1125 restore overwritten ones to their previous values."""
1126 if self._builtins_added:
1127 for key in self._orig_builtins.keys():
1128 self.remove_builtin(key)
1129 self._orig_builtins.clear()
1130 self._builtins_added = False
1131
1132 def save_sys_module_state(self):
1055 def save_sys_module_state(self):
1133 """Save the state of hooks in the sys module.
1056 """Save the state of hooks in the sys module.
1134
1057
@@ -1328,7 +1251,9 b' class InteractiveShell(Component, Magic):'
1328 error("Magic function `%s` not found." % magic_name)
1251 error("Magic function `%s` not found." % magic_name)
1329 else:
1252 else:
1330 magic_args = self.var_expand(magic_args,1)
1253 magic_args = self.var_expand(magic_args,1)
1331 return fn(magic_args)
1254 with self.builtin_trap:
1255 result = fn(magic_args)
1256 return result
1332
1257
1333 def define_magic(self, magicname, func):
1258 def define_magic(self, magicname, func):
1334 """Expose own function as magic function for ipython
1259 """Expose own function as magic function for ipython
@@ -1423,6 +1348,7 b' class InteractiveShell(Component, Magic):'
1423
1348
1424 def ex(self, cmd):
1349 def ex(self, cmd):
1425 """Execute a normal python statement in user namespace."""
1350 """Execute a normal python statement in user namespace."""
1351 with self.builtin_trap:
1426 exec cmd in self.user_global_ns, self.user_ns
1352 exec cmd in self.user_global_ns, self.user_ns
1427
1353
1428 def ev(self, expr):
1354 def ev(self, expr):
@@ -1430,7 +1356,9 b' class InteractiveShell(Component, Magic):'
1430
1356
1431 Returns the result of evaluation
1357 Returns the result of evaluation
1432 """
1358 """
1433 return eval(expr, self.user_global_ns, self.user_ns)
1359 with self.builtin_trap:
1360 result = eval(expr, self.user_global_ns, self.user_ns)
1361 return result
1434
1362
1435 def getoutput(self, cmd):
1363 def getoutput(self, cmd):
1436 return getoutput(self.var_expand(cmd,depth=2),
1364 return getoutput(self.var_expand(cmd,depth=2),
@@ -1468,6 +1396,8 b' class InteractiveShell(Component, Magic):'
1468 Out[10]: ['x.ljust', 'x.lower', 'x.lstrip']
1396 Out[10]: ['x.ljust', 'x.lower', 'x.lstrip']
1469 """
1397 """
1470
1398
1399 # Inject names into __builtin__ so we can complete on the added names.
1400 with self.builtin_trap:
1471 complete = self.Completer.complete
1401 complete = self.Completer.complete
1472 state = 0
1402 state = 0
1473 # use a dict so we get unique keys, since ipyhton's multiple
1403 # use a dict so we get unique keys, since ipyhton's multiple
@@ -1875,6 +1805,8 b' class InteractiveShell(Component, Magic):'
1875 If an optional banner argument is given, it will override the
1805 If an optional banner argument is given, it will override the
1876 internally created default banner.
1806 internally created default banner.
1877 """
1807 """
1808
1809 with self.builtin_trap:
1878 if self.c: # Emulate Python's -c option
1810 if self.c: # Emulate Python's -c option
1879 self.exec_init_cmd()
1811 self.exec_init_cmd()
1880
1812
@@ -1909,77 +1841,6 b' class InteractiveShell(Component, Magic):'
1909 if not self.interactive:
1841 if not self.interactive:
1910 self.ask_exit()
1842 self.ask_exit()
1911
1843
1912 def embed_mainloop(self,header='',local_ns=None,global_ns=None,stack_depth=0):
1913 """Embeds IPython into a running python program.
1914
1915 Input:
1916
1917 - header: An optional header message can be specified.
1918
1919 - local_ns, global_ns: working namespaces. If given as None, the
1920 IPython-initialized one is updated with __main__.__dict__, so that
1921 program variables become visible but user-specific configuration
1922 remains possible.
1923
1924 - stack_depth: specifies how many levels in the stack to go to
1925 looking for namespaces (when local_ns and global_ns are None). This
1926 allows an intermediate caller to make sure that this function gets
1927 the namespace from the intended level in the stack. By default (0)
1928 it will get its locals and globals from the immediate caller.
1929
1930 Warning: it's possible to use this in a program which is being run by
1931 IPython itself (via %run), but some funny things will happen (a few
1932 globals get overwritten). In the future this will be cleaned up, as
1933 there is no fundamental reason why it can't work perfectly."""
1934
1935 # Get locals and globals from caller
1936 if local_ns is None or global_ns is None:
1937 call_frame = sys._getframe(stack_depth).f_back
1938
1939 if local_ns is None:
1940 local_ns = call_frame.f_locals
1941 if global_ns is None:
1942 global_ns = call_frame.f_globals
1943
1944 # Update namespaces and fire up interpreter
1945
1946 # The global one is easy, we can just throw it in
1947 self.user_global_ns = global_ns
1948
1949 # but the user/local one is tricky: ipython needs it to store internal
1950 # data, but we also need the locals. We'll copy locals in the user
1951 # one, but will track what got copied so we can delete them at exit.
1952 # This is so that a later embedded call doesn't see locals from a
1953 # previous call (which most likely existed in a separate scope).
1954 local_varnames = local_ns.keys()
1955 self.user_ns.update(local_ns)
1956 #self.user_ns['local_ns'] = local_ns # dbg
1957
1958 # Patch for global embedding to make sure that things don't overwrite
1959 # user globals accidentally. Thanks to Richard <rxe@renre-europe.com>
1960 # FIXME. Test this a bit more carefully (the if.. is new)
1961 if local_ns is None and global_ns is None:
1962 self.user_global_ns.update(__main__.__dict__)
1963
1964 # make sure the tab-completer has the correct frame information, so it
1965 # actually completes using the frame's locals/globals
1966 self.set_completer_frame()
1967
1968 # before activating the interactive mode, we need to make sure that
1969 # all names in the builtin namespace needed by ipython point to
1970 # ourselves, and not to other instances.
1971 self.add_builtins()
1972
1973 self.interact(header)
1974
1975 # now, purge out the user namespace from anything we might have added
1976 # from the caller's local namespace
1977 delvar = self.user_ns.pop
1978 for var in local_varnames:
1979 delvar(var,None)
1980 # and clean builtins we may have overridden
1981 self.remove_builtins()
1982
1983 def interact_prompt(self):
1844 def interact_prompt(self):
1984 """ Print the prompt (in read-eval-print loop)
1845 """ Print the prompt (in read-eval-print loop)
1985
1846
@@ -2377,6 +2238,7 b' class InteractiveShell(Component, Magic):'
2377 lines = lines.splitlines()
2238 lines = lines.splitlines()
2378 more = 0
2239 more = 0
2379
2240
2241 with self.builtin_trap:
2380 for line in lines:
2242 for line in lines:
2381 # skip blank lines so we don't mess up the prompt counter, but do
2243 # skip blank lines so we don't mess up the prompt counter, but do
2382 # NOT skip even a blank line if we are in a code block (more is
2244 # NOT skip even a blank line if we are in a code block (more is
General Comments 0
You need to be logged in to leave comments. Login now