##// END OF EJS Templates
More re-organization of InteractiveShell.
Brian Granger -
Show More

The requested changes are too big and content was truncated. Show full diff

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