##// END OF EJS Templates
Fix regression in embed() from pull-request #2096....
Bradley M. Froehle -
Show More
@@ -1,298 +1,300 b''
1 # encoding: utf-8
1 # encoding: utf-8
2 """
2 """
3 An embedded IPython shell.
3 An embedded IPython shell.
4
4
5 Authors:
5 Authors:
6
6
7 * Brian Granger
7 * Brian Granger
8 * Fernando Perez
8 * Fernando Perez
9
9
10 Notes
10 Notes
11 -----
11 -----
12 """
12 """
13
13
14 #-----------------------------------------------------------------------------
14 #-----------------------------------------------------------------------------
15 # Copyright (C) 2008-2011 The IPython Development Team
15 # Copyright (C) 2008-2011 The IPython Development Team
16 #
16 #
17 # Distributed under the terms of the BSD License. The full license is in
17 # Distributed under the terms of the BSD License. The full license is in
18 # the file COPYING, distributed as part of this software.
18 # the file COPYING, distributed as part of this software.
19 #-----------------------------------------------------------------------------
19 #-----------------------------------------------------------------------------
20
20
21 #-----------------------------------------------------------------------------
21 #-----------------------------------------------------------------------------
22 # Imports
22 # Imports
23 #-----------------------------------------------------------------------------
23 #-----------------------------------------------------------------------------
24
24
25 from __future__ import with_statement
25 from __future__ import with_statement
26
26
27 import sys
27 import sys
28 import warnings
28 import warnings
29
29
30 # We need to use nested to support python 2.6, once we move to >=2.7, we can
30 # We need to use nested to support python 2.6, once we move to >=2.7, we can
31 # use the with keyword's new builtin support for nested managers
31 # use the with keyword's new builtin support for nested managers
32 try:
32 try:
33 from contextlib import nested
33 from contextlib import nested
34 except:
34 except:
35 from IPython.utils.nested_context import nested
35 from IPython.utils.nested_context import nested
36
36
37 from IPython.core import ultratb, compilerop
37 from IPython.core import ultratb, compilerop
38 from IPython.core.magic import Magics, magics_class, line_magic
38 from IPython.core.magic import Magics, magics_class, line_magic
39 from IPython.frontend.terminal.interactiveshell import TerminalInteractiveShell
39 from IPython.frontend.terminal.interactiveshell import TerminalInteractiveShell
40 from IPython.frontend.terminal.ipapp import load_default_config
40 from IPython.frontend.terminal.ipapp import load_default_config
41
41
42 from IPython.utils.traitlets import Bool, CBool, Unicode
42 from IPython.utils.traitlets import Bool, CBool, Unicode
43 from IPython.utils.io import ask_yes_no
43 from IPython.utils.io import ask_yes_no
44
44
45
45
46 #-----------------------------------------------------------------------------
46 #-----------------------------------------------------------------------------
47 # Classes and functions
47 # Classes and functions
48 #-----------------------------------------------------------------------------
48 #-----------------------------------------------------------------------------
49
49
50 # This is an additional magic that is exposed in embedded shells.
50 # This is an additional magic that is exposed in embedded shells.
51 @magics_class
51 @magics_class
52 class EmbeddedMagics(Magics):
52 class EmbeddedMagics(Magics):
53
53
54 @line_magic
54 @line_magic
55 def kill_embedded(self, parameter_s=''):
55 def kill_embedded(self, parameter_s=''):
56 """%kill_embedded : deactivate for good the current embedded IPython.
56 """%kill_embedded : deactivate for good the current embedded IPython.
57
57
58 This function (after asking for confirmation) sets an internal flag so
58 This function (after asking for confirmation) sets an internal flag so
59 that an embedded IPython will never activate again. This is useful to
59 that an embedded IPython will never activate again. This is useful to
60 permanently disable a shell that is being called inside a loop: once
60 permanently disable a shell that is being called inside a loop: once
61 you've figured out what you needed from it, you may then kill it and
61 you've figured out what you needed from it, you may then kill it and
62 the program will then continue to run without the interactive shell
62 the program will then continue to run without the interactive shell
63 interfering again.
63 interfering again.
64 """
64 """
65
65
66 kill = ask_yes_no("Are you sure you want to kill this embedded instance "
66 kill = ask_yes_no("Are you sure you want to kill this embedded instance "
67 "(y/n)? [y/N] ",'n')
67 "(y/n)? [y/N] ",'n')
68 if kill:
68 if kill:
69 self.shell.embedded_active = False
69 self.shell.embedded_active = False
70 print ("This embedded IPython will not reactivate anymore "
70 print ("This embedded IPython will not reactivate anymore "
71 "once you exit.")
71 "once you exit.")
72
72
73
73
74 class InteractiveShellEmbed(TerminalInteractiveShell):
74 class InteractiveShellEmbed(TerminalInteractiveShell):
75
75
76 dummy_mode = Bool(False)
76 dummy_mode = Bool(False)
77 exit_msg = Unicode('')
77 exit_msg = Unicode('')
78 embedded = CBool(True)
78 embedded = CBool(True)
79 embedded_active = CBool(True)
79 embedded_active = CBool(True)
80 # Like the base class display_banner is not configurable, but here it
80 # Like the base class display_banner is not configurable, but here it
81 # is True by default.
81 # is True by default.
82 display_banner = CBool(True)
82 display_banner = CBool(True)
83
83
84 def __init__(self, config=None, ipython_dir=None, user_ns=None,
84 def __init__(self, config=None, ipython_dir=None, user_ns=None,
85 user_module=None, custom_exceptions=((),None),
85 user_module=None, custom_exceptions=((),None),
86 usage=None, banner1=None, banner2=None,
86 usage=None, banner1=None, banner2=None,
87 display_banner=None, exit_msg=u'', user_global_ns=None):
87 display_banner=None, exit_msg=u'', user_global_ns=None):
88
88
89 if user_global_ns is not None:
89 if user_global_ns is not None:
90 warnings.warn("user_global_ns has been replaced by user_module. The\
90 warnings.warn("user_global_ns has been replaced by user_module. The\
91 parameter will be ignored.", DeprecationWarning)
91 parameter will be ignored.", DeprecationWarning)
92
92
93 super(InteractiveShellEmbed,self).__init__(
93 super(InteractiveShellEmbed,self).__init__(
94 config=config, ipython_dir=ipython_dir, user_ns=user_ns,
94 config=config, ipython_dir=ipython_dir, user_ns=user_ns,
95 user_module=user_module, custom_exceptions=custom_exceptions,
95 user_module=user_module, custom_exceptions=custom_exceptions,
96 usage=usage, banner1=banner1, banner2=banner2,
96 usage=usage, banner1=banner1, banner2=banner2,
97 display_banner=display_banner
97 display_banner=display_banner
98 )
98 )
99
99
100 self.exit_msg = exit_msg
100 self.exit_msg = exit_msg
101
101
102 # don't use the ipython crash handler so that user exceptions aren't
102 # don't use the ipython crash handler so that user exceptions aren't
103 # trapped
103 # trapped
104 sys.excepthook = ultratb.FormattedTB(color_scheme=self.colors,
104 sys.excepthook = ultratb.FormattedTB(color_scheme=self.colors,
105 mode=self.xmode,
105 mode=self.xmode,
106 call_pdb=self.pdb)
106 call_pdb=self.pdb)
107
107
108 def init_sys_modules(self):
108 def init_sys_modules(self):
109 pass
109 pass
110
110
111 def init_magics(self):
111 def init_magics(self):
112 super(InteractiveShellEmbed, self).init_magics()
112 super(InteractiveShellEmbed, self).init_magics()
113 self.register_magics(EmbeddedMagics)
113 self.register_magics(EmbeddedMagics)
114
114
115 def __call__(self, header='', local_ns=None, module=None, dummy=None,
115 def __call__(self, header='', local_ns=None, module=None, dummy=None,
116 stack_depth=1, global_ns=None, compile_flags=None):
116 stack_depth=1, global_ns=None, compile_flags=None):
117 """Activate the interactive interpreter.
117 """Activate the interactive interpreter.
118
118
119 __call__(self,header='',local_ns=None,module=None,dummy=None) -> Start
119 __call__(self,header='',local_ns=None,module=None,dummy=None) -> Start
120 the interpreter shell with the given local and global namespaces, and
120 the interpreter shell with the given local and global namespaces, and
121 optionally print a header string at startup.
121 optionally print a header string at startup.
122
122
123 The shell can be globally activated/deactivated using the
123 The shell can be globally activated/deactivated using the
124 dummy_mode attribute. This allows you to turn off a shell used
124 dummy_mode attribute. This allows you to turn off a shell used
125 for debugging globally.
125 for debugging globally.
126
126
127 However, *each* time you call the shell you can override the current
127 However, *each* time you call the shell you can override the current
128 state of dummy_mode with the optional keyword parameter 'dummy'. For
128 state of dummy_mode with the optional keyword parameter 'dummy'. For
129 example, if you set dummy mode on with IPShell.dummy_mode = True, you
129 example, if you set dummy mode on with IPShell.dummy_mode = True, you
130 can still have a specific call work by making it as IPShell(dummy=False).
130 can still have a specific call work by making it as IPShell(dummy=False).
131 """
131 """
132
132
133 # If the user has turned it off, go away
133 # If the user has turned it off, go away
134 if not self.embedded_active:
134 if not self.embedded_active:
135 return
135 return
136
136
137 # Normal exits from interactive mode set this flag, so the shell can't
137 # Normal exits from interactive mode set this flag, so the shell can't
138 # re-enter (it checks this variable at the start of interactive mode).
138 # re-enter (it checks this variable at the start of interactive mode).
139 self.exit_now = False
139 self.exit_now = False
140
140
141 # Allow the dummy parameter to override the global __dummy_mode
141 # Allow the dummy parameter to override the global __dummy_mode
142 if dummy or (dummy != 0 and self.dummy_mode):
142 if dummy or (dummy != 0 and self.dummy_mode):
143 return
143 return
144
144
145 if self.has_readline:
145 if self.has_readline:
146 self.set_readline_completer()
146 self.set_readline_completer()
147
147
148 # self.banner is auto computed
148 # self.banner is auto computed
149 if header:
149 if header:
150 self.old_banner2 = self.banner2
150 self.old_banner2 = self.banner2
151 self.banner2 = self.banner2 + '\n' + header + '\n'
151 self.banner2 = self.banner2 + '\n' + header + '\n'
152 else:
152 else:
153 self.old_banner2 = ''
153 self.old_banner2 = ''
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(local_ns, module, stack_depth=stack_depth,
157 self.mainloop(local_ns, module, stack_depth=stack_depth,
158 global_ns=global_ns, compile_flags=compile_flags)
158 global_ns=global_ns, compile_flags=compile_flags)
159
159
160 self.banner2 = self.old_banner2
160 self.banner2 = self.old_banner2
161
161
162 if self.exit_msg is not None:
162 if self.exit_msg is not None:
163 print self.exit_msg
163 print self.exit_msg
164
164
165 def mainloop(self, local_ns=None, module=None, stack_depth=0,
165 def mainloop(self, local_ns=None, module=None, stack_depth=0,
166 display_banner=None, global_ns=None, compile_flags=None):
166 display_banner=None, global_ns=None, compile_flags=None):
167 """Embeds IPython into a running python program.
167 """Embeds IPython into a running python program.
168
168
169 Input:
169 Input:
170
170
171 - header: An optional header message can be specified.
171 - header: An optional header message can be specified.
172
172
173 - local_ns, module: working local namespace (a dict) and module (a
173 - local_ns, module: working local namespace (a dict) and module (a
174 module or similar object). If given as None, they are automatically
174 module or similar object). If given as None, they are automatically
175 taken from the scope where the shell was called, so that
175 taken from the scope where the shell was called, so that
176 program variables become visible.
176 program variables become visible.
177
177
178 - stack_depth: specifies how many levels in the stack to go to
178 - stack_depth: specifies how many levels in the stack to go to
179 looking for namespaces (when local_ns or module is None). This
179 looking for namespaces (when local_ns or module is None). This
180 allows an intermediate caller to make sure that this function gets
180 allows an intermediate caller to make sure that this function gets
181 the namespace from the intended level in the stack. By default (0)
181 the namespace from the intended level in the stack. By default (0)
182 it will get its locals and globals from the immediate caller.
182 it will get its locals and globals from the immediate caller.
183
183
184 - compile_flags: A bit field identifying the __future__ features
184 - compile_flags: A bit field identifying the __future__ features
185 that are enabled, as passed to the builtin `compile` function. If
185 that are enabled, as passed to the builtin `compile` function. If
186 given as None, they are automatically taken from the scope where the
186 given as None, they are automatically taken from the scope where the
187 shell was called.
187 shell was called.
188
188
189 Warning: it's possible to use this in a program which is being run by
189 Warning: it's possible to use this in a program which is being run by
190 IPython itself (via %run), but some funny things will happen (a few
190 IPython itself (via %run), but some funny things will happen (a few
191 globals get overwritten). In the future this will be cleaned up, as
191 globals get overwritten). In the future this will be cleaned up, as
192 there is no fundamental reason why it can't work perfectly."""
192 there is no fundamental reason why it can't work perfectly."""
193
193
194 if (global_ns is not None) and (module is None):
194 if (global_ns is not None) and (module is None):
195 class DummyMod(object):
195 class DummyMod(object):
196 """A dummy module object for embedded IPython."""
196 """A dummy module object for embedded IPython."""
197 pass
197 pass
198 warnings.warn("global_ns is deprecated, use module instead.", DeprecationWarning)
198 warnings.warn("global_ns is deprecated, use module instead.", DeprecationWarning)
199 module = DummyMod()
199 module = DummyMod()
200 module.__dict__ = global_ns
200 module.__dict__ = global_ns
201
201
202 # Get locals and globals from caller
202 # Get locals and globals from caller
203 if (local_ns is None or module is None) and self.default_user_namespaces:
203 if ((local_ns is None or module is None or compile_flags is None)
204 and self.default_user_namespaces):
204 call_frame = sys._getframe(stack_depth).f_back
205 call_frame = sys._getframe(stack_depth).f_back
205
206
206 if local_ns is None:
207 if local_ns is None:
207 local_ns = call_frame.f_locals
208 local_ns = call_frame.f_locals
208 if module is None:
209 if module is None:
209 global_ns = call_frame.f_globals
210 global_ns = call_frame.f_globals
210 module = sys.modules[global_ns['__name__']]
211 module = sys.modules[global_ns['__name__']]
211 if compile_flags is None:
212 if compile_flags is None:
212 compile_flags = (call_frame.f_code.co_flags &
213 compile_flags = (call_frame.f_code.co_flags &
213 compilerop.PyCF_MASK)
214 compilerop.PyCF_MASK)
214
215
215 # Save original namespace and module so we can restore them after
216 # Save original namespace and module so we can restore them after
216 # embedding; otherwise the shell doesn't shut down correctly.
217 # embedding; otherwise the shell doesn't shut down correctly.
217 orig_user_module = self.user_module
218 orig_user_module = self.user_module
218 orig_user_ns = self.user_ns
219 orig_user_ns = self.user_ns
219 orig_compile_flags = self.compile.flags
220 orig_compile_flags = self.compile.flags
220
221
221 # Update namespaces and fire up interpreter
222 # Update namespaces and fire up interpreter
222
223
223 # The global one is easy, we can just throw it in
224 # The global one is easy, we can just throw it in
224 if module is not None:
225 if module is not None:
225 self.user_module = module
226 self.user_module = module
226
227
227 # But the user/local one is tricky: ipython needs it to store internal
228 # But the user/local one is tricky: ipython needs it to store internal
228 # data, but we also need the locals. We'll throw our hidden variables
229 # data, but we also need the locals. We'll throw our hidden variables
229 # like _ih and get_ipython() into the local namespace, but delete them
230 # like _ih and get_ipython() into the local namespace, but delete them
230 # later.
231 # later.
231 if local_ns is not None:
232 if local_ns is not None:
232 self.user_ns = local_ns
233 self.user_ns = local_ns
233 self.init_user_ns()
234 self.init_user_ns()
234
235
235 # Compiler flags
236 # Compiler flags
236 self.compile.flags = compile_flags
237 if compile_flags is not None:
238 self.compile.flags = compile_flags
237
239
238 # Patch for global embedding to make sure that things don't overwrite
240 # Patch for global embedding to make sure that things don't overwrite
239 # user globals accidentally. Thanks to Richard <rxe@renre-europe.com>
241 # user globals accidentally. Thanks to Richard <rxe@renre-europe.com>
240 # FIXME. Test this a bit more carefully (the if.. is new)
242 # FIXME. Test this a bit more carefully (the if.. is new)
241 # N.B. This can't now ever be called. Not sure what it was for.
243 # N.B. This can't now ever be called. Not sure what it was for.
242 # And now, since it wasn't called in the previous version, I'm
244 # And now, since it wasn't called in the previous version, I'm
243 # commenting out these lines so they can't be called with my new changes
245 # commenting out these lines so they can't be called with my new changes
244 # --TK, 2011-12-10
246 # --TK, 2011-12-10
245 #if local_ns is None and module is None:
247 #if local_ns is None and module is None:
246 # self.user_global_ns.update(__main__.__dict__)
248 # self.user_global_ns.update(__main__.__dict__)
247
249
248 # make sure the tab-completer has the correct frame information, so it
250 # make sure the tab-completer has the correct frame information, so it
249 # actually completes using the frame's locals/globals
251 # actually completes using the frame's locals/globals
250 self.set_completer_frame()
252 self.set_completer_frame()
251
253
252 with nested(self.builtin_trap, self.display_trap):
254 with nested(self.builtin_trap, self.display_trap):
253 self.interact(display_banner=display_banner)
255 self.interact(display_banner=display_banner)
254
256
255 # now, purge out the local namespace of IPython's hidden variables.
257 # now, purge out the local namespace of IPython's hidden variables.
256 if local_ns is not None:
258 if local_ns is not None:
257 for name in self.user_ns_hidden:
259 for name in self.user_ns_hidden:
258 local_ns.pop(name, None)
260 local_ns.pop(name, None)
259
261
260 # Restore original namespace so shell can shut down when we exit.
262 # Restore original namespace so shell can shut down when we exit.
261 self.user_module = orig_user_module
263 self.user_module = orig_user_module
262 self.user_ns = orig_user_ns
264 self.user_ns = orig_user_ns
263 self.compile.flags = orig_compile_flags
265 self.compile.flags = orig_compile_flags
264
266
265 _embedded_shell = None
267 _embedded_shell = None
266
268
267
269
268 def embed(**kwargs):
270 def embed(**kwargs):
269 """Call this to embed IPython at the current point in your program.
271 """Call this to embed IPython at the current point in your program.
270
272
271 The first invocation of this will create an :class:`InteractiveShellEmbed`
273 The first invocation of this will create an :class:`InteractiveShellEmbed`
272 instance and then call it. Consecutive calls just call the already
274 instance and then call it. Consecutive calls just call the already
273 created instance.
275 created instance.
274
276
275 Here is a simple example::
277 Here is a simple example::
276
278
277 from IPython import embed
279 from IPython import embed
278 a = 10
280 a = 10
279 b = 20
281 b = 20
280 embed('First time')
282 embed('First time')
281 c = 30
283 c = 30
282 d = 40
284 d = 40
283 embed
285 embed
284
286
285 Full customization can be done by passing a :class:`Struct` in as the
287 Full customization can be done by passing a :class:`Struct` in as the
286 config argument.
288 config argument.
287 """
289 """
288 config = kwargs.get('config')
290 config = kwargs.get('config')
289 header = kwargs.pop('header', u'')
291 header = kwargs.pop('header', u'')
290 compile_flags = kwargs.pop('compile_flags', None)
292 compile_flags = kwargs.pop('compile_flags', None)
291 if config is None:
293 if config is None:
292 config = load_default_config()
294 config = load_default_config()
293 config.InteractiveShellEmbed = config.TerminalInteractiveShell
295 config.InteractiveShellEmbed = config.TerminalInteractiveShell
294 kwargs['config'] = config
296 kwargs['config'] = config
295 global _embedded_shell
297 global _embedded_shell
296 if _embedded_shell is None:
298 if _embedded_shell is None:
297 _embedded_shell = InteractiveShellEmbed(**kwargs)
299 _embedded_shell = InteractiveShellEmbed(**kwargs)
298 _embedded_shell(header=header, stack_depth=2, compile_flags=compile_flags)
300 _embedded_shell(header=header, stack_depth=2, compile_flags=compile_flags)
General Comments 0
You need to be logged in to leave comments. Login now