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