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