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