##// END OF EJS Templates
Fix fallback prompt & improve info on test failure
Thomas Kluyver -
Show More
@@ -1,56 +1,60 b''
1 1 # -*- coding: utf-8 -*-
2 2 """Tests for shellapp module.
3 3
4 4 Authors
5 5 -------
6 6 * Bradley Froehle
7 7 """
8 8 #-----------------------------------------------------------------------------
9 9 # Copyright (C) 2012 The IPython Development Team
10 10 #
11 11 # Distributed under the terms of the BSD License. The full license is in
12 12 # the file COPYING, distributed as part of this software.
13 13 #-----------------------------------------------------------------------------
14 14
15 15 #-----------------------------------------------------------------------------
16 16 # Imports
17 17 #-----------------------------------------------------------------------------
18 18 import unittest
19 19
20 20 from IPython.testing import decorators as dec
21 21 from IPython.testing import tools as tt
22 22
23 23 sqlite_err_maybe = dec.module_not_available('sqlite3')
24 24 SQLITE_NOT_AVAILABLE_ERROR = ('WARNING: IPython History requires SQLite,'
25 25 ' your history will not be saved\n')
26 26
27 27 class TestFileToRun(unittest.TestCase, tt.TempFileMixin):
28 28 """Test the behavior of the file_to_run parameter."""
29 29
30 30 def test_py_script_file_attribute(self):
31 31 """Test that `__file__` is set when running `ipython file.py`"""
32 32 src = "print(__file__)\n"
33 33 self.mktmp(src)
34 34
35 35 err = SQLITE_NOT_AVAILABLE_ERROR if sqlite_err_maybe else None
36 36 tt.ipexec_validate(self.fname, self.fname, err)
37 37
38 38 def test_ipy_script_file_attribute(self):
39 39 """Test that `__file__` is set when running `ipython file.ipy`"""
40 40 src = "print(__file__)\n"
41 41 self.mktmp(src, ext='.ipy')
42 42
43 43 err = SQLITE_NOT_AVAILABLE_ERROR if sqlite_err_maybe else None
44 44 tt.ipexec_validate(self.fname, self.fname, err)
45 45
46 46 # The commands option to ipexec_validate doesn't work on Windows, and it
47 47 # doesn't seem worth fixing
48 48 @dec.skip_win32
49 49 def test_py_script_file_attribute_interactively(self):
50 50 """Test that `__file__` is not set after `ipython -i file.py`"""
51 51 src = "True\n"
52 52 self.mktmp(src)
53 53
54 54 out, err = tt.ipexec(self.fname, options=['-i'],
55 commands=['"__file__" in globals()', 'exit()'])
56 self.assertIn("False", out)
55 commands=['"__file__" in globals()', 'print(123)', 'exit()'])
56 if 'False' not in out:
57 print("Subprocess stderr:")
58 print(err)
59 print('-----')
60 raise AssertionError("'False' not found in %r" % out)
@@ -1,542 +1,541 b''
1 1 """IPython terminal interface using prompt_toolkit"""
2 2
3 3 import os
4 4 import sys
5 5 import warnings
6 6 from warnings import warn
7 7
8 8 from IPython.core.interactiveshell import InteractiveShell, InteractiveShellABC
9 9 from IPython.utils import io
10 10 from IPython.utils.py3compat import input
11 11 from IPython.utils.terminal import toggle_set_term_title, set_term_title
12 12 from IPython.utils.process import abbrev_cwd
13 13 from traitlets import (
14 14 Bool, Unicode, Dict, Integer, observe, Instance, Type, default, Enum, Union,
15 15 Any,
16 16 )
17 17
18 18 from prompt_toolkit.document import Document
19 19 from prompt_toolkit.enums import DEFAULT_BUFFER, EditingMode
20 20 from prompt_toolkit.filters import (HasFocus, Condition, IsDone)
21 21 from prompt_toolkit.history import InMemoryHistory
22 22 from prompt_toolkit.shortcuts import create_prompt_application, create_eventloop, create_prompt_layout, create_output
23 23 from prompt_toolkit.interface import CommandLineInterface
24 24 from prompt_toolkit.key_binding.manager import KeyBindingManager
25 25 from prompt_toolkit.layout.processors import ConditionalProcessor, HighlightMatchingBracketProcessor
26 26 from prompt_toolkit.styles import PygmentsStyle, DynamicStyle
27 27
28 28 from pygments.styles import get_style_by_name
29 29 from pygments.style import Style
30 30 from pygments.token import Token
31 31
32 32 from .debugger import TerminalPdb, Pdb
33 33 from .magics import TerminalMagics
34 34 from .pt_inputhooks import get_inputhook_name_and_func
35 35 from .prompts import Prompts, ClassicPrompts, RichPromptDisplayHook
36 36 from .ptutils import IPythonPTCompleter, IPythonPTLexer
37 37 from .shortcuts import register_ipython_shortcuts
38 38
39 39 DISPLAY_BANNER_DEPRECATED = object()
40 40
41 41
42 42 class _NoStyle(Style): pass
43 43
44 44
45 45
46 46 _style_overrides_light_bg = {
47 47 Token.Prompt: '#0000ff',
48 48 Token.PromptNum: '#0000ee bold',
49 49 Token.OutPrompt: '#cc0000',
50 50 Token.OutPromptNum: '#bb0000 bold',
51 51 }
52 52
53 53 _style_overrides_linux = {
54 54 Token.Prompt: '#00cc00',
55 55 Token.PromptNum: '#00bb00 bold',
56 56 Token.OutPrompt: '#cc0000',
57 57 Token.OutPromptNum: '#bb0000 bold',
58 58 }
59 59
60 60 def get_default_editor():
61 61 try:
62 62 return os.environ['EDITOR']
63 63 except KeyError:
64 64 pass
65 65 except UnicodeError:
66 66 warn("$EDITOR environment variable is not pure ASCII. Using platform "
67 67 "default editor.")
68 68
69 69 if os.name == 'posix':
70 70 return 'vi' # the only one guaranteed to be there!
71 71 else:
72 72 return 'notepad' # same in Windows!
73 73
74 74 # conservatively check for tty
75 75 # overridden streams can result in things like:
76 76 # - sys.stdin = None
77 77 # - no isatty method
78 78 for _name in ('stdin', 'stdout', 'stderr'):
79 79 _stream = getattr(sys, _name)
80 80 if not _stream or not hasattr(_stream, 'isatty') or not _stream.isatty():
81 81 _is_tty = False
82 82 break
83 83 else:
84 84 _is_tty = True
85 85
86 86
87 87 _use_simple_prompt = ('IPY_TEST_SIMPLE_PROMPT' in os.environ) or (not _is_tty)
88 88
89 89 class TerminalInteractiveShell(InteractiveShell):
90 90 space_for_menu = Integer(6, help='Number of line at the bottom of the screen '
91 91 'to reserve for the completion menu'
92 92 ).tag(config=True)
93 93
94 94 def _space_for_menu_changed(self, old, new):
95 95 self._update_layout()
96 96
97 97 pt_cli = None
98 98 debugger_history = None
99 99 _pt_app = None
100 100
101 101 simple_prompt = Bool(_use_simple_prompt,
102 102 help="""Use `raw_input` for the REPL, without completion and prompt colors.
103 103
104 104 Useful when controlling IPython as a subprocess, and piping STDIN/OUT/ERR. Known usage are:
105 105 IPython own testing machinery, and emacs inferior-shell integration through elpy.
106 106
107 107 This mode default to `True` if the `IPY_TEST_SIMPLE_PROMPT`
108 108 environment variable is set, or the current terminal is not a tty."""
109 109 ).tag(config=True)
110 110
111 111 @property
112 112 def debugger_cls(self):
113 113 return Pdb if self.simple_prompt else TerminalPdb
114 114
115 115 confirm_exit = Bool(True,
116 116 help="""
117 117 Set to confirm when you try to exit IPython with an EOF (Control-D
118 118 in Unix, Control-Z/Enter in Windows). By typing 'exit' or 'quit',
119 119 you can force a direct exit without any confirmation.""",
120 120 ).tag(config=True)
121 121
122 122 editing_mode = Unicode('emacs',
123 123 help="Shortcut style to use at the prompt. 'vi' or 'emacs'.",
124 124 ).tag(config=True)
125 125
126 126 mouse_support = Bool(False,
127 127 help="Enable mouse support in the prompt\n(Note: prevents selecting text with the mouse)"
128 128 ).tag(config=True)
129 129
130 130 # We don't load the list of styles for the help string, because loading
131 131 # Pygments plugins takes time and can cause unexpected errors.
132 132 highlighting_style = Union([Unicode('legacy'), Type(klass=Style)],
133 133 help="""The name or class of a Pygments style to use for syntax
134 134 highlighting. To see available styles, run `pygmentize -L styles`."""
135 135 ).tag(config=True)
136 136
137 137
138 138 @observe('highlighting_style')
139 139 @observe('colors')
140 140 def _highlighting_style_changed(self, change):
141 141 self.refresh_style()
142 142
143 143 def refresh_style(self):
144 144 self._style = self._make_style_from_name_or_cls(self.highlighting_style)
145 145
146 146
147 147 highlighting_style_overrides = Dict(
148 148 help="Override highlighting format for specific tokens"
149 149 ).tag(config=True)
150 150
151 151 true_color = Bool(False,
152 152 help=("Use 24bit colors instead of 256 colors in prompt highlighting. "
153 153 "If your terminal supports true color, the following command "
154 154 "should print 'TRUECOLOR' in orange: "
155 155 "printf \"\\x1b[38;2;255;100;0mTRUECOLOR\\x1b[0m\\n\"")
156 156 ).tag(config=True)
157 157
158 158 editor = Unicode(get_default_editor(),
159 159 help="Set the editor used by IPython (default to $EDITOR/vi/notepad)."
160 160 ).tag(config=True)
161 161
162 162 prompts_class = Type(Prompts, help='Class used to generate Prompt token for prompt_toolkit').tag(config=True)
163 163
164 164 prompts = Instance(Prompts)
165 165
166 166 @default('prompts')
167 167 def _prompts_default(self):
168 168 return self.prompts_class(self)
169 169
170 170 @observe('prompts')
171 171 def _(self, change):
172 172 self._update_layout()
173 173
174 174 @default('displayhook_class')
175 175 def _displayhook_class_default(self):
176 176 return RichPromptDisplayHook
177 177
178 178 term_title = Bool(True,
179 179 help="Automatically set the terminal title"
180 180 ).tag(config=True)
181 181
182 182 term_title_format = Unicode("IPython: {cwd}",
183 183 help="Customize the terminal title format. This is a python format string. " +
184 184 "Available substitutions are: {cwd}."
185 185 ).tag(config=True)
186 186
187 187 display_completions = Enum(('column', 'multicolumn','readlinelike'),
188 188 help= ( "Options for displaying tab completions, 'column', 'multicolumn', and "
189 189 "'readlinelike'. These options are for `prompt_toolkit`, see "
190 190 "`prompt_toolkit` documentation for more information."
191 191 ),
192 192 default_value='multicolumn').tag(config=True)
193 193
194 194 highlight_matching_brackets = Bool(True,
195 195 help="Highlight matching brackets.",
196 196 ).tag(config=True)
197 197
198 198 extra_open_editor_shortcuts = Bool(False,
199 199 help="Enable vi (v) or Emacs (C-X C-E) shortcuts to open an external editor. "
200 200 "This is in addition to the F2 binding, which is always enabled."
201 201 ).tag(config=True)
202 202
203 203 handle_return = Any(None,
204 204 help="Provide an alternative handler to be called when the user presses "
205 205 "Return. This is an advanced option intended for debugging, which "
206 206 "may be changed or removed in later releases."
207 207 ).tag(config=True)
208 208
209 209 enable_history_search = Bool(True,
210 210 help="Allows to enable/disable the prompt toolkit history search"
211 211 ).tag(config=True)
212 212
213 213 @observe('term_title')
214 214 def init_term_title(self, change=None):
215 215 # Enable or disable the terminal title.
216 216 if self.term_title:
217 217 toggle_set_term_title(True)
218 218 set_term_title(self.term_title_format.format(cwd=abbrev_cwd()))
219 219 else:
220 220 toggle_set_term_title(False)
221 221
222 222 def init_display_formatter(self):
223 223 super(TerminalInteractiveShell, self).init_display_formatter()
224 224 # terminal only supports plain text
225 225 self.display_formatter.active_types = ['text/plain']
226 226 # disable `_ipython_display_`
227 227 self.display_formatter.ipython_display_formatter.enabled = False
228 228
229 229 def init_prompt_toolkit_cli(self):
230 230 if self.simple_prompt:
231 231 # Fall back to plain non-interactive output for tests.
232 # This is very limited, and only accepts a single line.
232 # This is very limited.
233 233 def prompt():
234 isp = self.input_splitter
234 itm = self.input_transformer_manager
235 235 prompt_text = "".join(x[1] for x in self.prompts.in_prompt_tokens())
236 lines = [input(prompt_text)]
236 237 prompt_continuation = "".join(x[1] for x in self.prompts.continuation_prompt_tokens())
237 while isp.push_accepts_more():
238 line = input(prompt_text)
239 isp.push(line)
240 prompt_text = prompt_continuation
241 return isp.source_reset()
238 while not itm.check_complete('\n'.join(lines)):
239 lines.append( input(prompt_continuation) )
240 return '\n'.join(lines)
242 241 self.prompt_for_code = prompt
243 242 return
244 243
245 244 # Set up keyboard shortcuts
246 245 kbmanager = KeyBindingManager.for_prompt(
247 246 enable_open_in_editor=self.extra_open_editor_shortcuts,
248 247 )
249 248 register_ipython_shortcuts(kbmanager.registry, self)
250 249
251 250 # Pre-populate history from IPython's history database
252 251 history = InMemoryHistory()
253 252 last_cell = u""
254 253 for __, ___, cell in self.history_manager.get_tail(self.history_load_length,
255 254 include_latest=True):
256 255 # Ignore blank lines and consecutive duplicates
257 256 cell = cell.rstrip()
258 257 if cell and (cell != last_cell):
259 258 history.append(cell)
260 259 last_cell = cell
261 260
262 261 self._style = self._make_style_from_name_or_cls(self.highlighting_style)
263 262 self.style = DynamicStyle(lambda: self._style)
264 263
265 264 editing_mode = getattr(EditingMode, self.editing_mode.upper())
266 265
267 266 def patch_stdout(**kwargs):
268 267 return self.pt_cli.patch_stdout_context(**kwargs)
269 268
270 269 self._pt_app = create_prompt_application(
271 270 editing_mode=editing_mode,
272 271 key_bindings_registry=kbmanager.registry,
273 272 history=history,
274 273 completer=IPythonPTCompleter(shell=self,
275 274 patch_stdout=patch_stdout),
276 275 enable_history_search=self.enable_history_search,
277 276 style=self.style,
278 277 mouse_support=self.mouse_support,
279 278 **self._layout_options()
280 279 )
281 280 self._eventloop = create_eventloop(self.inputhook)
282 281 self.pt_cli = CommandLineInterface(
283 282 self._pt_app, eventloop=self._eventloop,
284 283 output=create_output(true_color=self.true_color))
285 284
286 285 def _make_style_from_name_or_cls(self, name_or_cls):
287 286 """
288 287 Small wrapper that make an IPython compatible style from a style name
289 288
290 289 We need that to add style for prompt ... etc.
291 290 """
292 291 style_overrides = {}
293 292 if name_or_cls == 'legacy':
294 293 legacy = self.colors.lower()
295 294 if legacy == 'linux':
296 295 style_cls = get_style_by_name('monokai')
297 296 style_overrides = _style_overrides_linux
298 297 elif legacy == 'lightbg':
299 298 style_overrides = _style_overrides_light_bg
300 299 style_cls = get_style_by_name('pastie')
301 300 elif legacy == 'neutral':
302 301 # The default theme needs to be visible on both a dark background
303 302 # and a light background, because we can't tell what the terminal
304 303 # looks like. These tweaks to the default theme help with that.
305 304 style_cls = get_style_by_name('default')
306 305 style_overrides.update({
307 306 Token.Number: '#007700',
308 307 Token.Operator: 'noinherit',
309 308 Token.String: '#BB6622',
310 309 Token.Name.Function: '#2080D0',
311 310 Token.Name.Class: 'bold #2080D0',
312 311 Token.Name.Namespace: 'bold #2080D0',
313 312 Token.Prompt: '#009900',
314 313 Token.PromptNum: '#00ff00 bold',
315 314 Token.OutPrompt: '#990000',
316 315 Token.OutPromptNum: '#ff0000 bold',
317 316 })
318 317
319 318 # Hack: Due to limited color support on the Windows console
320 319 # the prompt colors will be wrong without this
321 320 if os.name == 'nt':
322 321 style_overrides.update({
323 322 Token.Prompt: '#ansidarkgreen',
324 323 Token.PromptNum: '#ansigreen bold',
325 324 Token.OutPrompt: '#ansidarkred',
326 325 Token.OutPromptNum: '#ansired bold',
327 326 })
328 327 elif legacy =='nocolor':
329 328 style_cls=_NoStyle
330 329 style_overrides = {}
331 330 else :
332 331 raise ValueError('Got unknown colors: ', legacy)
333 332 else :
334 333 if isinstance(name_or_cls, str):
335 334 style_cls = get_style_by_name(name_or_cls)
336 335 else:
337 336 style_cls = name_or_cls
338 337 style_overrides = {
339 338 Token.Prompt: '#009900',
340 339 Token.PromptNum: '#00ff00 bold',
341 340 Token.OutPrompt: '#990000',
342 341 Token.OutPromptNum: '#ff0000 bold',
343 342 }
344 343 style_overrides.update(self.highlighting_style_overrides)
345 344 style = PygmentsStyle.from_defaults(pygments_style_cls=style_cls,
346 345 style_dict=style_overrides)
347 346
348 347 return style
349 348
350 349 def _layout_options(self):
351 350 """
352 351 Return the current layout option for the current Terminal InteractiveShell
353 352 """
354 353 return {
355 354 'lexer':IPythonPTLexer(),
356 355 'reserve_space_for_menu':self.space_for_menu,
357 356 'get_prompt_tokens':self.prompts.in_prompt_tokens,
358 357 'get_continuation_tokens':self.prompts.continuation_prompt_tokens,
359 358 'multiline':True,
360 359 'display_completions_in_columns': (self.display_completions == 'multicolumn'),
361 360
362 361 # Highlight matching brackets, but only when this setting is
363 362 # enabled, and only when the DEFAULT_BUFFER has the focus.
364 363 'extra_input_processors': [ConditionalProcessor(
365 364 processor=HighlightMatchingBracketProcessor(chars='[](){}'),
366 365 filter=HasFocus(DEFAULT_BUFFER) & ~IsDone() &
367 366 Condition(lambda cli: self.highlight_matching_brackets))],
368 367 }
369 368
370 369 def _update_layout(self):
371 370 """
372 371 Ask for a re computation of the application layout, if for example ,
373 372 some configuration options have changed.
374 373 """
375 374 if self._pt_app:
376 375 self._pt_app.layout = create_prompt_layout(**self._layout_options())
377 376
378 377 def prompt_for_code(self):
379 378 with self.pt_cli.patch_stdout_context(raw=True):
380 379 document = self.pt_cli.run(
381 380 pre_run=self.pre_prompt, reset_current_buffer=True)
382 381 return document.text
383 382
384 383 def enable_win_unicode_console(self):
385 384 if sys.version_info >= (3, 6):
386 385 # Since PEP 528, Python uses the unicode APIs for the Windows
387 386 # console by default, so WUC shouldn't be needed.
388 387 return
389 388
390 389 import win_unicode_console
391 390 win_unicode_console.enable()
392 391
393 392 def init_io(self):
394 393 if sys.platform not in {'win32', 'cli'}:
395 394 return
396 395
397 396 self.enable_win_unicode_console()
398 397
399 398 import colorama
400 399 colorama.init()
401 400
402 401 # For some reason we make these wrappers around stdout/stderr.
403 402 # For now, we need to reset them so all output gets coloured.
404 403 # https://github.com/ipython/ipython/issues/8669
405 404 # io.std* are deprecated, but don't show our own deprecation warnings
406 405 # during initialization of the deprecated API.
407 406 with warnings.catch_warnings():
408 407 warnings.simplefilter('ignore', DeprecationWarning)
409 408 io.stdout = io.IOStream(sys.stdout)
410 409 io.stderr = io.IOStream(sys.stderr)
411 410
412 411 def init_magics(self):
413 412 super(TerminalInteractiveShell, self).init_magics()
414 413 self.register_magics(TerminalMagics)
415 414
416 415 def init_alias(self):
417 416 # The parent class defines aliases that can be safely used with any
418 417 # frontend.
419 418 super(TerminalInteractiveShell, self).init_alias()
420 419
421 420 # Now define aliases that only make sense on the terminal, because they
422 421 # need direct access to the console in a way that we can't emulate in
423 422 # GUI or web frontend
424 423 if os.name == 'posix':
425 424 for cmd in ['clear', 'more', 'less', 'man']:
426 425 self.alias_manager.soft_define_alias(cmd, cmd)
427 426
428 427
429 428 def __init__(self, *args, **kwargs):
430 429 super(TerminalInteractiveShell, self).__init__(*args, **kwargs)
431 430 self.init_prompt_toolkit_cli()
432 431 self.init_term_title()
433 432 self.keep_running = True
434 433
435 434 self.debugger_history = InMemoryHistory()
436 435
437 436 def ask_exit(self):
438 437 self.keep_running = False
439 438
440 439 rl_next_input = None
441 440
442 441 def pre_prompt(self):
443 442 if self.rl_next_input:
444 443 # We can't set the buffer here, because it will be reset just after
445 444 # this. Adding a callable to pre_run_callables does what we need
446 445 # after the buffer is reset.
447 446 s = self.rl_next_input
448 447 def set_doc():
449 448 self.pt_cli.application.buffer.document = Document(s)
450 449 if hasattr(self.pt_cli, 'pre_run_callables'):
451 450 self.pt_cli.pre_run_callables.append(set_doc)
452 451 else:
453 452 # Older version of prompt_toolkit; it's OK to set the document
454 453 # directly here.
455 454 set_doc()
456 455 self.rl_next_input = None
457 456
458 457 def interact(self, display_banner=DISPLAY_BANNER_DEPRECATED):
459 458
460 459 if display_banner is not DISPLAY_BANNER_DEPRECATED:
461 460 warn('interact `display_banner` argument is deprecated since IPython 5.0. Call `show_banner()` if needed.', DeprecationWarning, stacklevel=2)
462 461
463 462 self.keep_running = True
464 463 while self.keep_running:
465 464 print(self.separate_in, end='')
466 465
467 466 try:
468 467 code = self.prompt_for_code()
469 468 except EOFError:
470 469 if (not self.confirm_exit) \
471 470 or self.ask_yes_no('Do you really want to exit ([y]/n)?','y','n'):
472 471 self.ask_exit()
473 472
474 473 else:
475 474 if code:
476 475 self.run_cell(code, store_history=True)
477 476
478 477 def mainloop(self, display_banner=DISPLAY_BANNER_DEPRECATED):
479 478 # An extra layer of protection in case someone mashing Ctrl-C breaks
480 479 # out of our internal code.
481 480 if display_banner is not DISPLAY_BANNER_DEPRECATED:
482 481 warn('mainloop `display_banner` argument is deprecated since IPython 5.0. Call `show_banner()` if needed.', DeprecationWarning, stacklevel=2)
483 482 while True:
484 483 try:
485 484 self.interact()
486 485 break
487 486 except KeyboardInterrupt as e:
488 487 print("\n%s escaped interact()\n" % type(e).__name__)
489 488 finally:
490 489 # An interrupt during the eventloop will mess up the
491 490 # internal state of the prompt_toolkit library.
492 491 # Stopping the eventloop fixes this, see
493 492 # https://github.com/ipython/ipython/pull/9867
494 493 if hasattr(self, '_eventloop'):
495 494 self._eventloop.stop()
496 495
497 496 _inputhook = None
498 497 def inputhook(self, context):
499 498 if self._inputhook is not None:
500 499 self._inputhook(context)
501 500
502 501 active_eventloop = None
503 502 def enable_gui(self, gui=None):
504 503 if gui:
505 504 self.active_eventloop, self._inputhook =\
506 505 get_inputhook_name_and_func(gui)
507 506 else:
508 507 self.active_eventloop = self._inputhook = None
509 508
510 509 # Run !system commands directly, not through pipes, so terminal programs
511 510 # work correctly.
512 511 system = InteractiveShell.system_raw
513 512
514 513 def auto_rewrite_input(self, cmd):
515 514 """Overridden from the parent class to use fancy rewriting prompt"""
516 515 if not self.show_rewritten_input:
517 516 return
518 517
519 518 tokens = self.prompts.rewrite_prompt_tokens()
520 519 if self.pt_cli:
521 520 self.pt_cli.print_tokens(tokens)
522 521 print(cmd)
523 522 else:
524 523 prompt = ''.join(s for t, s in tokens)
525 524 print(prompt, cmd, sep='')
526 525
527 526 _prompts_before = None
528 527 def switch_doctest_mode(self, mode):
529 528 """Switch prompts to classic for %doctest_mode"""
530 529 if mode:
531 530 self._prompts_before = self.prompts
532 531 self.prompts = ClassicPrompts(self)
533 532 elif self._prompts_before:
534 533 self.prompts = self._prompts_before
535 534 self._prompts_before = None
536 535 self._update_layout()
537 536
538 537
539 538 InteractiveShellABC.register(TerminalInteractiveShell)
540 539
541 540 if __name__ == '__main__':
542 541 TerminalInteractiveShell.instance().interact()
General Comments 0
You need to be logged in to leave comments. Login now