##// END OF EJS Templates
More re-organization of InteractiveShell.
Brian Granger -
Show More

The requested changes are too big and content was truncated. Show full diff

@@ -1,260 +1,268 b''
1 #!/usr/bin/env python
1 #!/usr/bin/env python
2 # encoding: utf-8
2 # encoding: utf-8
3 """
3 """
4 An embedded IPython shell.
4 An embedded IPython shell.
5
5
6 Authors:
6 Authors:
7
7
8 * Brian Granger
8 * Brian Granger
9 * Fernando Perez
9 * Fernando Perez
10
10
11 Notes
11 Notes
12 -----
12 -----
13 """
13 """
14
14
15 #-----------------------------------------------------------------------------
15 #-----------------------------------------------------------------------------
16 # Copyright (C) 2008-2009 The IPython Development Team
16 # Copyright (C) 2008-2009 The IPython Development Team
17 #
17 #
18 # Distributed under the terms of the BSD License. The full license is in
18 # Distributed under the terms of the BSD License. The full license is in
19 # the file COPYING, distributed as part of this software.
19 # the file COPYING, distributed as part of this software.
20 #-----------------------------------------------------------------------------
20 #-----------------------------------------------------------------------------
21
21
22 #-----------------------------------------------------------------------------
22 #-----------------------------------------------------------------------------
23 # Imports
23 # Imports
24 #-----------------------------------------------------------------------------
24 #-----------------------------------------------------------------------------
25
25
26 from __future__ import with_statement
26 from __future__ import with_statement
27
27
28 import sys
28 import sys
29 from contextlib import nested
29 from contextlib import nested
30
30
31 from IPython.core import ultratb
31 from IPython.core import ultratb
32 from IPython.core.iplib import InteractiveShell
32 from IPython.core.iplib import InteractiveShell
33
33
34 from IPython.utils.traitlets import Bool, Str, CBool
34 from IPython.utils.traitlets import Bool, Str, CBool
35 from IPython.utils.genutils import ask_yes_no
35 from IPython.utils.genutils import ask_yes_no
36
36
37 #-----------------------------------------------------------------------------
37 #-----------------------------------------------------------------------------
38 # Classes and functions
38 # Classes and functions
39 #-----------------------------------------------------------------------------
39 #-----------------------------------------------------------------------------
40
40
41 # This is an additional magic that is exposed in embedded shells.
41 # This is an additional magic that is exposed in embedded shells.
42 def kill_embedded(self,parameter_s=''):
42 def kill_embedded(self,parameter_s=''):
43 """%kill_embedded : deactivate for good the current embedded IPython.
43 """%kill_embedded : deactivate for good the current embedded IPython.
44
44
45 This function (after asking for confirmation) sets an internal flag so that
45 This function (after asking for confirmation) sets an internal flag so that
46 an embedded IPython will never activate again. This is useful to
46 an embedded IPython will never activate again. This is useful to
47 permanently disable a shell that is being called inside a loop: once you've
47 permanently disable a shell that is being called inside a loop: once you've
48 figured out what you needed from it, you may then kill it and the program
48 figured out what you needed from it, you may then kill it and the program
49 will then continue to run without the interactive shell interfering again.
49 will then continue to run without the interactive shell interfering again.
50 """
50 """
51
51
52 kill = ask_yes_no("Are you sure you want to kill this embedded instance "
52 kill = ask_yes_no("Are you sure you want to kill this embedded instance "
53 "(y/n)? [y/N] ",'n')
53 "(y/n)? [y/N] ",'n')
54 if kill:
54 if kill:
55 self.embedded_active = False
55 self.embedded_active = False
56 print "This embedded IPython will not reactivate anymore once you exit."
56 print "This embedded IPython will not reactivate anymore once you exit."
57
57
58
58
59 class InteractiveShellEmbed(InteractiveShell):
59 class InteractiveShellEmbed(InteractiveShell):
60
60
61 dummy_mode = Bool(False)
61 dummy_mode = Bool(False)
62 exit_msg = Str('')
62 exit_msg = Str('')
63 embedded = CBool(True)
63 embedded = CBool(True)
64 embedded_active = CBool(True)
64 embedded_active = CBool(True)
65
65
66 def __init__(self, parent=None, config=None, ipythondir=None, usage=None,
66 def __init__(self, parent=None, config=None, ipythondir=None, usage=None,
67 user_ns=None, user_global_ns=None,
67 user_ns=None, user_global_ns=None,
68 banner1=None, banner2=None,
68 banner1=None, banner2=None,
69 custom_exceptions=((),None), exit_msg=''):
69 custom_exceptions=((),None), exit_msg=''):
70
70
71 self.save_sys_ipcompleter()
71 self.save_sys_ipcompleter()
72
72
73 super(InteractiveShellEmbed,self).__init__(
73 super(InteractiveShellEmbed,self).__init__(
74 parent=parent, config=config, ipythondir=ipythondir, usage=usage,
74 parent=parent, config=config, ipythondir=ipythondir, usage=usage,
75 user_ns=user_ns, user_global_ns=user_global_ns,
75 user_ns=user_ns, user_global_ns=user_global_ns,
76 banner1=banner1, banner2=banner2,
76 banner1=banner1, banner2=banner2,
77 custom_exceptions=custom_exceptions)
77 custom_exceptions=custom_exceptions)
78
78
79 self.exit_msg = exit_msg
79 self.exit_msg = exit_msg
80 self.define_magic("kill_embedded", kill_embedded)
80 self.define_magic("kill_embedded", kill_embedded)
81
81
82 # don't use the ipython crash handler so that user exceptions aren't
82 # don't use the ipython crash handler so that user exceptions aren't
83 # trapped
83 # trapped
84 sys.excepthook = ultratb.FormattedTB(color_scheme=self.colors,
84 sys.excepthook = ultratb.FormattedTB(color_scheme=self.colors,
85 mode=self.xmode,
85 mode=self.xmode,
86 call_pdb=self.pdb)
86 call_pdb=self.pdb)
87
87
88 self.restore_sys_ipcompleter()
88 self.restore_sys_ipcompleter()
89
89
90 def init_sys_modules(self):
90 def init_sys_modules(self):
91 pass
91 pass
92
92
93 def save_sys_ipcompleter(self):
93 def save_sys_ipcompleter(self):
94 """Save readline completer status."""
94 """Save readline completer status."""
95 try:
95 try:
96 #print 'Save completer',sys.ipcompleter # dbg
96 #print 'Save completer',sys.ipcompleter # dbg
97 self.sys_ipcompleter_orig = sys.ipcompleter
97 self.sys_ipcompleter_orig = sys.ipcompleter
98 except:
98 except:
99 pass # not nested with IPython
99 pass # not nested with IPython
100
100
101 def restore_sys_ipcompleter(self):
101 def restore_sys_ipcompleter(self):
102 """Restores the readline completer which was in place.
102 """Restores the readline completer which was in place.
103
103
104 This allows embedded IPython within IPython not to disrupt the
104 This allows embedded IPython within IPython not to disrupt the
105 parent's completion.
105 parent's completion.
106 """
106 """
107 try:
107 try:
108 self.readline.set_completer(self.sys_ipcompleter_orig)
108 self.readline.set_completer(self.sys_ipcompleter_orig)
109 sys.ipcompleter = self.sys_ipcompleter_orig
109 sys.ipcompleter = self.sys_ipcompleter_orig
110 except:
110 except:
111 pass
111 pass
112
112
113 def __call__(self, header='', local_ns=None, global_ns=None, dummy=None,
113 def __call__(self, header='', local_ns=None, global_ns=None, dummy=None,
114 stack_depth=1):
114 stack_depth=1):
115 """Activate the interactive interpreter.
115 """Activate the interactive interpreter.
116
116
117 __call__(self,header='',local_ns=None,global_ns,dummy=None) -> Start
117 __call__(self,header='',local_ns=None,global_ns,dummy=None) -> Start
118 the interpreter shell with the given local and global namespaces, and
118 the interpreter shell with the given local and global namespaces, and
119 optionally print a header string at startup.
119 optionally print a header string at startup.
120
120
121 The shell can be globally activated/deactivated using the
121 The shell can be globally activated/deactivated using the
122 set/get_dummy_mode methods. This allows you to turn off a shell used
122 set/get_dummy_mode methods. This allows you to turn off a shell used
123 for debugging globally.
123 for debugging globally.
124
124
125 However, *each* time you call the shell you can override the current
125 However, *each* time you call the shell you can override the current
126 state of dummy_mode with the optional keyword parameter 'dummy'. For
126 state of dummy_mode with the optional keyword parameter 'dummy'. For
127 example, if you set dummy mode on with IPShell.set_dummy_mode(1), you
127 example, if you set dummy mode on with IPShell.set_dummy_mode(1), you
128 can still have a specific call work by making it as IPShell(dummy=0).
128 can still have a specific call work by making it as IPShell(dummy=0).
129
129
130 The optional keyword parameter dummy controls whether the call
130 The optional keyword parameter dummy controls whether the call
131 actually does anything.
131 actually does anything.
132 """
132 """
133
133
134 # If the user has turned it off, go away
134 # If the user has turned it off, go away
135 if not self.embedded_active:
135 if not self.embedded_active:
136 return
136 return
137
137
138 # Normal exits from interactive mode set this flag, so the shell can't
138 # Normal exits from interactive mode set this flag, so the shell can't
139 # re-enter (it checks this variable at the start of interactive mode).
139 # re-enter (it checks this variable at the start of interactive mode).
140 self.exit_now = False
140 self.exit_now = False
141
141
142 # Allow the dummy parameter to override the global __dummy_mode
142 # Allow the dummy parameter to override the global __dummy_mode
143 if dummy or (dummy != 0 and self.dummy_mode):
143 if dummy or (dummy != 0 and self.dummy_mode):
144 return
144 return
145
145
146 if self.has_readline:
146 if self.has_readline:
147 self.set_completer()
147 self.set_completer()
148
148
149 if self.banner and header:
149 if self.banner and header:
150 format = '%s\n%s\n'
150 format = '%s\n%s\n'
151 else:
151 else:
152 format = '%s%s\n'
152 format = '%s%s\n'
153 banner = format % (self.banner,header)
153 banner = format % (self.banner,header)
154
154
155 # Call the embedding code with a stack depth of 1 so it can skip over
155 # Call the embedding code with a stack depth of 1 so it can skip over
156 # our call and get the original caller's namespaces.
156 # our call and get the original caller's namespaces.
157 self.mainloop(banner, local_ns, global_ns,
157 self.mainloop(banner, local_ns, global_ns,
158 stack_depth=stack_depth)
158 stack_depth=stack_depth)
159
159
160 if self.exit_msg is not None:
160 if self.exit_msg is not None:
161 print self.exit_msg
161 print self.exit_msg
162
162
163 self.restore_sys_ipcompleter()
163 self.restore_sys_ipcompleter()
164
164
165 def mainloop(self,header='',local_ns=None,global_ns=None,stack_depth=0):
165 def mainloop(self,header='',local_ns=None,global_ns=None,stack_depth=0):
166 """Embeds IPython into a running python program.
166 """Embeds IPython into a running python program.
167
167
168 Input:
168 Input:
169
169
170 - header: An optional header message can be specified.
170 - header: An optional header message can be specified.
171
171
172 - local_ns, global_ns: working namespaces. If given as None, the
172 - local_ns, global_ns: working namespaces. If given as None, the
173 IPython-initialized one is updated with __main__.__dict__, so that
173 IPython-initialized one is updated with __main__.__dict__, so that
174 program variables become visible but user-specific configuration
174 program variables become visible but user-specific configuration
175 remains possible.
175 remains possible.
176
176
177 - stack_depth: specifies how many levels in the stack to go to
177 - stack_depth: specifies how many levels in the stack to go to
178 looking for namespaces (when local_ns and global_ns are None). This
178 looking for namespaces (when local_ns and global_ns are None). This
179 allows an intermediate caller to make sure that this function gets
179 allows an intermediate caller to make sure that this function gets
180 the namespace from the intended level in the stack. By default (0)
180 the namespace from the intended level in the stack. By default (0)
181 it will get its locals and globals from the immediate caller.
181 it will get its locals and globals from the immediate caller.
182
182
183 Warning: it's possible to use this in a program which is being run by
183 Warning: it's possible to use this in a program which is being run by
184 IPython itself (via %run), but some funny things will happen (a few
184 IPython itself (via %run), but some funny things will happen (a few
185 globals get overwritten). In the future this will be cleaned up, as
185 globals get overwritten). In the future this will be cleaned up, as
186 there is no fundamental reason why it can't work perfectly."""
186 there is no fundamental reason why it can't work perfectly."""
187
187
188 # Get locals and globals from caller
188 # Get locals and globals from caller
189 if local_ns is None or global_ns is None:
189 if local_ns is None or global_ns is None:
190 call_frame = sys._getframe(stack_depth).f_back
190 call_frame = sys._getframe(stack_depth).f_back
191
191
192 if local_ns is None:
192 if local_ns is None:
193 local_ns = call_frame.f_locals
193 local_ns = call_frame.f_locals
194 if global_ns is None:
194 if global_ns is None:
195 global_ns = call_frame.f_globals
195 global_ns = call_frame.f_globals
196
196
197 # Update namespaces and fire up interpreter
197 # Update namespaces and fire up interpreter
198
198
199 # The global one is easy, we can just throw it in
199 # The global one is easy, we can just throw it in
200 self.user_global_ns = global_ns
200 self.user_global_ns = global_ns
201
201
202 # but the user/local one is tricky: ipython needs it to store internal
202 # but the user/local one is tricky: ipython needs it to store internal
203 # data, but we also need the locals. We'll copy locals in the user
203 # data, but we also need the locals. We'll copy locals in the user
204 # one, but will track what got copied so we can delete them at exit.
204 # one, but will track what got copied so we can delete them at exit.
205 # This is so that a later embedded call doesn't see locals from a
205 # This is so that a later embedded call doesn't see locals from a
206 # previous call (which most likely existed in a separate scope).
206 # previous call (which most likely existed in a separate scope).
207 local_varnames = local_ns.keys()
207 local_varnames = local_ns.keys()
208 self.user_ns.update(local_ns)
208 self.user_ns.update(local_ns)
209 #self.user_ns['local_ns'] = local_ns # dbg
209 #self.user_ns['local_ns'] = local_ns # dbg
210
210
211 # Patch for global embedding to make sure that things don't overwrite
211 # Patch for global embedding to make sure that things don't overwrite
212 # user globals accidentally. Thanks to Richard <rxe@renre-europe.com>
212 # user globals accidentally. Thanks to Richard <rxe@renre-europe.com>
213 # FIXME. Test this a bit more carefully (the if.. is new)
213 # FIXME. Test this a bit more carefully (the if.. is new)
214 if local_ns is None and global_ns is None:
214 if local_ns is None and global_ns is None:
215 self.user_global_ns.update(__main__.__dict__)
215 self.user_global_ns.update(__main__.__dict__)
216
216
217 # make sure the tab-completer has the correct frame information, so it
217 # make sure the tab-completer has the correct frame information, so it
218 # actually completes using the frame's locals/globals
218 # actually completes using the frame's locals/globals
219 self.set_completer_frame()
219 self.set_completer_frame()
220
220
221 with nested(self.builtin_trap, self.display_trap):
221 with nested(self.builtin_trap, self.display_trap):
222 self.interact(header)
222 self.interact(header)
223
223
224 # now, purge out the user namespace from anything we might have added
224 # now, purge out the user namespace from anything we might have added
225 # from the caller's local namespace
225 # from the caller's local namespace
226 delvar = self.user_ns.pop
226 delvar = self.user_ns.pop
227 for var in local_varnames:
227 for var in local_varnames:
228 delvar(var,None)
228 delvar(var,None)
229
229
230 def set_completer_frame(self, frame=None):
231 if frame:
232 self.Completer.namespace = frame.f_locals
233 self.Completer.global_namespace = frame.f_globals
234 else:
235 self.Completer.namespace = self.user_ns
236 self.Completer.global_namespace = self.user_global_ns
237
230
238
231 _embedded_shell = None
239 _embedded_shell = None
232
240
233
241
234 def embed(header='', config=None, usage=None, banner1=None, banner2=None,
242 def embed(header='', config=None, usage=None, banner1=None, banner2=None,
235 exit_msg=''):
243 exit_msg=''):
236 """Call this to embed IPython at the current point in your program.
244 """Call this to embed IPython at the current point in your program.
237
245
238 The first invocation of this will create an :class:`InteractiveShellEmbed`
246 The first invocation of this will create an :class:`InteractiveShellEmbed`
239 instance and then call it. Consecutive calls just call the already
247 instance and then call it. Consecutive calls just call the already
240 created instance.
248 created instance.
241
249
242 Here is a simple example::
250 Here is a simple example::
243
251
244 from IPython import embed
252 from IPython import embed
245 a = 10
253 a = 10
246 b = 20
254 b = 20
247 embed('First time')
255 embed('First time')
248 c = 30
256 c = 30
249 d = 40
257 d = 40
250 embed
258 embed
251
259
252 Full customization can be done by passing a :class:`Struct` in as the
260 Full customization can be done by passing a :class:`Struct` in as the
253 config argument.
261 config argument.
254 """
262 """
255 global _embedded_shell
263 global _embedded_shell
256 if _embedded_shell is None:
264 if _embedded_shell is None:
257 _embedded_shell = InteractiveShellEmbed(config=config,
265 _embedded_shell = InteractiveShellEmbed(config=config,
258 usage=usage, banner1=banner1, banner2=banner2, exit_msg=exit_msg)
266 usage=usage, banner1=banner1, banner2=banner2, exit_msg=exit_msg)
259 _embedded_shell(header=header, stack_depth=2)
267 _embedded_shell(header=header, stack_depth=2)
260
268
1 NO CONTENT: modified file
NO CONTENT: modified file
The requested commit or file is too big and content was truncated. Show full diff
General Comments 0
You need to be logged in to leave comments. Login now