interactiveshell.py
683 lines
| 24.9 KiB
| text/x-python
|
PythonLexer
Brian Granger
|
r2761 | # -*- coding: utf-8 -*- | ||
"""Subclass of InteractiveShell for terminal based frontends.""" | ||||
#----------------------------------------------------------------------------- | ||||
# Copyright (C) 2001 Janko Hauser <jhauser@zscout.de> | ||||
# Copyright (C) 2001-2007 Fernando Perez. <fperez@colorado.edu> | ||||
Matthias BUSSONNIER
|
r5390 | # Copyright (C) 2008-2011 The IPython Development Team | ||
Brian Granger
|
r2761 | # | ||
# Distributed under the terms of the BSD License. The full license is in | ||||
# the file COPYING, distributed as part of this software. | ||||
#----------------------------------------------------------------------------- | ||||
#----------------------------------------------------------------------------- | ||||
# Imports | ||||
#----------------------------------------------------------------------------- | ||||
import __builtin__ | ||||
import bdb | ||||
import os | ||||
import re | ||||
import sys | ||||
Fernando Perez
|
r5435 | import textwrap | ||
Brian Granger
|
r2761 | |||
Thomas Kluyver
|
r4751 | try: | ||
from contextlib import nested | ||||
except: | ||||
from IPython.utils.nested_context import nested | ||||
MinRK
|
r6270 | from IPython.core.error import TryNext, UsageError | ||
Brian Granger
|
r2761 | from IPython.core.usage import interactive_usage, default_banner | ||
from IPython.core.interactiveshell import InteractiveShell, InteractiveShellABC | ||||
Fernando Perez
|
r5469 | from IPython.core.pylabtools import pylab_activate | ||
Thomas Kluyver
|
r3886 | from IPython.testing.skipdoctest import skip_doctest | ||
Brandon Parsons
|
r6655 | from IPython.utils.encoding import get_stream_enc | ||
Thomas Kluyver
|
r4734 | from IPython.utils import py3compat | ||
Brian Granger
|
r2761 | from IPython.utils.terminal import toggle_set_term_title, set_term_title | ||
from IPython.utils.process import abbrev_cwd | ||||
Matt Cottingham
|
r5367 | from IPython.utils.warn import warn, error | ||
Fernando Perez
|
r5435 | from IPython.utils.text import num_ini_spaces, SList | ||
MinRK
|
r5344 | from IPython.utils.traitlets import Integer, CBool, Unicode | ||
Brian Granger
|
r2761 | |||
#----------------------------------------------------------------------------- | ||||
# Utilities | ||||
#----------------------------------------------------------------------------- | ||||
def get_default_editor(): | ||||
try: | ||||
ed = os.environ['EDITOR'] | ||||
except KeyError: | ||||
if os.name == 'posix': | ||||
ed = 'vi' # the only one guaranteed to be there! | ||||
else: | ||||
ed = 'notepad' # same in Windows! | ||||
return ed | ||||
Fernando Perez
|
r5435 | |||
Thomas Kluyver
|
r5451 | def get_pasted_lines(sentinel, l_input=py3compat.input): | ||
Fernando Perez
|
r5435 | """ Yield pasted lines until the user enters the given sentinel value. | ||
""" | ||||
print "Pasting code; enter '%s' alone on the line to stop or use Ctrl-D." \ | ||||
% sentinel | ||||
while True: | ||||
try: | ||||
Thomas Kluyver
|
r5451 | l = l_input(':') | ||
Fernando Perez
|
r5435 | if l == sentinel: | ||
return | ||||
else: | ||||
yield l | ||||
except EOFError: | ||||
print '<EOF>' | ||||
return | ||||
Fernando Perez
|
r5437 | def strip_email_quotes(raw_lines): | ||
""" Strip email quotation marks at the beginning of each line. | ||||
We don't do any more input transofrmations here because the main shell's | ||||
prefiltering handles other cases. | ||||
""" | ||||
lines = [re.sub(r'^\s*(\s?>)+', '', l) for l in raw_lines] | ||||
return '\n'.join(lines) + '\n' | ||||
# These two functions are needed by the %paste/%cpaste magics. In practice | ||||
# they are basically methods (they take the shell as their first argument), but | ||||
# we leave them as standalone functions because eventually the magics | ||||
# themselves will become separate objects altogether. At that point, the | ||||
# magics will have access to the shell object, and these functions can be made | ||||
# methods of the magic object, but not of the shell. | ||||
Fernando Perez
|
r5435 | def store_or_execute(shell, block, name): | ||
""" Execute a block, or store it in a variable, per the user's request. | ||||
""" | ||||
Fernando Perez
|
r5437 | # Dedent and prefilter so what we store matches what is executed by | ||
# run_cell. | ||||
b = shell.prefilter(textwrap.dedent(block)) | ||||
Fernando Perez
|
r5435 | if name: | ||
# If storing it for further editing, run the prefilter on it | ||||
Fernando Perez
|
r5437 | shell.user_ns[name] = SList(b.splitlines()) | ||
Fernando Perez
|
r5435 | print "Block assigned to '%s'" % name | ||
else: | ||||
shell.user_ns['pasted_block'] = b | ||||
shell.run_cell(b) | ||||
Fernando Perez
|
r5437 | def rerun_pasted(shell, name='pasted_block'): | ||
Fernando Perez
|
r5435 | """ Rerun a previously pasted command. | ||
""" | ||||
Fernando Perez
|
r5437 | b = shell.user_ns.get(name) | ||
# Sanity checks | ||||
Fernando Perez
|
r5435 | if b is None: | ||
raise UsageError('No previous pasted block available') | ||||
Fernando Perez
|
r5437 | if not isinstance(b, basestring): | ||
raise UsageError( | ||||
"Variable 'pasted_block' is not a string, can't execute") | ||||
Fernando Perez
|
r5435 | print "Re-executing '%s...' (%d chars)"% (b.split('\n',1)[0], len(b)) | ||
shell.run_cell(b) | ||||
Fernando Perez
|
r5437 | |||
Fernando Perez
|
r6916 | #------------------------------------------------------------------------ | ||
# Terminal-specific magics | ||||
#------------------------------------------------------------------------ | ||||
def magic_autoindent(self, parameter_s = ''): | ||||
"""Toggle autoindent on/off (if available).""" | ||||
self.shell.set_autoindent() | ||||
print "Automatic indentation is:",['OFF','ON'][self.shell.autoindent] | ||||
@skip_doctest | ||||
def magic_cpaste(self, parameter_s=''): | ||||
"""Paste & execute a pre-formatted code block from clipboard. | ||||
You must terminate the block with '--' (two minus-signs) or Ctrl-D | ||||
alone on the line. You can also provide your own sentinel with '%paste | ||||
-s %%' ('%%' is the new sentinel for this operation) | ||||
The block is dedented prior to execution to enable execution of method | ||||
definitions. '>' and '+' characters at the beginning of a line are | ||||
ignored, to allow pasting directly from e-mails, diff files and | ||||
doctests (the '...' continuation prompt is also stripped). The | ||||
executed block is also assigned to variable named 'pasted_block' for | ||||
later editing with '%edit pasted_block'. | ||||
You can also pass a variable name as an argument, e.g. '%cpaste foo'. | ||||
This assigns the pasted block to variable 'foo' as string, without | ||||
dedenting or executing it (preceding >>> and + is still stripped) | ||||
'%cpaste -r' re-executes the block previously entered by cpaste. | ||||
Do not be alarmed by garbled output on Windows (it's a readline bug). | ||||
Just press enter and type -- (and press enter again) and the block | ||||
will be what was just pasted. | ||||
IPython statements (magics, shell escapes) are not supported (yet). | ||||
See also | ||||
-------- | ||||
paste: automatically pull code from clipboard. | ||||
Examples | ||||
-------- | ||||
:: | ||||
In [8]: %cpaste | ||||
Pasting code; enter '--' alone on the line to stop. | ||||
:>>> a = ["world!", "Hello"] | ||||
:>>> print " ".join(sorted(a)) | ||||
:-- | ||||
Hello world! | ||||
""" | ||||
opts, name = self.parse_options(parameter_s, 'rs:', mode='string') | ||||
if 'r' in opts: | ||||
rerun_pasted(self.shell) | ||||
return | ||||
sentinel = opts.get('s', '--') | ||||
block = strip_email_quotes(get_pasted_lines(sentinel)) | ||||
store_or_execute(self.shell, block, name) | ||||
def magic_paste(self, parameter_s=''): | ||||
"""Paste & execute a pre-formatted code block from clipboard. | ||||
The text is pulled directly from the clipboard without user | ||||
intervention and printed back on the screen before execution (unless | ||||
the -q flag is given to force quiet mode). | ||||
The block is dedented prior to execution to enable execution of method | ||||
definitions. '>' and '+' characters at the beginning of a line are | ||||
ignored, to allow pasting directly from e-mails, diff files and | ||||
doctests (the '...' continuation prompt is also stripped). The | ||||
executed block is also assigned to variable named 'pasted_block' for | ||||
later editing with '%edit pasted_block'. | ||||
You can also pass a variable name as an argument, e.g. '%paste foo'. | ||||
This assigns the pasted block to variable 'foo' as string, without | ||||
dedenting or executing it (preceding >>> and + is still stripped) | ||||
Options | ||||
------- | ||||
-r: re-executes the block previously entered by cpaste. | ||||
-q: quiet mode: do not echo the pasted text back to the terminal. | ||||
IPython statements (magics, shell escapes) are not supported (yet). | ||||
See also | ||||
-------- | ||||
cpaste: manually paste code into terminal until you mark its end. | ||||
""" | ||||
opts, name = self.parse_options(parameter_s, 'rq', mode='string') | ||||
if 'r' in opts: | ||||
rerun_pasted(self.shell) | ||||
return | ||||
try: | ||||
text = self.shell.hooks.clipboard_get() | ||||
block = strip_email_quotes(text.splitlines()) | ||||
except TryNext as clipboard_exc: | ||||
message = getattr(clipboard_exc, 'args') | ||||
if message: | ||||
error(message[0]) | ||||
else: | ||||
error('Could not get text from the clipboard.') | ||||
return | ||||
# By default, echo back to terminal unless quiet mode is requested | ||||
if 'q' not in opts: | ||||
write = self.shell.write | ||||
write(self.shell.pycolorize(block)) | ||||
if not block.endswith('\n'): | ||||
write('\n') | ||||
write("## -- End pasted text --\n") | ||||
store_or_execute(self.shell, block, name) | ||||
# Class-level: add a '%cls' magic only on Windows | ||||
if sys.platform == 'win32': | ||||
def magic_cls(self, s): | ||||
"""Clear screen. | ||||
""" | ||||
os.system("cls") | ||||
Brian Granger
|
r2761 | #----------------------------------------------------------------------------- | ||
# Main class | ||||
#----------------------------------------------------------------------------- | ||||
class TerminalInteractiveShell(InteractiveShell): | ||||
MinRK
|
r3963 | autoedit_syntax = CBool(False, config=True, | ||
help="auto editing of files with syntax errors.") | ||||
MinRK
|
r3464 | banner = Unicode('') | ||
MinRK
|
r3963 | banner1 = Unicode(default_banner, config=True, | ||
help="""The part of the banner to be printed before the profile""" | ||||
) | ||||
banner2 = Unicode('', config=True, | ||||
help="""The part of the banner to be printed after the profile""" | ||||
) | ||||
confirm_exit = CBool(True, config=True, | ||||
help=""" | ||||
Set to confirm when you try to exit IPython with an EOF (Control-D | ||||
MinRK
|
r3967 | in Unix, Control-Z/Enter in Windows). By typing 'exit' or 'quit', | ||
you can force a direct exit without any confirmation.""", | ||||
MinRK
|
r3963 | ) | ||
Brian Granger
|
r2761 | # This display_banner only controls whether or not self.show_banner() | ||
# is called when mainloop/interact are called. The default is False | ||||
# because for the terminal based application, the banner behavior | ||||
# is controlled by Global.display_banner, which IPythonApp looks at | ||||
# to determine if *it* should call show_banner() by hand or not. | ||||
display_banner = CBool(False) # This isn't configurable! | ||||
embedded = CBool(False) | ||||
embedded_active = CBool(False) | ||||
MinRK
|
r3963 | editor = Unicode(get_default_editor(), config=True, | ||
help="Set the editor used by IPython (default to $EDITOR/vi/notepad)." | ||||
) | ||||
pager = Unicode('less', config=True, | ||||
help="The shell program to be used for paging.") | ||||
MinRK
|
r5344 | screen_length = Integer(0, config=True, | ||
MinRK
|
r3963 | help= | ||
"""Number of lines of your screen, used to control printing of very | ||||
long strings. Strings longer than this number of lines will be sent | ||||
through a pager instead of directly printed. The default value for | ||||
this is 0, which means IPython will auto-detect your screen size every | ||||
time it needs to print certain potentially long strings (this doesn't | ||||
change the behavior of the 'print' keyword, it's only triggered | ||||
internally). If for some reason this isn't working well (it needs | ||||
curses support), specify it yourself. Otherwise don't change the | ||||
default.""", | ||||
) | ||||
term_title = CBool(False, config=True, | ||||
help="Enable auto setting the terminal title." | ||||
) | ||||
Fernando Perez
|
r5470 | # In the terminal, GUI control is done via PyOS_InputHook | ||
from IPython.lib.inputhook import enable_gui | ||||
enable_gui = staticmethod(enable_gui) | ||||
def __init__(self, config=None, ipython_dir=None, profile_dir=None, | ||||
user_ns=None, user_module=None, custom_exceptions=((),None), | ||||
usage=None, banner1=None, banner2=None, display_banner=None): | ||||
Brian Granger
|
r2761 | |||
super(TerminalInteractiveShell, self).__init__( | ||||
MinRK
|
r3963 | config=config, profile_dir=profile_dir, user_ns=user_ns, | ||
Thomas Kluyver
|
r5453 | user_module=user_module, custom_exceptions=custom_exceptions | ||
Brian Granger
|
r2761 | ) | ||
MinRK
|
r5276 | # use os.system instead of utils.process.system by default, | ||
# because piped system doesn't make sense in the Terminal: | ||||
self.system = self.system_raw | ||||
Bernardo B. Marques
|
r4872 | |||
Brian Granger
|
r2761 | self.init_term_title() | ||
self.init_usage(usage) | ||||
self.init_banner(banner1, banner2, display_banner) | ||||
#------------------------------------------------------------------------- | ||||
# Things related to the terminal | ||||
#------------------------------------------------------------------------- | ||||
@property | ||||
def usable_screen_length(self): | ||||
if self.screen_length == 0: | ||||
return 0 | ||||
else: | ||||
num_lines_bot = self.separate_in.count('\n')+1 | ||||
return self.screen_length - num_lines_bot | ||||
def init_term_title(self): | ||||
# Enable or disable the terminal title. | ||||
if self.term_title: | ||||
toggle_set_term_title(True) | ||||
set_term_title('IPython: ' + abbrev_cwd()) | ||||
else: | ||||
toggle_set_term_title(False) | ||||
#------------------------------------------------------------------------- | ||||
Fernando Perez
|
r3003 | # Things related to aliases | ||
#------------------------------------------------------------------------- | ||||
def init_alias(self): | ||||
# The parent class defines aliases that can be safely used with any | ||||
# frontend. | ||||
super(TerminalInteractiveShell, self).init_alias() | ||||
# Now define aliases that only make sense on the terminal, because they | ||||
# need direct access to the console in a way that we can't emulate in | ||||
# GUI or web frontend | ||||
if os.name == 'posix': | ||||
aliases = [('clear', 'clear'), ('more', 'more'), ('less', 'less'), | ||||
('man', 'man')] | ||||
elif os.name == 'nt': | ||||
aliases = [('cls', 'cls')] | ||||
for name, cmd in aliases: | ||||
self.alias_manager.define_alias(name, cmd) | ||||
#------------------------------------------------------------------------- | ||||
Brian Granger
|
r2761 | # Things related to the banner and usage | ||
#------------------------------------------------------------------------- | ||||
def _banner1_changed(self): | ||||
self.compute_banner() | ||||
def _banner2_changed(self): | ||||
self.compute_banner() | ||||
def _term_title_changed(self, name, new_value): | ||||
self.init_term_title() | ||||
def init_banner(self, banner1, banner2, display_banner): | ||||
if banner1 is not None: | ||||
self.banner1 = banner1 | ||||
if banner2 is not None: | ||||
self.banner2 = banner2 | ||||
if display_banner is not None: | ||||
self.display_banner = display_banner | ||||
self.compute_banner() | ||||
def show_banner(self, banner=None): | ||||
if banner is None: | ||||
banner = self.banner | ||||
self.write(banner) | ||||
def compute_banner(self): | ||||
Fernando Perez
|
r3008 | self.banner = self.banner1 | ||
MinRK
|
r4041 | if self.profile and self.profile != 'default': | ||
Brian Granger
|
r2761 | self.banner += '\nIPython profile: %s\n' % self.profile | ||
if self.banner2: | ||||
Fernando Perez
|
r3008 | self.banner += '\n' + self.banner2 | ||
Brian Granger
|
r2761 | |||
def init_usage(self, usage=None): | ||||
if usage is None: | ||||
self.usage = interactive_usage | ||||
else: | ||||
self.usage = usage | ||||
#------------------------------------------------------------------------- | ||||
# Mainloop and code execution logic | ||||
#------------------------------------------------------------------------- | ||||
def mainloop(self, display_banner=None): | ||||
"""Start the mainloop. | ||||
If an optional banner argument is given, it will override the | ||||
internally created default banner. | ||||
""" | ||||
Bernardo B. Marques
|
r4872 | |||
Brian Granger
|
r2761 | with nested(self.builtin_trap, self.display_trap): | ||
while 1: | ||||
try: | ||||
self.interact(display_banner=display_banner) | ||||
Bernardo B. Marques
|
r4872 | #self.interact_with_readline() | ||
Brian Granger
|
r2761 | # XXX for testing of a readline-decoupled repl loop, call | ||
# interact_with_readline above | ||||
break | ||||
except KeyboardInterrupt: | ||||
# this should not be necessary, but KeyboardInterrupt | ||||
# handling seems rather unpredictable... | ||||
self.write("\nKeyboardInterrupt in interact()\n") | ||||
Julian Taylor
|
r5013 | def _replace_rlhist_multiline(self, source_raw, hlen_before_cell): | ||
Julian Taylor
|
r5011 | """Store multiple lines as a single entry in history""" | ||
Julian Taylor
|
r5254 | |||
Julian Taylor
|
r5269 | # do nothing without readline or disabled multiline | ||
if not self.has_readline or not self.multiline_history: | ||||
return hlen_before_cell | ||||
Julian Taylor
|
r5254 | |||
Julian Taylor
|
r5273 | # windows rl has no remove_history_item | ||
if not hasattr(self.readline, "remove_history_item"): | ||||
return hlen_before_cell | ||||
Julian Taylor
|
r5269 | # skip empty cells | ||
if not source_raw.rstrip(): | ||||
return hlen_before_cell | ||||
# nothing changed do nothing, e.g. when rl removes consecutive dups | ||||
hlen = self.readline.get_current_history_length() | ||||
if hlen == hlen_before_cell: | ||||
Julian Taylor
|
r5270 | return hlen_before_cell | ||
Julian Taylor
|
r5269 | |||
for i in range(hlen - hlen_before_cell): | ||||
self.readline.remove_history_item(hlen - i - 1) | ||||
Brandon Parsons
|
r6655 | stdin_encoding = get_stream_enc(sys.stdin, 'utf-8') | ||
Julian Taylor
|
r5269 | self.readline.add_history(py3compat.unicode_to_str(source_raw.rstrip(), | ||
stdin_encoding)) | ||||
return self.readline.get_current_history_length() | ||||
Julian Taylor
|
r5011 | |||
Brian Granger
|
r2761 | def interact(self, display_banner=None): | ||
"""Closely emulate the interactive Python console.""" | ||||
Bernardo B. Marques
|
r4872 | # batch run -> do not interact | ||
Brian Granger
|
r2761 | if self.exit_now: | ||
return | ||||
if display_banner is None: | ||||
display_banner = self.display_banner | ||||
Bernardo B. Marques
|
r4872 | |||
MinRK
|
r4210 | if isinstance(display_banner, basestring): | ||
self.show_banner(display_banner) | ||||
elif display_banner: | ||||
Brian Granger
|
r2761 | self.show_banner() | ||
Fernando Perez
|
r3080 | more = False | ||
Bernardo B. Marques
|
r4872 | |||
Brian Granger
|
r2761 | if self.has_readline: | ||
self.readline_startup_hook(self.pre_readline) | ||||
Julian Taylor
|
r5269 | hlen_b4_cell = self.readline.get_current_history_length() | ||
Julian Taylor
|
r5272 | else: | ||
hlen_b4_cell = 0 | ||||
Brian Granger
|
r2761 | # exit_now is set by a call to %Exit or %Quit, through the | ||
# ask_exit callback. | ||||
Fernando Perez
|
r3077 | |||
Brian Granger
|
r2761 | while not self.exit_now: | ||
self.hooks.pre_prompt_hook() | ||||
if more: | ||||
try: | ||||
Thomas Kluyver
|
r5495 | prompt = self.prompt_manager.render('in2') | ||
Brian Granger
|
r2761 | except: | ||
self.showtraceback() | ||||
if self.autoindent: | ||||
self.rl_do_indent = True | ||||
Bernardo B. Marques
|
r4872 | |||
Brian Granger
|
r2761 | else: | ||
try: | ||||
Thomas Kluyver
|
r5495 | prompt = self.separate_in + self.prompt_manager.render('in') | ||
Brian Granger
|
r2761 | except: | ||
self.showtraceback() | ||||
try: | ||||
Fernando Perez
|
r3080 | line = self.raw_input(prompt) | ||
Brian Granger
|
r2761 | if self.exit_now: | ||
# quick exit on sys.std[in|out] close | ||||
break | ||||
if self.autoindent: | ||||
self.rl_do_indent = False | ||||
Bernardo B. Marques
|
r4872 | |||
Brian Granger
|
r2761 | except KeyboardInterrupt: | ||
#double-guard against keyboardinterrupts during kbdint handling | ||||
try: | ||||
self.write('\nKeyboardInterrupt\n') | ||||
Julian Taylor
|
r5012 | source_raw = self.input_splitter.source_raw_reset()[1] | ||
Julian Taylor
|
r5269 | hlen_b4_cell = \ | ||
self._replace_rlhist_multiline(source_raw, hlen_b4_cell) | ||||
Fernando Perez
|
r3080 | more = False | ||
Brian Granger
|
r2761 | except KeyboardInterrupt: | ||
pass | ||||
except EOFError: | ||||
if self.autoindent: | ||||
self.rl_do_indent = False | ||||
if self.has_readline: | ||||
self.readline_startup_hook(None) | ||||
self.write('\n') | ||||
self.exit() | ||||
except bdb.BdbQuit: | ||||
warn('The Python debugger has exited with a BdbQuit exception.\n' | ||||
'Because of how pdb handles the stack, it is impossible\n' | ||||
'for IPython to properly format this particular exception.\n' | ||||
'IPython will resume normal operation.') | ||||
except: | ||||
# exceptions here are VERY RARE, but they can be triggered | ||||
# asynchronously by signal handlers, for example. | ||||
self.showtraceback() | ||||
else: | ||||
Fernando Perez
|
r3080 | self.input_splitter.push(line) | ||
more = self.input_splitter.push_accepts_more() | ||||
Brian Granger
|
r2761 | if (self.SyntaxTB.last_syntax_error and | ||
self.autoedit_syntax): | ||||
self.edit_syntax_error() | ||||
Fernando Perez
|
r3080 | if not more: | ||
Fernando Perez
|
r3085 | source_raw = self.input_splitter.source_raw_reset()[1] | ||
Thomas Kluyver
|
r4995 | self.run_cell(source_raw, store_history=True) | ||
Julian Taylor
|
r5269 | hlen_b4_cell = \ | ||
self._replace_rlhist_multiline(source_raw, hlen_b4_cell) | ||||
Bernardo B. Marques
|
r4872 | |||
Brian Granger
|
r2761 | # Turn off the exit flag, so the mainloop can be restarted if desired | ||
self.exit_now = False | ||||
Fernando Perez
|
r3080 | def raw_input(self, prompt=''): | ||
"""Write a prompt and read a line. | ||||
The returned line does not include the trailing newline. | ||||
When the user enters the EOF key sequence, EOFError is raised. | ||||
Optional inputs: | ||||
- prompt(''): a string to be printed to prompt the user. | ||||
- continue_prompt(False): whether this line is the first one or a | ||||
continuation in a sequence of inputs. | ||||
""" | ||||
# Code run by the user may have modified the readline completer state. | ||||
# We must ensure that our completer is back in place. | ||||
if self.has_readline: | ||||
self.set_readline_completer() | ||||
Bernardo B. Marques
|
r4872 | |||
Fernando Perez
|
r3080 | try: | ||
Thomas Kluyver
|
r4731 | line = py3compat.str_to_unicode(self.raw_input_original(prompt)) | ||
Fernando Perez
|
r3080 | except ValueError: | ||
warn("\n********\nYou or a %run:ed script called sys.stdin.close()" | ||||
" or sys.stdout.close()!\nExiting IPython!") | ||||
self.ask_exit() | ||||
return "" | ||||
# Try to be reasonably smart about not re-indenting pasted input more | ||||
# than necessary. We do this by trimming out the auto-indent initial | ||||
# spaces, if the user's actual input started itself with whitespace. | ||||
if self.autoindent: | ||||
if num_ini_spaces(line) > self.indent_current_nsp: | ||||
line = line[self.indent_current_nsp:] | ||||
self.indent_current_nsp = 0 | ||||
Bernardo B. Marques
|
r4872 | |||
Fernando Perez
|
r3080 | return line | ||
Brian Granger
|
r2761 | #------------------------------------------------------------------------- | ||
# Methods to support auto-editing of SyntaxErrors. | ||||
#------------------------------------------------------------------------- | ||||
def edit_syntax_error(self): | ||||
"""The bottom half of the syntax error handler called in the main loop. | ||||
Loop until syntax error is fixed or user cancels. | ||||
""" | ||||
while self.SyntaxTB.last_syntax_error: | ||||
# copy and clear last_syntax_error | ||||
err = self.SyntaxTB.clear_err_state() | ||||
if not self._should_recompile(err): | ||||
return | ||||
try: | ||||
# may set last_syntax_error again if a SyntaxError is raised | ||||
self.safe_execfile(err.filename,self.user_ns) | ||||
except: | ||||
self.showtraceback() | ||||
else: | ||||
try: | ||||
Brandon Parsons
|
r6650 | f = open(err.filename) | ||
Brian Granger
|
r2761 | try: | ||
Bernardo B. Marques
|
r4872 | # This should be inside a display_trap block and I | ||
Brian Granger
|
r2761 | # think it is. | ||
sys.displayhook(f.read()) | ||||
finally: | ||||
f.close() | ||||
except: | ||||
self.showtraceback() | ||||
def _should_recompile(self,e): | ||||
"""Utility routine for edit_syntax_error""" | ||||
if e.filename in ('<ipython console>','<input>','<string>', | ||||
'<console>','<BackgroundJob compilation>', | ||||
None): | ||||
Bernardo B. Marques
|
r4872 | |||
Brian Granger
|
r2761 | return False | ||
try: | ||||
Bernardo B. Marques
|
r4872 | if (self.autoedit_syntax and | ||
Brian Granger
|
r2761 | not self.ask_yes_no('Return to editor to correct syntax error? ' | ||
'[Y/n] ','y')): | ||||
return False | ||||
except EOFError: | ||||
return False | ||||
def int0(x): | ||||
try: | ||||
return int(x) | ||||
except TypeError: | ||||
return 0 | ||||
# always pass integer line and offset values to editor hook | ||||
try: | ||||
self.hooks.fix_error_editor(e.filename, | ||||
int0(e.lineno),int0(e.offset),e.msg) | ||||
except TryNext: | ||||
warn('Could not open editor') | ||||
return False | ||||
return True | ||||
#------------------------------------------------------------------------- | ||||
# Things related to exiting | ||||
#------------------------------------------------------------------------- | ||||
def ask_exit(self): | ||||
""" Ask the shell to exit. Can be overiden and used as a callback. """ | ||||
self.exit_now = True | ||||
def exit(self): | ||||
"""Handle interactive exit. | ||||
This method calls the ask_exit callback.""" | ||||
if self.confirm_exit: | ||||
if self.ask_yes_no('Do you really want to exit ([y]/n)?','y'): | ||||
self.ask_exit() | ||||
else: | ||||
self.ask_exit() | ||||
Bernardo B. Marques
|
r4872 | |||
Fernando Perez
|
r6916 | #------------------------------------------------------------------------- | ||
# Things related to magics | ||||
#------------------------------------------------------------------------- | ||||
Fernando Perez
|
r2975 | |||
Fernando Perez
|
r6916 | def init_magics(self): | ||
super(TerminalInteractiveShell, self).init_magics() | ||||
self.define_magic('autoindent', magic_autoindent) | ||||
self.define_magic('cpaste', magic_cpaste) | ||||
self.define_magic('paste', magic_paste) | ||||
Matt Cottingham
|
r5367 | try: | ||
Fernando Perez
|
r6916 | magic_cls | ||
except NameError: | ||||
pass | ||||
else: | ||||
self.define_magic('cls', magic_cls) | ||||
Jörgen Stenarson
|
r5165 | |||
Thomas Kluyver
|
r4226 | def showindentationerror(self): | ||
super(TerminalInteractiveShell, self).showindentationerror() | ||||
Fernando Perez
|
r5437 | print("If you want to paste code into IPython, try the " | ||
"%paste and %cpaste magic functions.") | ||||
Brian Granger
|
r2761 | |||
InteractiveShellABC.register(TerminalInteractiveShell) | ||||