##// END OF EJS Templates
Backport PR #14169: Set instance on singleton configurable when created via constructor.
Matthias Bussonnier -
Show More
@@ -1,420 +1,426 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
8
9 import sys
9 import sys
10 import warnings
10 import warnings
11
11
12 from IPython.core import ultratb, compilerop
12 from IPython.core import ultratb, compilerop
13 from IPython.core import magic_arguments
13 from IPython.core import magic_arguments
14 from IPython.core.magic import Magics, magics_class, line_magic
14 from IPython.core.magic import Magics, magics_class, line_magic
15 from IPython.core.interactiveshell import DummyMod, InteractiveShell
15 from IPython.core.interactiveshell import DummyMod, InteractiveShell
16 from IPython.terminal.interactiveshell import TerminalInteractiveShell
16 from IPython.terminal.interactiveshell import TerminalInteractiveShell
17 from IPython.terminal.ipapp import load_default_config
17 from IPython.terminal.ipapp import load_default_config
18
18
19 from traitlets import Bool, CBool, Unicode
19 from traitlets import Bool, CBool, Unicode
20 from IPython.utils.io import ask_yes_no
20 from IPython.utils.io import ask_yes_no
21
21
22 from typing import Set
22 from typing import Set
23
23
24 class KillEmbedded(Exception):pass
24 class KillEmbedded(Exception):pass
25
25
26 # kept for backward compatibility as IPython 6 was released with
26 # kept for backward compatibility as IPython 6 was released with
27 # the typo. See https://github.com/ipython/ipython/pull/10706
27 # the typo. See https://github.com/ipython/ipython/pull/10706
28 KillEmbeded = KillEmbedded
28 KillEmbeded = KillEmbedded
29
29
30 # This is an additional magic that is exposed in embedded shells.
30 # This is an additional magic that is exposed in embedded shells.
31 @magics_class
31 @magics_class
32 class EmbeddedMagics(Magics):
32 class EmbeddedMagics(Magics):
33
33
34 @line_magic
34 @line_magic
35 @magic_arguments.magic_arguments()
35 @magic_arguments.magic_arguments()
36 @magic_arguments.argument('-i', '--instance', action='store_true',
36 @magic_arguments.argument('-i', '--instance', action='store_true',
37 help='Kill instance instead of call location')
37 help='Kill instance instead of call location')
38 @magic_arguments.argument('-x', '--exit', action='store_true',
38 @magic_arguments.argument('-x', '--exit', action='store_true',
39 help='Also exit the current session')
39 help='Also exit the current session')
40 @magic_arguments.argument('-y', '--yes', action='store_true',
40 @magic_arguments.argument('-y', '--yes', action='store_true',
41 help='Do not ask confirmation')
41 help='Do not ask confirmation')
42 def kill_embedded(self, parameter_s=''):
42 def kill_embedded(self, parameter_s=''):
43 """%kill_embedded : deactivate for good the current embedded IPython
43 """%kill_embedded : deactivate for good the current embedded IPython
44
44
45 This function (after asking for confirmation) sets an internal flag so
45 This function (after asking for confirmation) sets an internal flag so
46 that an embedded IPython will never activate again for the given call
46 that an embedded IPython will never activate again for the given call
47 location. This is useful to permanently disable a shell that is being
47 location. This is useful to permanently disable a shell that is being
48 called inside a loop: once you've figured out what you needed from it,
48 called inside a loop: once you've figured out what you needed from it,
49 you may then kill it and the program will then continue to run without
49 you may then kill it and the program will then continue to run without
50 the interactive shell interfering again.
50 the interactive shell interfering again.
51
51
52 Kill Instance Option:
52 Kill Instance Option:
53
53
54 If for some reasons you need to kill the location where the instance
54 If for some reasons you need to kill the location where the instance
55 is created and not called, for example if you create a single
55 is created and not called, for example if you create a single
56 instance in one place and debug in many locations, you can use the
56 instance in one place and debug in many locations, you can use the
57 ``--instance`` option to kill this specific instance. Like for the
57 ``--instance`` option to kill this specific instance. Like for the
58 ``call location`` killing an "instance" should work even if it is
58 ``call location`` killing an "instance" should work even if it is
59 recreated within a loop.
59 recreated within a loop.
60
60
61 .. note::
61 .. note::
62
62
63 This was the default behavior before IPython 5.2
63 This was the default behavior before IPython 5.2
64
64
65 """
65 """
66
66
67 args = magic_arguments.parse_argstring(self.kill_embedded, parameter_s)
67 args = magic_arguments.parse_argstring(self.kill_embedded, parameter_s)
68 print(args)
68 print(args)
69 if args.instance:
69 if args.instance:
70 # let no ask
70 # let no ask
71 if not args.yes:
71 if not args.yes:
72 kill = ask_yes_no(
72 kill = ask_yes_no(
73 "Are you sure you want to kill this embedded instance? [y/N] ", 'n')
73 "Are you sure you want to kill this embedded instance? [y/N] ", 'n')
74 else:
74 else:
75 kill = True
75 kill = True
76 if kill:
76 if kill:
77 self.shell._disable_init_location()
77 self.shell._disable_init_location()
78 print("This embedded IPython instance will not reactivate anymore "
78 print("This embedded IPython instance will not reactivate anymore "
79 "once you exit.")
79 "once you exit.")
80 else:
80 else:
81 if not args.yes:
81 if not args.yes:
82 kill = ask_yes_no(
82 kill = ask_yes_no(
83 "Are you sure you want to kill this embedded call_location? [y/N] ", 'n')
83 "Are you sure you want to kill this embedded call_location? [y/N] ", 'n')
84 else:
84 else:
85 kill = True
85 kill = True
86 if kill:
86 if kill:
87 self.shell.embedded_active = False
87 self.shell.embedded_active = False
88 print("This embedded IPython call location will not reactivate anymore "
88 print("This embedded IPython call location will not reactivate anymore "
89 "once you exit.")
89 "once you exit.")
90
90
91 if args.exit:
91 if args.exit:
92 # Ask-exit does not really ask, it just set internals flags to exit
92 # Ask-exit does not really ask, it just set internals flags to exit
93 # on next loop.
93 # on next loop.
94 self.shell.ask_exit()
94 self.shell.ask_exit()
95
95
96
96
97 @line_magic
97 @line_magic
98 def exit_raise(self, parameter_s=''):
98 def exit_raise(self, parameter_s=''):
99 """%exit_raise Make the current embedded kernel exit and raise and exception.
99 """%exit_raise Make the current embedded kernel exit and raise and exception.
100
100
101 This function sets an internal flag so that an embedded IPython will
101 This function sets an internal flag so that an embedded IPython will
102 raise a `IPython.terminal.embed.KillEmbedded` Exception on exit, and then exit the current I. This is
102 raise a `IPython.terminal.embed.KillEmbedded` Exception on exit, and then exit the current I. This is
103 useful to permanently exit a loop that create IPython embed instance.
103 useful to permanently exit a loop that create IPython embed instance.
104 """
104 """
105
105
106 self.shell.should_raise = True
106 self.shell.should_raise = True
107 self.shell.ask_exit()
107 self.shell.ask_exit()
108
108
109
109
110 class _Sentinel:
110 class _Sentinel:
111 def __init__(self, repr):
111 def __init__(self, repr):
112 assert isinstance(repr, str)
112 assert isinstance(repr, str)
113 self.repr = repr
113 self.repr = repr
114
114
115 def __repr__(self):
115 def __repr__(self):
116 return repr
116 return repr
117
117
118
118
119 class InteractiveShellEmbed(TerminalInteractiveShell):
119 class InteractiveShellEmbed(TerminalInteractiveShell):
120
120
121 dummy_mode = Bool(False)
121 dummy_mode = Bool(False)
122 exit_msg = Unicode('')
122 exit_msg = Unicode('')
123 embedded = CBool(True)
123 embedded = CBool(True)
124 should_raise = CBool(False)
124 should_raise = CBool(False)
125 # Like the base class display_banner is not configurable, but here it
125 # Like the base class display_banner is not configurable, but here it
126 # is True by default.
126 # is True by default.
127 display_banner = CBool(True)
127 display_banner = CBool(True)
128 exit_msg = Unicode()
128 exit_msg = Unicode()
129
129
130 # When embedding, by default we don't change the terminal title
130 # When embedding, by default we don't change the terminal title
131 term_title = Bool(False,
131 term_title = Bool(False,
132 help="Automatically set the terminal title"
132 help="Automatically set the terminal title"
133 ).tag(config=True)
133 ).tag(config=True)
134
134
135 _inactive_locations: Set[str] = set()
135 _inactive_locations: Set[str] = set()
136
136
137 def _disable_init_location(self):
137 def _disable_init_location(self):
138 """Disable the current Instance creation location"""
138 """Disable the current Instance creation location"""
139 InteractiveShellEmbed._inactive_locations.add(self._init_location_id)
139 InteractiveShellEmbed._inactive_locations.add(self._init_location_id)
140
140
141 @property
141 @property
142 def embedded_active(self):
142 def embedded_active(self):
143 return (self._call_location_id not in InteractiveShellEmbed._inactive_locations)\
143 return (self._call_location_id not in InteractiveShellEmbed._inactive_locations)\
144 and (self._init_location_id not in InteractiveShellEmbed._inactive_locations)
144 and (self._init_location_id not in InteractiveShellEmbed._inactive_locations)
145
145
146 @embedded_active.setter
146 @embedded_active.setter
147 def embedded_active(self, value):
147 def embedded_active(self, value):
148 if value:
148 if value:
149 InteractiveShellEmbed._inactive_locations.discard(
149 InteractiveShellEmbed._inactive_locations.discard(
150 self._call_location_id)
150 self._call_location_id)
151 InteractiveShellEmbed._inactive_locations.discard(
151 InteractiveShellEmbed._inactive_locations.discard(
152 self._init_location_id)
152 self._init_location_id)
153 else:
153 else:
154 InteractiveShellEmbed._inactive_locations.add(
154 InteractiveShellEmbed._inactive_locations.add(
155 self._call_location_id)
155 self._call_location_id)
156
156
157 def __init__(self, **kw):
157 def __init__(self, **kw):
158 assert (
158 assert (
159 "user_global_ns" not in kw
159 "user_global_ns" not in kw
160 ), "Key word argument `user_global_ns` has been replaced by `user_module` since IPython 4.0."
160 ), "Key word argument `user_global_ns` has been replaced by `user_module` since IPython 4.0."
161 # temporary fix for https://github.com/ipython/ipython/issues/14164
162 cls = type(self)
163 if cls._instance is None:
164 for subclass in cls._walk_mro():
165 subclass._instance = self
166 cls._instance = self
161
167
162 clid = kw.pop('_init_location_id', None)
168 clid = kw.pop('_init_location_id', None)
163 if not clid:
169 if not clid:
164 frame = sys._getframe(1)
170 frame = sys._getframe(1)
165 clid = '%s:%s' % (frame.f_code.co_filename, frame.f_lineno)
171 clid = '%s:%s' % (frame.f_code.co_filename, frame.f_lineno)
166 self._init_location_id = clid
172 self._init_location_id = clid
167
173
168 super(InteractiveShellEmbed,self).__init__(**kw)
174 super(InteractiveShellEmbed,self).__init__(**kw)
169
175
170 # don't use the ipython crash handler so that user exceptions aren't
176 # don't use the ipython crash handler so that user exceptions aren't
171 # trapped
177 # trapped
172 sys.excepthook = ultratb.FormattedTB(color_scheme=self.colors,
178 sys.excepthook = ultratb.FormattedTB(color_scheme=self.colors,
173 mode=self.xmode,
179 mode=self.xmode,
174 call_pdb=self.pdb)
180 call_pdb=self.pdb)
175
181
176 def init_sys_modules(self):
182 def init_sys_modules(self):
177 """
183 """
178 Explicitly overwrite :mod:`IPython.core.interactiveshell` to do nothing.
184 Explicitly overwrite :mod:`IPython.core.interactiveshell` to do nothing.
179 """
185 """
180 pass
186 pass
181
187
182 def init_magics(self):
188 def init_magics(self):
183 super(InteractiveShellEmbed, self).init_magics()
189 super(InteractiveShellEmbed, self).init_magics()
184 self.register_magics(EmbeddedMagics)
190 self.register_magics(EmbeddedMagics)
185
191
186 def __call__(
192 def __call__(
187 self,
193 self,
188 header="",
194 header="",
189 local_ns=None,
195 local_ns=None,
190 module=None,
196 module=None,
191 dummy=None,
197 dummy=None,
192 stack_depth=1,
198 stack_depth=1,
193 compile_flags=None,
199 compile_flags=None,
194 **kw
200 **kw
195 ):
201 ):
196 """Activate the interactive interpreter.
202 """Activate the interactive interpreter.
197
203
198 __call__(self,header='',local_ns=None,module=None,dummy=None) -> Start
204 __call__(self,header='',local_ns=None,module=None,dummy=None) -> Start
199 the interpreter shell with the given local and global namespaces, and
205 the interpreter shell with the given local and global namespaces, and
200 optionally print a header string at startup.
206 optionally print a header string at startup.
201
207
202 The shell can be globally activated/deactivated using the
208 The shell can be globally activated/deactivated using the
203 dummy_mode attribute. This allows you to turn off a shell used
209 dummy_mode attribute. This allows you to turn off a shell used
204 for debugging globally.
210 for debugging globally.
205
211
206 However, *each* time you call the shell you can override the current
212 However, *each* time you call the shell you can override the current
207 state of dummy_mode with the optional keyword parameter 'dummy'. For
213 state of dummy_mode with the optional keyword parameter 'dummy'. For
208 example, if you set dummy mode on with IPShell.dummy_mode = True, you
214 example, if you set dummy mode on with IPShell.dummy_mode = True, you
209 can still have a specific call work by making it as IPShell(dummy=False).
215 can still have a specific call work by making it as IPShell(dummy=False).
210 """
216 """
211
217
212 # we are called, set the underlying interactiveshell not to exit.
218 # we are called, set the underlying interactiveshell not to exit.
213 self.keep_running = True
219 self.keep_running = True
214
220
215 # If the user has turned it off, go away
221 # If the user has turned it off, go away
216 clid = kw.pop('_call_location_id', None)
222 clid = kw.pop('_call_location_id', None)
217 if not clid:
223 if not clid:
218 frame = sys._getframe(1)
224 frame = sys._getframe(1)
219 clid = '%s:%s' % (frame.f_code.co_filename, frame.f_lineno)
225 clid = '%s:%s' % (frame.f_code.co_filename, frame.f_lineno)
220 self._call_location_id = clid
226 self._call_location_id = clid
221
227
222 if not self.embedded_active:
228 if not self.embedded_active:
223 return
229 return
224
230
225 # Normal exits from interactive mode set this flag, so the shell can't
231 # Normal exits from interactive mode set this flag, so the shell can't
226 # re-enter (it checks this variable at the start of interactive mode).
232 # re-enter (it checks this variable at the start of interactive mode).
227 self.exit_now = False
233 self.exit_now = False
228
234
229 # Allow the dummy parameter to override the global __dummy_mode
235 # Allow the dummy parameter to override the global __dummy_mode
230 if dummy or (dummy != 0 and self.dummy_mode):
236 if dummy or (dummy != 0 and self.dummy_mode):
231 return
237 return
232
238
233 # self.banner is auto computed
239 # self.banner is auto computed
234 if header:
240 if header:
235 self.old_banner2 = self.banner2
241 self.old_banner2 = self.banner2
236 self.banner2 = self.banner2 + '\n' + header + '\n'
242 self.banner2 = self.banner2 + '\n' + header + '\n'
237 else:
243 else:
238 self.old_banner2 = ''
244 self.old_banner2 = ''
239
245
240 if self.display_banner:
246 if self.display_banner:
241 self.show_banner()
247 self.show_banner()
242
248
243 # Call the embedding code with a stack depth of 1 so it can skip over
249 # Call the embedding code with a stack depth of 1 so it can skip over
244 # our call and get the original caller's namespaces.
250 # our call and get the original caller's namespaces.
245 self.mainloop(
251 self.mainloop(
246 local_ns, module, stack_depth=stack_depth, compile_flags=compile_flags
252 local_ns, module, stack_depth=stack_depth, compile_flags=compile_flags
247 )
253 )
248
254
249 self.banner2 = self.old_banner2
255 self.banner2 = self.old_banner2
250
256
251 if self.exit_msg is not None:
257 if self.exit_msg is not None:
252 print(self.exit_msg)
258 print(self.exit_msg)
253
259
254 if self.should_raise:
260 if self.should_raise:
255 raise KillEmbedded('Embedded IPython raising error, as user requested.')
261 raise KillEmbedded('Embedded IPython raising error, as user requested.')
256
262
257 def mainloop(
263 def mainloop(
258 self,
264 self,
259 local_ns=None,
265 local_ns=None,
260 module=None,
266 module=None,
261 stack_depth=0,
267 stack_depth=0,
262 compile_flags=None,
268 compile_flags=None,
263 ):
269 ):
264 """Embeds IPython into a running python program.
270 """Embeds IPython into a running python program.
265
271
266 Parameters
272 Parameters
267 ----------
273 ----------
268 local_ns, module
274 local_ns, module
269 Working local namespace (a dict) and module (a module or similar
275 Working local namespace (a dict) and module (a module or similar
270 object). If given as None, they are automatically taken from the scope
276 object). If given as None, they are automatically taken from the scope
271 where the shell was called, so that program variables become visible.
277 where the shell was called, so that program variables become visible.
272 stack_depth : int
278 stack_depth : int
273 How many levels in the stack to go to looking for namespaces (when
279 How many levels in the stack to go to looking for namespaces (when
274 local_ns or module is None). This allows an intermediate caller to
280 local_ns or module is None). This allows an intermediate caller to
275 make sure that this function gets the namespace from the intended
281 make sure that this function gets the namespace from the intended
276 level in the stack. By default (0) it will get its locals and globals
282 level in the stack. By default (0) it will get its locals and globals
277 from the immediate caller.
283 from the immediate caller.
278 compile_flags
284 compile_flags
279 A bit field identifying the __future__ features
285 A bit field identifying the __future__ features
280 that are enabled, as passed to the builtin :func:`compile` function.
286 that are enabled, as passed to the builtin :func:`compile` function.
281 If given as None, they are automatically taken from the scope where
287 If given as None, they are automatically taken from the scope where
282 the shell was called.
288 the shell was called.
283
289
284 """
290 """
285
291
286 # Get locals and globals from caller
292 # Get locals and globals from caller
287 if ((local_ns is None or module is None or compile_flags is None)
293 if ((local_ns is None or module is None or compile_flags is None)
288 and self.default_user_namespaces):
294 and self.default_user_namespaces):
289 call_frame = sys._getframe(stack_depth).f_back
295 call_frame = sys._getframe(stack_depth).f_back
290
296
291 if local_ns is None:
297 if local_ns is None:
292 local_ns = call_frame.f_locals
298 local_ns = call_frame.f_locals
293 if module is None:
299 if module is None:
294 global_ns = call_frame.f_globals
300 global_ns = call_frame.f_globals
295 try:
301 try:
296 module = sys.modules[global_ns['__name__']]
302 module = sys.modules[global_ns['__name__']]
297 except KeyError:
303 except KeyError:
298 warnings.warn("Failed to get module %s" % \
304 warnings.warn("Failed to get module %s" % \
299 global_ns.get('__name__', 'unknown module')
305 global_ns.get('__name__', 'unknown module')
300 )
306 )
301 module = DummyMod()
307 module = DummyMod()
302 module.__dict__ = global_ns
308 module.__dict__ = global_ns
303 if compile_flags is None:
309 if compile_flags is None:
304 compile_flags = (call_frame.f_code.co_flags &
310 compile_flags = (call_frame.f_code.co_flags &
305 compilerop.PyCF_MASK)
311 compilerop.PyCF_MASK)
306
312
307 # Save original namespace and module so we can restore them after
313 # Save original namespace and module so we can restore them after
308 # embedding; otherwise the shell doesn't shut down correctly.
314 # embedding; otherwise the shell doesn't shut down correctly.
309 orig_user_module = self.user_module
315 orig_user_module = self.user_module
310 orig_user_ns = self.user_ns
316 orig_user_ns = self.user_ns
311 orig_compile_flags = self.compile.flags
317 orig_compile_flags = self.compile.flags
312
318
313 # Update namespaces and fire up interpreter
319 # Update namespaces and fire up interpreter
314
320
315 # The global one is easy, we can just throw it in
321 # The global one is easy, we can just throw it in
316 if module is not None:
322 if module is not None:
317 self.user_module = module
323 self.user_module = module
318
324
319 # But the user/local one is tricky: ipython needs it to store internal
325 # But the user/local one is tricky: ipython needs it to store internal
320 # data, but we also need the locals. We'll throw our hidden variables
326 # data, but we also need the locals. We'll throw our hidden variables
321 # like _ih and get_ipython() into the local namespace, but delete them
327 # like _ih and get_ipython() into the local namespace, but delete them
322 # later.
328 # later.
323 if local_ns is not None:
329 if local_ns is not None:
324 reentrant_local_ns = {k: v for (k, v) in local_ns.items() if k not in self.user_ns_hidden.keys()}
330 reentrant_local_ns = {k: v for (k, v) in local_ns.items() if k not in self.user_ns_hidden.keys()}
325 self.user_ns = reentrant_local_ns
331 self.user_ns = reentrant_local_ns
326 self.init_user_ns()
332 self.init_user_ns()
327
333
328 # Compiler flags
334 # Compiler flags
329 if compile_flags is not None:
335 if compile_flags is not None:
330 self.compile.flags = compile_flags
336 self.compile.flags = compile_flags
331
337
332 # make sure the tab-completer has the correct frame information, so it
338 # make sure the tab-completer has the correct frame information, so it
333 # actually completes using the frame's locals/globals
339 # actually completes using the frame's locals/globals
334 self.set_completer_frame()
340 self.set_completer_frame()
335
341
336 with self.builtin_trap, self.display_trap:
342 with self.builtin_trap, self.display_trap:
337 self.interact()
343 self.interact()
338
344
339 # now, purge out the local namespace of IPython's hidden variables.
345 # now, purge out the local namespace of IPython's hidden variables.
340 if local_ns is not None:
346 if local_ns is not None:
341 local_ns.update({k: v for (k, v) in self.user_ns.items() if k not in self.user_ns_hidden.keys()})
347 local_ns.update({k: v for (k, v) in self.user_ns.items() if k not in self.user_ns_hidden.keys()})
342
348
343
349
344 # Restore original namespace so shell can shut down when we exit.
350 # Restore original namespace so shell can shut down when we exit.
345 self.user_module = orig_user_module
351 self.user_module = orig_user_module
346 self.user_ns = orig_user_ns
352 self.user_ns = orig_user_ns
347 self.compile.flags = orig_compile_flags
353 self.compile.flags = orig_compile_flags
348
354
349
355
350 def embed(*, header="", compile_flags=None, **kwargs):
356 def embed(*, header="", compile_flags=None, **kwargs):
351 """Call this to embed IPython at the current point in your program.
357 """Call this to embed IPython at the current point in your program.
352
358
353 The first invocation of this will create a :class:`terminal.embed.InteractiveShellEmbed`
359 The first invocation of this will create a :class:`terminal.embed.InteractiveShellEmbed`
354 instance and then call it. Consecutive calls just call the already
360 instance and then call it. Consecutive calls just call the already
355 created instance.
361 created instance.
356
362
357 If you don't want the kernel to initialize the namespace
363 If you don't want the kernel to initialize the namespace
358 from the scope of the surrounding function,
364 from the scope of the surrounding function,
359 and/or you want to load full IPython configuration,
365 and/or you want to load full IPython configuration,
360 you probably want `IPython.start_ipython()` instead.
366 you probably want `IPython.start_ipython()` instead.
361
367
362 Here is a simple example::
368 Here is a simple example::
363
369
364 from IPython import embed
370 from IPython import embed
365 a = 10
371 a = 10
366 b = 20
372 b = 20
367 embed(header='First time')
373 embed(header='First time')
368 c = 30
374 c = 30
369 d = 40
375 d = 40
370 embed()
376 embed()
371
377
372 Parameters
378 Parameters
373 ----------
379 ----------
374
380
375 header : str
381 header : str
376 Optional header string to print at startup.
382 Optional header string to print at startup.
377 compile_flags
383 compile_flags
378 Passed to the `compile_flags` parameter of :py:meth:`terminal.embed.InteractiveShellEmbed.mainloop()`,
384 Passed to the `compile_flags` parameter of :py:meth:`terminal.embed.InteractiveShellEmbed.mainloop()`,
379 which is called when the :class:`terminal.embed.InteractiveShellEmbed` instance is called.
385 which is called when the :class:`terminal.embed.InteractiveShellEmbed` instance is called.
380 **kwargs : various, optional
386 **kwargs : various, optional
381 Any other kwargs will be passed to the :class:`terminal.embed.InteractiveShellEmbed` constructor.
387 Any other kwargs will be passed to the :class:`terminal.embed.InteractiveShellEmbed` constructor.
382 Full customization can be done by passing a traitlets :class:`Config` in as the
388 Full customization can be done by passing a traitlets :class:`Config` in as the
383 `config` argument (see :ref:`configure_start_ipython` and :ref:`terminal_options`).
389 `config` argument (see :ref:`configure_start_ipython` and :ref:`terminal_options`).
384 """
390 """
385 config = kwargs.get('config')
391 config = kwargs.get('config')
386 if config is None:
392 if config is None:
387 config = load_default_config()
393 config = load_default_config()
388 config.InteractiveShellEmbed = config.TerminalInteractiveShell
394 config.InteractiveShellEmbed = config.TerminalInteractiveShell
389 kwargs['config'] = config
395 kwargs['config'] = config
390 using = kwargs.get('using', 'sync')
396 using = kwargs.get('using', 'sync')
391 if using :
397 if using :
392 kwargs['config'].update({'TerminalInteractiveShell':{'loop_runner':using, 'colors':'NoColor', 'autoawait': using!='sync'}})
398 kwargs['config'].update({'TerminalInteractiveShell':{'loop_runner':using, 'colors':'NoColor', 'autoawait': using!='sync'}})
393 #save ps1/ps2 if defined
399 #save ps1/ps2 if defined
394 ps1 = None
400 ps1 = None
395 ps2 = None
401 ps2 = None
396 try:
402 try:
397 ps1 = sys.ps1
403 ps1 = sys.ps1
398 ps2 = sys.ps2
404 ps2 = sys.ps2
399 except AttributeError:
405 except AttributeError:
400 pass
406 pass
401 #save previous instance
407 #save previous instance
402 saved_shell_instance = InteractiveShell._instance
408 saved_shell_instance = InteractiveShell._instance
403 if saved_shell_instance is not None:
409 if saved_shell_instance is not None:
404 cls = type(saved_shell_instance)
410 cls = type(saved_shell_instance)
405 cls.clear_instance()
411 cls.clear_instance()
406 frame = sys._getframe(1)
412 frame = sys._getframe(1)
407 shell = InteractiveShellEmbed.instance(_init_location_id='%s:%s' % (
413 shell = InteractiveShellEmbed.instance(_init_location_id='%s:%s' % (
408 frame.f_code.co_filename, frame.f_lineno), **kwargs)
414 frame.f_code.co_filename, frame.f_lineno), **kwargs)
409 shell(header=header, stack_depth=2, compile_flags=compile_flags,
415 shell(header=header, stack_depth=2, compile_flags=compile_flags,
410 _call_location_id='%s:%s' % (frame.f_code.co_filename, frame.f_lineno))
416 _call_location_id='%s:%s' % (frame.f_code.co_filename, frame.f_lineno))
411 InteractiveShellEmbed.clear_instance()
417 InteractiveShellEmbed.clear_instance()
412 #restore previous instance
418 #restore previous instance
413 if saved_shell_instance is not None:
419 if saved_shell_instance is not None:
414 cls = type(saved_shell_instance)
420 cls = type(saved_shell_instance)
415 cls.clear_instance()
421 cls.clear_instance()
416 for subclass in cls._walk_mro():
422 for subclass in cls._walk_mro():
417 subclass._instance = saved_shell_instance
423 subclass._instance = saved_shell_instance
418 if ps1 is not None:
424 if ps1 is not None:
419 sys.ps1 = ps1
425 sys.ps1 = ps1
420 sys.ps2 = ps2
426 sys.ps2 = ps2
General Comments 0
You need to be logged in to leave comments. Login now