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