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