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