diff options
author | Nikita Slyusarev <nslus@yandex-team.com> | 2022-02-10 16:46:53 +0300 |
---|---|---|
committer | Daniil Cherednik <dcherednik@yandex-team.ru> | 2022-02-10 16:46:53 +0300 |
commit | 469afdc4e2587bf62ecdd096b75a0baa444c4012 (patch) | |
tree | 49e222ea1c5804306084bb3ae065bb702625360f /contrib/python/ipython/py2/IPython/terminal | |
parent | cd77cecfc03a3eaf87816af28a33067c4f0cdb59 (diff) | |
download | ydb-469afdc4e2587bf62ecdd096b75a0baa444c4012.tar.gz |
Restoring authorship annotation for Nikita Slyusarev <nslus@yandex-team.com>. Commit 2 of 2.
Diffstat (limited to 'contrib/python/ipython/py2/IPython/terminal')
18 files changed, 1789 insertions, 1789 deletions
diff --git a/contrib/python/ipython/py2/IPython/terminal/debugger.py b/contrib/python/ipython/py2/IPython/terminal/debugger.py index 4be1bae6a8..c68a3204a6 100644 --- a/contrib/python/ipython/py2/IPython/terminal/debugger.py +++ b/contrib/python/ipython/py2/IPython/terminal/debugger.py @@ -1,46 +1,46 @@ import signal import sys -from IPython.core.debugger import Pdb - -from IPython.core.completer import IPCompleter -from .ptutils import IPythonPTCompleter +from IPython.core.debugger import Pdb + +from IPython.core.completer import IPCompleter +from .ptutils import IPythonPTCompleter from .shortcuts import suspend_to_bg, cursor_in_leading_ws - + from prompt_toolkit.enums import DEFAULT_BUFFER from prompt_toolkit.filters import (Condition, HasFocus, HasSelection, ViInsertMode, EmacsInsertMode) from prompt_toolkit.keys import Keys from prompt_toolkit.key_binding.manager import KeyBindingManager from prompt_toolkit.key_binding.bindings.completion import display_completions_like_readline -from prompt_toolkit.token import Token -from prompt_toolkit.shortcuts import create_prompt_application -from prompt_toolkit.interface import CommandLineInterface -from prompt_toolkit.enums import EditingMode - - -class TerminalPdb(Pdb): - def __init__(self, *args, **kwargs): - Pdb.__init__(self, *args, **kwargs) - self._ptcomp = None - self.pt_init() - - def pt_init(self): - def get_prompt_tokens(cli): - return [(Token.Prompt, self.prompt)] - +from prompt_toolkit.token import Token +from prompt_toolkit.shortcuts import create_prompt_application +from prompt_toolkit.interface import CommandLineInterface +from prompt_toolkit.enums import EditingMode + + +class TerminalPdb(Pdb): + def __init__(self, *args, **kwargs): + Pdb.__init__(self, *args, **kwargs) + self._ptcomp = None + self.pt_init() + + def pt_init(self): + def get_prompt_tokens(cli): + return [(Token.Prompt, self.prompt)] + def patch_stdout(**kwargs): return self.pt_cli.patch_stdout_context(**kwargs) - if self._ptcomp is None: - compl = IPCompleter(shell=self.shell, - namespace={}, - global_namespace={}, - use_readline=False, - parent=self.shell, - ) + if self._ptcomp is None: + compl = IPCompleter(shell=self.shell, + namespace={}, + global_namespace={}, + use_readline=False, + parent=self.shell, + ) self._ptcomp = IPythonPTCompleter(compl, patch_stdout=patch_stdout) - + kbmanager = KeyBindingManager.for_prompt() supports_suspend = Condition(lambda cli: hasattr(signal, 'SIGTSTP')) kbmanager.registry.add_binding(Keys.ControlZ, filter=supports_suspend @@ -55,55 +55,55 @@ class TerminalPdb(Pdb): ))(display_completions_like_readline) multicolumn = (self.shell.display_completions == 'multicolumn') - self._pt_app = create_prompt_application( - editing_mode=getattr(EditingMode, self.shell.editing_mode.upper()), + self._pt_app = create_prompt_application( + editing_mode=getattr(EditingMode, self.shell.editing_mode.upper()), key_bindings_registry=kbmanager.registry, - history=self.shell.debugger_history, - completer= self._ptcomp, - enable_history_search=True, - mouse_support=self.shell.mouse_support, + history=self.shell.debugger_history, + completer= self._ptcomp, + enable_history_search=True, + mouse_support=self.shell.mouse_support, get_prompt_tokens=get_prompt_tokens, display_completions_in_columns=multicolumn, style=self.shell.style - ) - self.pt_cli = CommandLineInterface(self._pt_app, eventloop=self.shell._eventloop) - - def cmdloop(self, intro=None): - """Repeatedly issue a prompt, accept input, parse an initial prefix - off the received input, and dispatch to action methods, passing them - the remainder of the line as argument. - - override the same methods from cmd.Cmd to provide prompt toolkit replacement. - """ - if not self.use_rawinput: - raise ValueError('Sorry ipdb does not support use_rawinput=False') - - self.preloop() - - try: - if intro is not None: - self.intro = intro - if self.intro: - self.stdout.write(str(self.intro)+"\n") - stop = None - while not stop: - if self.cmdqueue: - line = self.cmdqueue.pop(0) - else: - self._ptcomp.ipy_completer.namespace = self.curframe_locals - self._ptcomp.ipy_completer.global_namespace = self.curframe.f_globals - try: - line = self.pt_cli.run(reset_current_buffer=True).text - except EOFError: - line = 'EOF' - line = self.precmd(line) - stop = self.onecmd(line) - stop = self.postcmd(stop, line) - self.postloop() - except Exception: - raise - - + ) + self.pt_cli = CommandLineInterface(self._pt_app, eventloop=self.shell._eventloop) + + def cmdloop(self, intro=None): + """Repeatedly issue a prompt, accept input, parse an initial prefix + off the received input, and dispatch to action methods, passing them + the remainder of the line as argument. + + override the same methods from cmd.Cmd to provide prompt toolkit replacement. + """ + if not self.use_rawinput: + raise ValueError('Sorry ipdb does not support use_rawinput=False') + + self.preloop() + + try: + if intro is not None: + self.intro = intro + if self.intro: + self.stdout.write(str(self.intro)+"\n") + stop = None + while not stop: + if self.cmdqueue: + line = self.cmdqueue.pop(0) + else: + self._ptcomp.ipy_completer.namespace = self.curframe_locals + self._ptcomp.ipy_completer.global_namespace = self.curframe.f_globals + try: + line = self.pt_cli.run(reset_current_buffer=True).text + except EOFError: + line = 'EOF' + line = self.precmd(line) + stop = self.onecmd(line) + stop = self.postcmd(stop, line) + self.postloop() + except Exception: + raise + + def set_trace(frame=None): """ Start debugging from `frame`. diff --git a/contrib/python/ipython/py2/IPython/terminal/embed.py b/contrib/python/ipython/py2/IPython/terminal/embed.py index 9f8be00a77..5ad70431e4 100644 --- a/contrib/python/ipython/py2/IPython/terminal/embed.py +++ b/contrib/python/ipython/py2/IPython/terminal/embed.py @@ -14,7 +14,7 @@ import warnings from IPython.core import ultratb, compilerop from IPython.core import magic_arguments from IPython.core.magic import Magics, magics_class, line_magic -from IPython.core.interactiveshell import DummyMod, InteractiveShell +from IPython.core.interactiveshell import DummyMod, InteractiveShell from IPython.terminal.interactiveshell import TerminalInteractiveShell from IPython.terminal.ipapp import load_default_config @@ -117,33 +117,33 @@ class InteractiveShellEmbed(TerminalInteractiveShell): display_banner = CBool(True) exit_msg = Unicode() - # When embedding, by default we don't change the terminal title - term_title = Bool(False, - help="Automatically set the terminal title" - ).tag(config=True) - - _inactive_locations = set() - - @property - def embedded_active(self): + # When embedding, by default we don't change the terminal title + term_title = Bool(False, + help="Automatically set the terminal title" + ).tag(config=True) + + _inactive_locations = set() + + @property + def embedded_active(self): return (self._call_location_id not in InteractiveShellEmbed._inactive_locations)\ and (self._init_location_id not in InteractiveShellEmbed._inactive_locations) - + def _disable_init_location(self): """Disable the current Instance creation location""" InteractiveShellEmbed._inactive_locations.add(self._init_location_id) - @embedded_active.setter - def embedded_active(self, value): + @embedded_active.setter + def embedded_active(self, value): if value: InteractiveShellEmbed._inactive_locations.discard( self._call_location_id) InteractiveShellEmbed._inactive_locations.discard( self._init_location_id) - else: + else: InteractiveShellEmbed._inactive_locations.add( self._call_location_id) - + def __init__(self, **kw): if kw.get('user_global_ns', None) is not None: raise DeprecationWarning( @@ -154,7 +154,7 @@ class InteractiveShellEmbed(TerminalInteractiveShell): frame = sys._getframe(1) clid = '%s:%s' % (frame.f_code.co_filename, frame.f_lineno) self._init_location_id = clid - + super(InteractiveShellEmbed,self).__init__(**kw) # don't use the ipython crash handler so that user exceptions aren't @@ -219,9 +219,9 @@ class InteractiveShellEmbed(TerminalInteractiveShell): else: self.old_banner2 = '' - if self.display_banner: - self.show_banner() - + if self.display_banner: + self.show_banner() + # Call the embedding code with a stack depth of 1 so it can skip over # our call and get the original caller's namespaces. self.mainloop(local_ns, module, stack_depth=stack_depth, @@ -264,11 +264,11 @@ class InteractiveShellEmbed(TerminalInteractiveShell): """ if (global_ns is not None) and (module is None): - raise DeprecationWarning("'global_ns' keyword argument is deprecated, and has been removed in IPython 5.0 use `module` keyword argument instead.") + raise DeprecationWarning("'global_ns' keyword argument is deprecated, and has been removed in IPython 5.0 use `module` keyword argument instead.") + + if (display_banner is not None): + warnings.warn("The display_banner parameter is deprecated since IPython 4.0", DeprecationWarning) - if (display_banner is not None): - warnings.warn("The display_banner parameter is deprecated since IPython 4.0", DeprecationWarning) - # Get locals and globals from caller if ((local_ns is None or module is None or compile_flags is None) and self.default_user_namespaces): @@ -278,14 +278,14 @@ class InteractiveShellEmbed(TerminalInteractiveShell): local_ns = call_frame.f_locals if module is None: global_ns = call_frame.f_globals - try: - module = sys.modules[global_ns['__name__']] - except KeyError: - warnings.warn("Failed to get module %s" % \ - global_ns.get('__name__', 'unknown module') - ) - module = DummyMod() - module.__dict__ = global_ns + try: + module = sys.modules[global_ns['__name__']] + except KeyError: + warnings.warn("Failed to get module %s" % \ + global_ns.get('__name__', 'unknown module') + ) + module = DummyMod() + module.__dict__ = global_ns if compile_flags is None: compile_flags = (call_frame.f_code.co_flags & compilerop.PyCF_MASK) @@ -320,7 +320,7 @@ class InteractiveShellEmbed(TerminalInteractiveShell): self.set_completer_frame() with self.builtin_trap, self.display_trap: - self.interact() + self.interact() # now, purge out the local namespace of IPython's hidden variables. if local_ns is not None: @@ -378,7 +378,7 @@ def embed(**kwargs): if saved_shell_instance is not None: cls = type(saved_shell_instance) cls.clear_instance() - frame = sys._getframe(1) + frame = sys._getframe(1) shell = InteractiveShellEmbed.instance(_init_location_id='%s:%s' % ( frame.f_code.co_filename, frame.f_lineno), **kwargs) shell(header=header, stack_depth=2, compile_flags=compile_flags, diff --git a/contrib/python/ipython/py2/IPython/terminal/interactiveshell.py b/contrib/python/ipython/py2/IPython/terminal/interactiveshell.py index c5b0d7d921..f67cc6b502 100644 --- a/contrib/python/ipython/py2/IPython/terminal/interactiveshell.py +++ b/contrib/python/ipython/py2/IPython/terminal/interactiveshell.py @@ -1,68 +1,68 @@ -"""IPython terminal interface using prompt_toolkit""" +"""IPython terminal interface using prompt_toolkit""" from __future__ import print_function import os import sys -import warnings -from warnings import warn +import warnings +from warnings import warn from IPython.core.interactiveshell import InteractiveShell, InteractiveShellABC -from IPython.utils import io +from IPython.utils import io from IPython.utils.py3compat import PY3, cast_unicode_py2, input, string_types from IPython.utils.terminal import toggle_set_term_title, set_term_title from IPython.utils.process import abbrev_cwd from traitlets import Bool, Unicode, Dict, Integer, observe, Instance, Type, default, Enum, Union from prompt_toolkit.document import Document -from prompt_toolkit.enums import DEFAULT_BUFFER, EditingMode -from prompt_toolkit.filters import (HasFocus, Condition, IsDone) -from prompt_toolkit.history import InMemoryHistory -from prompt_toolkit.shortcuts import create_prompt_application, create_eventloop, create_prompt_layout, create_output -from prompt_toolkit.interface import CommandLineInterface -from prompt_toolkit.key_binding.manager import KeyBindingManager -from prompt_toolkit.layout.processors import ConditionalProcessor, HighlightMatchingBracketProcessor -from prompt_toolkit.styles import PygmentsStyle, DynamicStyle +from prompt_toolkit.enums import DEFAULT_BUFFER, EditingMode +from prompt_toolkit.filters import (HasFocus, Condition, IsDone) +from prompt_toolkit.history import InMemoryHistory +from prompt_toolkit.shortcuts import create_prompt_application, create_eventloop, create_prompt_layout, create_output +from prompt_toolkit.interface import CommandLineInterface +from prompt_toolkit.key_binding.manager import KeyBindingManager +from prompt_toolkit.layout.processors import ConditionalProcessor, HighlightMatchingBracketProcessor +from prompt_toolkit.styles import PygmentsStyle, DynamicStyle from pygments.styles import get_style_by_name from pygments.style import Style -from pygments.token import Token - -from .debugger import TerminalPdb, Pdb -from .magics import TerminalMagics +from pygments.token import Token + +from .debugger import TerminalPdb, Pdb +from .magics import TerminalMagics from .pt_inputhooks import get_inputhook_name_and_func -from .prompts import Prompts, ClassicPrompts, RichPromptDisplayHook -from .ptutils import IPythonPTCompleter, IPythonPTLexer -from .shortcuts import register_ipython_shortcuts - -DISPLAY_BANNER_DEPRECATED = object() - - -from pygments.style import Style - -class _NoStyle(Style): pass - - - -_style_overrides_light_bg = { - Token.Prompt: '#0000ff', - Token.PromptNum: '#0000ee bold', - Token.OutPrompt: '#cc0000', - Token.OutPromptNum: '#bb0000 bold', -} - -_style_overrides_linux = { - Token.Prompt: '#00cc00', - Token.PromptNum: '#00bb00 bold', - Token.OutPrompt: '#cc0000', - Token.OutPromptNum: '#bb0000 bold', -} - - - +from .prompts import Prompts, ClassicPrompts, RichPromptDisplayHook +from .ptutils import IPythonPTCompleter, IPythonPTLexer +from .shortcuts import register_ipython_shortcuts + +DISPLAY_BANNER_DEPRECATED = object() + + +from pygments.style import Style + +class _NoStyle(Style): pass + + + +_style_overrides_light_bg = { + Token.Prompt: '#0000ff', + Token.PromptNum: '#0000ee bold', + Token.OutPrompt: '#cc0000', + Token.OutPromptNum: '#bb0000 bold', +} + +_style_overrides_linux = { + Token.Prompt: '#00cc00', + Token.PromptNum: '#00bb00 bold', + Token.OutPrompt: '#cc0000', + Token.OutPromptNum: '#bb0000 bold', +} + + + def get_default_editor(): try: ed = os.environ['EDITOR'] - if not PY3: + if not PY3: ed = ed.decode() return ed except KeyError: @@ -76,153 +76,153 @@ def get_default_editor(): else: return 'notepad' # same in Windows! -# conservatively check for tty -# overridden streams can result in things like: -# - sys.stdin = None -# - no isatty method -for _name in ('stdin', 'stdout', 'stderr'): - _stream = getattr(sys, _name) - if not _stream or not hasattr(_stream, 'isatty') or not _stream.isatty(): - _is_tty = False - break -else: - _is_tty = True +# conservatively check for tty +# overridden streams can result in things like: +# - sys.stdin = None +# - no isatty method +for _name in ('stdin', 'stdout', 'stderr'): + _stream = getattr(sys, _name) + if not _stream or not hasattr(_stream, 'isatty') or not _stream.isatty(): + _is_tty = False + break +else: + _is_tty = True -_use_simple_prompt = ('IPY_TEST_SIMPLE_PROMPT' in os.environ) or (not _is_tty) +_use_simple_prompt = ('IPY_TEST_SIMPLE_PROMPT' in os.environ) or (not _is_tty) -class TerminalInteractiveShell(InteractiveShell): - space_for_menu = Integer(6, help='Number of line at the bottom of the screen ' - 'to reserve for the completion menu' - ).tag(config=True) +class TerminalInteractiveShell(InteractiveShell): + space_for_menu = Integer(6, help='Number of line at the bottom of the screen ' + 'to reserve for the completion menu' + ).tag(config=True) - def _space_for_menu_changed(self, old, new): - self._update_layout() + def _space_for_menu_changed(self, old, new): + self._update_layout() - pt_cli = None - debugger_history = None - _pt_app = None + pt_cli = None + debugger_history = None + _pt_app = None - simple_prompt = Bool(_use_simple_prompt, + simple_prompt = Bool(_use_simple_prompt, help="""Use `raw_input` for the REPL, without completion and prompt colors. - Useful when controlling IPython as a subprocess, and piping STDIN/OUT/ERR. Known usage are: - IPython own testing machinery, and emacs inferior-shell integration through elpy. + Useful when controlling IPython as a subprocess, and piping STDIN/OUT/ERR. Known usage are: + IPython own testing machinery, and emacs inferior-shell integration through elpy. - This mode default to `True` if the `IPY_TEST_SIMPLE_PROMPT` - environment variable is set, or the current terminal is not a tty. + This mode default to `True` if the `IPY_TEST_SIMPLE_PROMPT` + environment variable is set, or the current terminal is not a tty. - """ - ).tag(config=True) + """ + ).tag(config=True) - @property - def debugger_cls(self): - return Pdb if self.simple_prompt else TerminalPdb + @property + def debugger_cls(self): + return Pdb if self.simple_prompt else TerminalPdb - confirm_exit = Bool(True, - help=""" - Set to confirm when you try to exit IPython with an EOF (Control-D - in Unix, Control-Z/Enter in Windows). By typing 'exit' or 'quit', - you can force a direct exit without any confirmation.""", - ).tag(config=True) + confirm_exit = Bool(True, + help=""" + Set to confirm when you try to exit IPython with an EOF (Control-D + in Unix, Control-Z/Enter in Windows). By typing 'exit' or 'quit', + you can force a direct exit without any confirmation.""", + ).tag(config=True) - editing_mode = Unicode('emacs', - help="Shortcut style to use at the prompt. 'vi' or 'emacs'.", - ).tag(config=True) + editing_mode = Unicode('emacs', + help="Shortcut style to use at the prompt. 'vi' or 'emacs'.", + ).tag(config=True) - mouse_support = Bool(False, - help="Enable mouse support in the prompt" - ).tag(config=True) + mouse_support = Bool(False, + help="Enable mouse support in the prompt" + ).tag(config=True) # We don't load the list of styles for the help string, because loading # Pygments plugins takes time and can cause unexpected errors. highlighting_style = Union([Unicode('legacy'), Type(klass=Style)], help="""The name or class of a Pygments style to use for syntax highlighting. To see available styles, run `pygmentize -L styles`.""" - ).tag(config=True) + ).tag(config=True) - @observe('highlighting_style') - @observe('colors') - def _highlighting_style_changed(self, change): - self.refresh_style() + @observe('highlighting_style') + @observe('colors') + def _highlighting_style_changed(self, change): + self.refresh_style() - def refresh_style(self): + def refresh_style(self): self._style = self._make_style_from_name_or_cls(self.highlighting_style) - highlighting_style_overrides = Dict( - help="Override highlighting format for specific tokens" - ).tag(config=True) + highlighting_style_overrides = Dict( + help="Override highlighting format for specific tokens" + ).tag(config=True) - true_color = Bool(False, - help=("Use 24bit colors instead of 256 colors in prompt highlighting. " - "If your terminal supports true color, the following command " - "should print 'TRUECOLOR' in orange: " - "printf \"\\x1b[38;2;255;100;0mTRUECOLOR\\x1b[0m\\n\"") - ).tag(config=True) + true_color = Bool(False, + help=("Use 24bit colors instead of 256 colors in prompt highlighting. " + "If your terminal supports true color, the following command " + "should print 'TRUECOLOR' in orange: " + "printf \"\\x1b[38;2;255;100;0mTRUECOLOR\\x1b[0m\\n\"") + ).tag(config=True) - editor = Unicode(get_default_editor(), - help="Set the editor used by IPython (default to $EDITOR/vi/notepad)." - ).tag(config=True) + editor = Unicode(get_default_editor(), + help="Set the editor used by IPython (default to $EDITOR/vi/notepad)." + ).tag(config=True) - prompts_class = Type(Prompts, help='Class used to generate Prompt token for prompt_toolkit').tag(config=True) + prompts_class = Type(Prompts, help='Class used to generate Prompt token for prompt_toolkit').tag(config=True) - prompts = Instance(Prompts) + prompts = Instance(Prompts) - @default('prompts') - def _prompts_default(self): - return self.prompts_class(self) + @default('prompts') + def _prompts_default(self): + return self.prompts_class(self) - @observe('prompts') - def _(self, change): - self._update_layout() + @observe('prompts') + def _(self, change): + self._update_layout() - @default('displayhook_class') - def _displayhook_class_default(self): - return RichPromptDisplayHook + @default('displayhook_class') + def _displayhook_class_default(self): + return RichPromptDisplayHook - term_title = Bool(True, - help="Automatically set the terminal title" - ).tag(config=True) + term_title = Bool(True, + help="Automatically set the terminal title" + ).tag(config=True) display_completions = Enum(('column', 'multicolumn','readlinelike'), - help= ( "Options for displaying tab completions, 'column', 'multicolumn', and " - "'readlinelike'. These options are for `prompt_toolkit`, see " - "`prompt_toolkit` documentation for more information." - ), - default_value='multicolumn').tag(config=True) + help= ( "Options for displaying tab completions, 'column', 'multicolumn', and " + "'readlinelike'. These options are for `prompt_toolkit`, see " + "`prompt_toolkit` documentation for more information." + ), + default_value='multicolumn').tag(config=True) - highlight_matching_brackets = Bool(True, + highlight_matching_brackets = Bool(True, help="Highlight matching brackets.", - ).tag(config=True) + ).tag(config=True) extra_open_editor_shortcuts = Bool(False, help="Enable vi (v) or Emacs (C-X C-E) shortcuts to open an external editor. " "This is in addition to the F2 binding, which is always enabled." ).tag(config=True) - @observe('term_title') - def init_term_title(self, change=None): - # 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) - - def init_display_formatter(self): - super(TerminalInteractiveShell, self).init_display_formatter() - # terminal only supports plain text - self.display_formatter.active_types = ['text/plain'] + @observe('term_title') + def init_term_title(self, change=None): + # 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) + + def init_display_formatter(self): + super(TerminalInteractiveShell, self).init_display_formatter() + # terminal only supports plain text + self.display_formatter.active_types = ['text/plain'] # disable `_ipython_display_` self.display_formatter.ipython_display_formatter.enabled = False - def init_prompt_toolkit_cli(self): - if self.simple_prompt: - # Fall back to plain non-interactive output for tests. - # This is very limited, and only accepts a single line. - def prompt(): + def init_prompt_toolkit_cli(self): + if self.simple_prompt: + # Fall back to plain non-interactive output for tests. + # This is very limited, and only accepts a single line. + def prompt(): isp = self.input_splitter prompt_text = "".join(x[1] for x in self.prompts.in_prompt_tokens()) prompt_continuation = "".join(x[1] for x in self.prompts.continuation_prompt_tokens()) @@ -231,82 +231,82 @@ class TerminalInteractiveShell(InteractiveShell): isp.push(line) prompt_text = prompt_continuation return isp.source_reset() - self.prompt_for_code = prompt - return + self.prompt_for_code = prompt + return - # Set up keyboard shortcuts + # Set up keyboard shortcuts kbmanager = KeyBindingManager.for_prompt( enable_open_in_editor=self.extra_open_editor_shortcuts, ) - register_ipython_shortcuts(kbmanager.registry, self) - - # Pre-populate history from IPython's history database - history = InMemoryHistory() - last_cell = u"" - for __, ___, cell in self.history_manager.get_tail(self.history_load_length, - include_latest=True): - # Ignore blank lines and consecutive duplicates - cell = cell.rstrip() - if cell and (cell != last_cell): - history.append(cell) + register_ipython_shortcuts(kbmanager.registry, self) + + # Pre-populate history from IPython's history database + history = InMemoryHistory() + last_cell = u"" + for __, ___, cell in self.history_manager.get_tail(self.history_load_length, + include_latest=True): + # Ignore blank lines and consecutive duplicates + cell = cell.rstrip() + if cell and (cell != last_cell): + history.append(cell) last_cell = cell self._style = self._make_style_from_name_or_cls(self.highlighting_style) self.style = DynamicStyle(lambda: self._style) - editing_mode = getattr(EditingMode, self.editing_mode.upper()) + editing_mode = getattr(EditingMode, self.editing_mode.upper()) def patch_stdout(**kwargs): return self.pt_cli.patch_stdout_context(**kwargs) - self._pt_app = create_prompt_application( - editing_mode=editing_mode, - key_bindings_registry=kbmanager.registry, - history=history, + self._pt_app = create_prompt_application( + editing_mode=editing_mode, + key_bindings_registry=kbmanager.registry, + history=history, completer=IPythonPTCompleter(shell=self, patch_stdout=patch_stdout), - enable_history_search=True, + enable_history_search=True, style=self.style, - mouse_support=self.mouse_support, - **self._layout_options() - ) - self._eventloop = create_eventloop(self.inputhook) - self.pt_cli = CommandLineInterface( - self._pt_app, eventloop=self._eventloop, - output=create_output(true_color=self.true_color)) + mouse_support=self.mouse_support, + **self._layout_options() + ) + self._eventloop = create_eventloop(self.inputhook) + self.pt_cli = CommandLineInterface( + self._pt_app, eventloop=self._eventloop, + output=create_output(true_color=self.true_color)) def _make_style_from_name_or_cls(self, name_or_cls): - """ - Small wrapper that make an IPython compatible style from a style name + """ + Small wrapper that make an IPython compatible style from a style name We need that to add style for prompt ... etc. """ - style_overrides = {} + style_overrides = {} if name_or_cls == 'legacy': - legacy = self.colors.lower() - if legacy == 'linux': - style_cls = get_style_by_name('monokai') - style_overrides = _style_overrides_linux - elif legacy == 'lightbg': - style_overrides = _style_overrides_light_bg - style_cls = get_style_by_name('pastie') - elif legacy == 'neutral': - # The default theme needs to be visible on both a dark background - # and a light background, because we can't tell what the terminal - # looks like. These tweaks to the default theme help with that. - style_cls = get_style_by_name('default') - style_overrides.update({ - Token.Number: '#007700', - Token.Operator: 'noinherit', - Token.String: '#BB6622', - Token.Name.Function: '#2080D0', - Token.Name.Class: 'bold #2080D0', - Token.Name.Namespace: 'bold #2080D0', - Token.Prompt: '#009900', - Token.PromptNum: '#00ff00 bold', - Token.OutPrompt: '#990000', - Token.OutPromptNum: '#ff0000 bold', - }) + legacy = self.colors.lower() + if legacy == 'linux': + style_cls = get_style_by_name('monokai') + style_overrides = _style_overrides_linux + elif legacy == 'lightbg': + style_overrides = _style_overrides_light_bg + style_cls = get_style_by_name('pastie') + elif legacy == 'neutral': + # The default theme needs to be visible on both a dark background + # and a light background, because we can't tell what the terminal + # looks like. These tweaks to the default theme help with that. + style_cls = get_style_by_name('default') + style_overrides.update({ + Token.Number: '#007700', + Token.Operator: 'noinherit', + Token.String: '#BB6622', + Token.Name.Function: '#2080D0', + Token.Name.Class: 'bold #2080D0', + Token.Name.Namespace: 'bold #2080D0', + Token.Prompt: '#009900', + Token.PromptNum: '#00ff00 bold', + Token.OutPrompt: '#990000', + Token.OutPromptNum: '#ff0000 bold', + }) # Hack: Due to limited color support on the Windows console # the prompt colors will be wrong without this @@ -317,111 +317,111 @@ class TerminalInteractiveShell(InteractiveShell): Token.OutPrompt: '#ansidarkred', Token.OutPromptNum: '#ansired bold', }) - elif legacy =='nocolor': - style_cls=_NoStyle - style_overrides = {} - else : - raise ValueError('Got unknown colors: ', legacy) - else : + elif legacy =='nocolor': + style_cls=_NoStyle + style_overrides = {} + else : + raise ValueError('Got unknown colors: ', legacy) + else : if isinstance(name_or_cls, string_types): style_cls = get_style_by_name(name_or_cls) else: style_cls = name_or_cls - style_overrides = { - Token.Prompt: '#009900', - Token.PromptNum: '#00ff00 bold', - Token.OutPrompt: '#990000', - Token.OutPromptNum: '#ff0000 bold', - } - style_overrides.update(self.highlighting_style_overrides) - style = PygmentsStyle.from_defaults(pygments_style_cls=style_cls, - style_dict=style_overrides) - - return style - - def _layout_options(self): - """ - Return the current layout option for the current Terminal InteractiveShell - """ - return { - 'lexer':IPythonPTLexer(), - 'reserve_space_for_menu':self.space_for_menu, - 'get_prompt_tokens':self.prompts.in_prompt_tokens, - 'get_continuation_tokens':self.prompts.continuation_prompt_tokens, - 'multiline':True, - 'display_completions_in_columns': (self.display_completions == 'multicolumn'), - - # Highlight matching brackets, but only when this setting is - # enabled, and only when the DEFAULT_BUFFER has the focus. - 'extra_input_processors': [ConditionalProcessor( - processor=HighlightMatchingBracketProcessor(chars='[](){}'), - filter=HasFocus(DEFAULT_BUFFER) & ~IsDone() & - Condition(lambda cli: self.highlight_matching_brackets))], - } - - def _update_layout(self): + style_overrides = { + Token.Prompt: '#009900', + Token.PromptNum: '#00ff00 bold', + Token.OutPrompt: '#990000', + Token.OutPromptNum: '#ff0000 bold', + } + style_overrides.update(self.highlighting_style_overrides) + style = PygmentsStyle.from_defaults(pygments_style_cls=style_cls, + style_dict=style_overrides) + + return style + + def _layout_options(self): """ - Ask for a re computation of the application layout, if for example , - some configuration options have changed. - """ - if self._pt_app: - self._pt_app.layout = create_prompt_layout(**self._layout_options()) - - def prompt_for_code(self): - document = self.pt_cli.run( - pre_run=self.pre_prompt, reset_current_buffer=True) - return document.text - - def enable_win_unicode_console(self): + Return the current layout option for the current Terminal InteractiveShell + """ + return { + 'lexer':IPythonPTLexer(), + 'reserve_space_for_menu':self.space_for_menu, + 'get_prompt_tokens':self.prompts.in_prompt_tokens, + 'get_continuation_tokens':self.prompts.continuation_prompt_tokens, + 'multiline':True, + 'display_completions_in_columns': (self.display_completions == 'multicolumn'), + + # Highlight matching brackets, but only when this setting is + # enabled, and only when the DEFAULT_BUFFER has the focus. + 'extra_input_processors': [ConditionalProcessor( + processor=HighlightMatchingBracketProcessor(chars='[](){}'), + filter=HasFocus(DEFAULT_BUFFER) & ~IsDone() & + Condition(lambda cli: self.highlight_matching_brackets))], + } + + def _update_layout(self): + """ + Ask for a re computation of the application layout, if for example , + some configuration options have changed. + """ + if self._pt_app: + self._pt_app.layout = create_prompt_layout(**self._layout_options()) + + def prompt_for_code(self): + document = self.pt_cli.run( + pre_run=self.pre_prompt, reset_current_buffer=True) + return document.text + + def enable_win_unicode_console(self): if sys.version_info >= (3, 6): # Since PEP 528, Python uses the unicode APIs for the Windows # console by default, so WUC shouldn't be needed. return - import win_unicode_console + import win_unicode_console - if PY3: - win_unicode_console.enable() + if PY3: + win_unicode_console.enable() else: - # https://github.com/ipython/ipython/issues/9768 - from win_unicode_console.streams import (TextStreamWrapper, - stdout_text_transcoded, stderr_text_transcoded) + # https://github.com/ipython/ipython/issues/9768 + from win_unicode_console.streams import (TextStreamWrapper, + stdout_text_transcoded, stderr_text_transcoded) - class LenientStrStreamWrapper(TextStreamWrapper): - def write(self, s): - if isinstance(s, bytes): - s = s.decode(self.encoding, 'replace') + class LenientStrStreamWrapper(TextStreamWrapper): + def write(self, s): + if isinstance(s, bytes): + s = s.decode(self.encoding, 'replace') - self.base.write(s) + self.base.write(s) - stdout_text_str = LenientStrStreamWrapper(stdout_text_transcoded) - stderr_text_str = LenientStrStreamWrapper(stderr_text_transcoded) + stdout_text_str = LenientStrStreamWrapper(stdout_text_transcoded) + stderr_text_str = LenientStrStreamWrapper(stderr_text_transcoded) - win_unicode_console.enable(stdout=stdout_text_str, - stderr=stderr_text_str) + win_unicode_console.enable(stdout=stdout_text_str, + stderr=stderr_text_str) - def init_io(self): - if sys.platform not in {'win32', 'cli'}: - return + def init_io(self): + if sys.platform not in {'win32', 'cli'}: + return - self.enable_win_unicode_console() + self.enable_win_unicode_console() - import colorama - colorama.init() + import colorama + colorama.init() - # For some reason we make these wrappers around stdout/stderr. - # For now, we need to reset them so all output gets coloured. - # https://github.com/ipython/ipython/issues/8669 - # io.std* are deprecated, but don't show our own deprecation warnings - # during initialization of the deprecated API. - with warnings.catch_warnings(): - warnings.simplefilter('ignore', DeprecationWarning) - io.stdout = io.IOStream(sys.stdout) - io.stderr = io.IOStream(sys.stderr) + # For some reason we make these wrappers around stdout/stderr. + # For now, we need to reset them so all output gets coloured. + # https://github.com/ipython/ipython/issues/8669 + # io.std* are deprecated, but don't show our own deprecation warnings + # during initialization of the deprecated API. + with warnings.catch_warnings(): + warnings.simplefilter('ignore', DeprecationWarning) + io.stdout = io.IOStream(sys.stdout) + io.stderr = io.IOStream(sys.stderr) - def init_magics(self): - super(TerminalInteractiveShell, self).init_magics() - self.register_magics(TerminalMagics) + def init_magics(self): + super(TerminalInteractiveShell, self).init_magics() + self.register_magics(TerminalMagics) def init_alias(self): # The parent class defines aliases that can be safely used with any @@ -432,25 +432,25 @@ class TerminalInteractiveShell(InteractiveShell): # need direct access to the console in a way that we can't emulate in # GUI or web frontend if os.name == 'posix': - for cmd in ['clear', 'more', 'less', 'man']: - self.alias_manager.soft_define_alias(cmd, cmd) + for cmd in ['clear', 'more', 'less', 'man']: + self.alias_manager.soft_define_alias(cmd, cmd) - def __init__(self, *args, **kwargs): - super(TerminalInteractiveShell, self).__init__(*args, **kwargs) - self.init_prompt_toolkit_cli() - self.init_term_title() - self.keep_running = True + def __init__(self, *args, **kwargs): + super(TerminalInteractiveShell, self).__init__(*args, **kwargs) + self.init_prompt_toolkit_cli() + self.init_term_title() + self.keep_running = True - self.debugger_history = InMemoryHistory() + self.debugger_history = InMemoryHistory() - def ask_exit(self): - self.keep_running = False + def ask_exit(self): + self.keep_running = False - rl_next_input = None + rl_next_input = None - def pre_prompt(self): - if self.rl_next_input: + def pre_prompt(self): + if self.rl_next_input: # We can't set the buffer here, because it will be reset just after # this. Adding a callable to pre_run_callables does what we need # after the buffer is reset. @@ -463,37 +463,37 @@ class TerminalInteractiveShell(InteractiveShell): # Older version of prompt_toolkit; it's OK to set the document # directly here. set_doc() - self.rl_next_input = None + self.rl_next_input = None - def interact(self, display_banner=DISPLAY_BANNER_DEPRECATED): + def interact(self, display_banner=DISPLAY_BANNER_DEPRECATED): - if display_banner is not DISPLAY_BANNER_DEPRECATED: - warn('interact `display_banner` argument is deprecated since IPython 5.0. Call `show_banner()` if needed.', DeprecationWarning, stacklevel=2) + if display_banner is not DISPLAY_BANNER_DEPRECATED: + warn('interact `display_banner` argument is deprecated since IPython 5.0. Call `show_banner()` if needed.', DeprecationWarning, stacklevel=2) - self.keep_running = True - while self.keep_running: - print(self.separate_in, end='') + self.keep_running = True + while self.keep_running: + print(self.separate_in, end='') try: - code = self.prompt_for_code() - except EOFError: - if (not self.confirm_exit) \ - or self.ask_yes_no('Do you really want to exit ([y]/n)?','y','n'): - self.ask_exit() + code = self.prompt_for_code() + except EOFError: + if (not self.confirm_exit) \ + or self.ask_yes_no('Do you really want to exit ([y]/n)?','y','n'): + self.ask_exit() else: - if code: - self.run_cell(code, store_history=True) - - def mainloop(self, display_banner=DISPLAY_BANNER_DEPRECATED): - # An extra layer of protection in case someone mashing Ctrl-C breaks - # out of our internal code. - if display_banner is not DISPLAY_BANNER_DEPRECATED: - warn('mainloop `display_banner` argument is deprecated since IPython 5.0. Call `show_banner()` if needed.', DeprecationWarning, stacklevel=2) - while True: + if code: + self.run_cell(code, store_history=True) + + def mainloop(self, display_banner=DISPLAY_BANNER_DEPRECATED): + # An extra layer of protection in case someone mashing Ctrl-C breaks + # out of our internal code. + if display_banner is not DISPLAY_BANNER_DEPRECATED: + warn('mainloop `display_banner` argument is deprecated since IPython 5.0. Call `show_banner()` if needed.', DeprecationWarning, stacklevel=2) + while True: try: - self.interact() - break + self.interact() + break except KeyboardInterrupt as e: print("\n%s escaped interact()\n" % type(e).__name__) finally: @@ -504,49 +504,49 @@ class TerminalInteractiveShell(InteractiveShell): if hasattr(self, '_eventloop'): self._eventloop.stop() - _inputhook = None - def inputhook(self, context): - if self._inputhook is not None: - self._inputhook(context) + _inputhook = None + def inputhook(self, context): + if self._inputhook is not None: + self._inputhook(context) active_eventloop = None - def enable_gui(self, gui=None): - if gui: + def enable_gui(self, gui=None): + if gui: self.active_eventloop, self._inputhook =\ get_inputhook_name_and_func(gui) - else: + else: self.active_eventloop = self._inputhook = None - # Run !system commands directly, not through pipes, so terminal programs - # work correctly. - system = InteractiveShell.system_raw + # Run !system commands directly, not through pipes, so terminal programs + # work correctly. + system = InteractiveShell.system_raw - def auto_rewrite_input(self, cmd): - """Overridden from the parent class to use fancy rewriting prompt""" - if not self.show_rewritten_input: - return + def auto_rewrite_input(self, cmd): + """Overridden from the parent class to use fancy rewriting prompt""" + if not self.show_rewritten_input: + return - tokens = self.prompts.rewrite_prompt_tokens() - if self.pt_cli: - self.pt_cli.print_tokens(tokens) - print(cmd) + tokens = self.prompts.rewrite_prompt_tokens() + if self.pt_cli: + self.pt_cli.print_tokens(tokens) + print(cmd) else: - prompt = ''.join(s for t, s in tokens) - print(prompt, cmd, sep='') + prompt = ''.join(s for t, s in tokens) + print(prompt, cmd, sep='') - _prompts_before = None - def switch_doctest_mode(self, mode): - """Switch prompts to classic for %doctest_mode""" - if mode: - self._prompts_before = self.prompts - self.prompts = ClassicPrompts(self) - elif self._prompts_before: - self.prompts = self._prompts_before - self._prompts_before = None - self._update_layout() + _prompts_before = None + def switch_doctest_mode(self, mode): + """Switch prompts to classic for %doctest_mode""" + if mode: + self._prompts_before = self.prompts + self.prompts = ClassicPrompts(self) + elif self._prompts_before: + self.prompts = self._prompts_before + self._prompts_before = None + self._update_layout() -InteractiveShellABC.register(TerminalInteractiveShell) +InteractiveShellABC.register(TerminalInteractiveShell) -if __name__ == '__main__': - TerminalInteractiveShell.instance().interact() +if __name__ == '__main__': + TerminalInteractiveShell.instance().interact() diff --git a/contrib/python/ipython/py2/IPython/terminal/ipapp.py b/contrib/python/ipython/py2/IPython/terminal/ipapp.py index a1181c1b0b..6b25aaa3e3 100755 --- a/contrib/python/ipython/py2/IPython/terminal/ipapp.py +++ b/contrib/python/ipython/py2/IPython/terminal/ipapp.py @@ -14,7 +14,7 @@ from __future__ import print_function import logging import os import sys -import warnings +import warnings from traitlets.config.loader import Config from traitlets.config.application import boolean_flag, catch_config_error, Application @@ -32,7 +32,7 @@ from IPython.core.shellapp import ( InteractiveShellApp, shell_flags, shell_aliases ) from IPython.extensions.storemagic import StoreMagics -from .interactiveshell import TerminalInteractiveShell +from .interactiveshell import TerminalInteractiveShell from IPython.paths import get_ipython_dir from traitlets import ( Bool, List, Dict, default, observe, Type @@ -101,11 +101,11 @@ addflag('autoedit-syntax', 'TerminalInteractiveShell.autoedit_syntax', 'Turn on auto editing of files with syntax errors.', 'Turn off auto editing of files with syntax errors.' ) -addflag('simple-prompt', 'TerminalInteractiveShell.simple_prompt', - "Force simple minimal prompt using `raw_input`", - "Use a rich interactive prompt with prompt_toolkit", -) - +addflag('simple-prompt', 'TerminalInteractiveShell.simple_prompt', + "Force simple minimal prompt using `raw_input`", + "Use a rich interactive prompt with prompt_toolkit", +) + addflag('banner', 'TerminalIPythonApp.display_banner', "Display a banner upon starting IPython.", "Don't display a banner upon starting IPython." @@ -123,7 +123,7 @@ addflag('term-title', 'TerminalInteractiveShell.term_title', classic_config = Config() classic_config.InteractiveShell.cache_size = 0 classic_config.PlainTextFormatter.pprint = False -classic_config.TerminalInteractiveShell.prompts_class='IPython.terminal.prompts.ClassicPrompts' +classic_config.TerminalInteractiveShell.prompts_class='IPython.terminal.prompts.ClassicPrompts' classic_config.InteractiveShell.separate_in = '' classic_config.InteractiveShell.separate_out = '' classic_config.InteractiveShell.separate_out2 = '' @@ -192,7 +192,7 @@ class TerminalIPythonApp(BaseIPythonApplication, InteractiveShellApp): help="Class to use to instantiate the TerminalInteractiveShell object. Useful for custom Frontends" ).tag(config=True) - @default('classes') + @default('classes') def _classes_default(self): """This has to be in a method, for TerminalIPythonApp to be available.""" return [ @@ -250,33 +250,33 @@ class TerminalIPythonApp(BaseIPythonApplication, InteractiveShellApp): # *do* autocreate requested profile, but don't create the config file. auto_create=Bool(True) # configurables - quick = Bool(False, + quick = Bool(False, help="""Start IPython quickly by skipping the loading of config files.""" - ).tag(config=True) - @observe('quick') - def _quick_changed(self, change): - if change['new']: + ).tag(config=True) + @observe('quick') + def _quick_changed(self, change): + if change['new']: self.load_config_file = lambda *a, **kw: None - display_banner = Bool(True, + display_banner = Bool(True, help="Whether to display a banner upon starting IPython." - ).tag(config=True) + ).tag(config=True) # if there is code of files to run from the cmd line, don't interact # unless the --i flag (App.force_interact) is true. - force_interact = Bool(False, + force_interact = Bool(False, help="""If a command or file is given via the command-line, e.g. 'ipython foo.py', start an interactive shell after executing the file or command.""" - ).tag(config=True) - @observe('force_interact') - def _force_interact_changed(self, change): - if change['new']: + ).tag(config=True) + @observe('force_interact') + def _force_interact_changed(self, change): + if change['new']: self.interact = True - @observe('file_to_run', 'code_to_run', 'module_to_run') - def _file_to_run_changed(self, change): - new = change['new'] + @observe('file_to_run', 'code_to_run', 'module_to_run') + def _file_to_run_changed(self, change): + new = change['new'] if new: self.something_to_run = True if new and not self.force_interact: @@ -295,7 +295,7 @@ class TerminalIPythonApp(BaseIPythonApplication, InteractiveShellApp): # warn and transform into current syntax argv = argv[:] # copy, don't clobber idx = argv.index('-pylab') - warnings.warn("`-pylab` flag has been deprecated.\n" + warnings.warn("`-pylab` flag has been deprecated.\n" " Use `--matplotlib <backend>` and import pylab manually.") argv[idx] = '--pylab' @@ -328,7 +328,7 @@ class TerminalIPythonApp(BaseIPythonApplication, InteractiveShellApp): # based app, because we call shell.show_banner() by hand below # so the banner shows *before* all extension loading stuff. self.shell = self.interactive_shell_class.instance(parent=self, - profile_dir=self.profile_dir, + profile_dir=self.profile_dir, ipython_dir=self.ipython_dir, user_ns=self.user_ns) self.shell.configurables.append(self) @@ -342,7 +342,7 @@ class TerminalIPythonApp(BaseIPythonApplication, InteractiveShellApp): def _pylab_changed(self, name, old, new): """Replace --pylab='inline' with --pylab='auto'""" if new == 'inline': - warnings.warn("'inline' not available as pylab backend, " + warnings.warn("'inline' not available as pylab backend, " "using 'auto' instead.") self.pylab = 'auto' diff --git a/contrib/python/ipython/py2/IPython/terminal/magics.py b/contrib/python/ipython/py2/IPython/terminal/magics.py index 60f465b0dc..3a844a0397 100644 --- a/contrib/python/ipython/py2/IPython/terminal/magics.py +++ b/contrib/python/ipython/py2/IPython/terminal/magics.py @@ -1,208 +1,208 @@ -"""Extra magics for terminal use.""" - -# Copyright (c) IPython Development Team. -# Distributed under the terms of the Modified BSD License. - -from __future__ import print_function - -from logging import error -import os -import sys - -from IPython.core.error import TryNext, UsageError -from IPython.core.inputsplitter import IPythonInputSplitter -from IPython.core.magic import Magics, magics_class, line_magic -from IPython.lib.clipboard import ClipboardEmpty -from IPython.utils.text import SList, strip_email_quotes -from IPython.utils import py3compat - -def get_pasted_lines(sentinel, l_input=py3compat.input, quiet=False): - """ Yield pasted lines until the user enters the given sentinel value. - """ - if not quiet: - print("Pasting code; enter '%s' alone on the line to stop or use Ctrl-D." \ - % sentinel) - prompt = ":" - else: - prompt = "" - while True: - try: - l = py3compat.str_to_unicode(l_input(prompt)) - if l == sentinel: - return - else: - yield l - except EOFError: - print('<EOF>') - return - - -@magics_class -class TerminalMagics(Magics): - def __init__(self, shell): - super(TerminalMagics, self).__init__(shell) - self.input_splitter = IPythonInputSplitter() - - def store_or_execute(self, block, name): - """ Execute a block, or store it in a variable, per the user's request. - """ - if name: - # If storing it for further editing - self.shell.user_ns[name] = SList(block.splitlines()) - print("Block assigned to '%s'" % name) - else: - b = self.preclean_input(block) - self.shell.user_ns['pasted_block'] = b - self.shell.using_paste_magics = True - try: - self.shell.run_cell(b) - finally: - self.shell.using_paste_magics = False - - def preclean_input(self, block): - lines = block.splitlines() - while lines and not lines[0].strip(): - lines = lines[1:] - return strip_email_quotes('\n'.join(lines)) - - def rerun_pasted(self, name='pasted_block'): - """ Rerun a previously pasted command. - """ - b = self.shell.user_ns.get(name) - - # Sanity checks - if b is None: - raise UsageError('No previous pasted block available') - if not isinstance(b, py3compat.string_types): - raise UsageError( - "Variable 'pasted_block' is not a string, can't execute") - - print("Re-executing '%s...' (%d chars)"% (b.split('\n',1)[0], len(b))) - self.shell.run_cell(b) - - @line_magic - def autoindent(self, parameter_s = ''): +"""Extra magics for terminal use.""" + +# Copyright (c) IPython Development Team. +# Distributed under the terms of the Modified BSD License. + +from __future__ import print_function + +from logging import error +import os +import sys + +from IPython.core.error import TryNext, UsageError +from IPython.core.inputsplitter import IPythonInputSplitter +from IPython.core.magic import Magics, magics_class, line_magic +from IPython.lib.clipboard import ClipboardEmpty +from IPython.utils.text import SList, strip_email_quotes +from IPython.utils import py3compat + +def get_pasted_lines(sentinel, l_input=py3compat.input, quiet=False): + """ Yield pasted lines until the user enters the given sentinel value. + """ + if not quiet: + print("Pasting code; enter '%s' alone on the line to stop or use Ctrl-D." \ + % sentinel) + prompt = ":" + else: + prompt = "" + while True: + try: + l = py3compat.str_to_unicode(l_input(prompt)) + if l == sentinel: + return + else: + yield l + except EOFError: + print('<EOF>') + return + + +@magics_class +class TerminalMagics(Magics): + def __init__(self, shell): + super(TerminalMagics, self).__init__(shell) + self.input_splitter = IPythonInputSplitter() + + def store_or_execute(self, block, name): + """ Execute a block, or store it in a variable, per the user's request. + """ + if name: + # If storing it for further editing + self.shell.user_ns[name] = SList(block.splitlines()) + print("Block assigned to '%s'" % name) + else: + b = self.preclean_input(block) + self.shell.user_ns['pasted_block'] = b + self.shell.using_paste_magics = True + try: + self.shell.run_cell(b) + finally: + self.shell.using_paste_magics = False + + def preclean_input(self, block): + lines = block.splitlines() + while lines and not lines[0].strip(): + lines = lines[1:] + return strip_email_quotes('\n'.join(lines)) + + def rerun_pasted(self, name='pasted_block'): + """ Rerun a previously pasted command. + """ + b = self.shell.user_ns.get(name) + + # Sanity checks + if b is None: + raise UsageError('No previous pasted block available') + if not isinstance(b, py3compat.string_types): + raise UsageError( + "Variable 'pasted_block' is not a string, can't execute") + + print("Re-executing '%s...' (%d chars)"% (b.split('\n',1)[0], len(b))) + self.shell.run_cell(b) + + @line_magic + def autoindent(self, parameter_s = ''): """Toggle autoindent on/off (deprecated)""" print("%autoindent is deprecated since IPython 5: you can now paste " "multiple lines without turning autoindentation off.") - self.shell.set_autoindent() - print("Automatic indentation is:",['OFF','ON'][self.shell.autoindent]) - - @line_magic - def 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. - '%cpaste -q' suppresses any additional output messages. - - 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, 'rqs:', mode='string') - if 'r' in opts: - self.rerun_pasted() - return - - quiet = ('q' in opts) - - sentinel = opts.get('s', u'--') - block = '\n'.join(get_pasted_lines(sentinel, quiet=quiet)) - self.store_or_execute(block, name) - - @line_magic - def 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 - 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: - self.rerun_pasted() - return - try: - block = self.shell.hooks.clipboard_get() - 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 - except ClipboardEmpty: - raise UsageError("The clipboard appears to be empty") - - # 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") - - self.store_or_execute(block, name) - - # Class-level: add a '%cls' magic only on Windows - if sys.platform == 'win32': - @line_magic - def cls(self, s): - """Clear screen. - """ - os.system("cls") + self.shell.set_autoindent() + print("Automatic indentation is:",['OFF','ON'][self.shell.autoindent]) + + @line_magic + def 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. + '%cpaste -q' suppresses any additional output messages. + + 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, 'rqs:', mode='string') + if 'r' in opts: + self.rerun_pasted() + return + + quiet = ('q' in opts) + + sentinel = opts.get('s', u'--') + block = '\n'.join(get_pasted_lines(sentinel, quiet=quiet)) + self.store_or_execute(block, name) + + @line_magic + def 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 + 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: + self.rerun_pasted() + return + try: + block = self.shell.hooks.clipboard_get() + 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 + except ClipboardEmpty: + raise UsageError("The clipboard appears to be empty") + + # 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") + + self.store_or_execute(block, name) + + # Class-level: add a '%cls' magic only on Windows + if sys.platform == 'win32': + @line_magic + def cls(self, s): + """Clear screen. + """ + os.system("cls") diff --git a/contrib/python/ipython/py2/IPython/terminal/prompts.py b/contrib/python/ipython/py2/IPython/terminal/prompts.py index a2203fe417..43c2170503 100644 --- a/contrib/python/ipython/py2/IPython/terminal/prompts.py +++ b/contrib/python/ipython/py2/IPython/terminal/prompts.py @@ -1,80 +1,80 @@ -"""Terminal input and output prompts.""" -from __future__ import print_function - -from pygments.token import Token -import sys - -from IPython.core.displayhook import DisplayHook - -from prompt_toolkit.layout.utils import token_list_width - -class Prompts(object): - def __init__(self, shell): - self.shell = shell - - def in_prompt_tokens(self, cli=None): - return [ - (Token.Prompt, 'In ['), - (Token.PromptNum, str(self.shell.execution_count)), - (Token.Prompt, ']: '), - ] - - def _width(self): - return token_list_width(self.in_prompt_tokens()) - - def continuation_prompt_tokens(self, cli=None, width=None): - if width is None: - width = self._width() - return [ - (Token.Prompt, (' ' * (width - 5)) + '...: '), - ] - - def rewrite_prompt_tokens(self): - width = self._width() - return [ - (Token.Prompt, ('-' * (width - 2)) + '> '), - ] - - def out_prompt_tokens(self): - return [ - (Token.OutPrompt, 'Out['), - (Token.OutPromptNum, str(self.shell.execution_count)), - (Token.OutPrompt, ']: '), - ] - -class ClassicPrompts(Prompts): - def in_prompt_tokens(self, cli=None): - return [ - (Token.Prompt, '>>> '), - ] - - def continuation_prompt_tokens(self, cli=None, width=None): - return [ - (Token.Prompt, '... ') - ] - - def rewrite_prompt_tokens(self): - return [] - - def out_prompt_tokens(self): - return [] - -class RichPromptDisplayHook(DisplayHook): - """Subclass of base display hook using coloured prompt""" - def write_output_prompt(self): - sys.stdout.write(self.shell.separate_out) +"""Terminal input and output prompts.""" +from __future__ import print_function + +from pygments.token import Token +import sys + +from IPython.core.displayhook import DisplayHook + +from prompt_toolkit.layout.utils import token_list_width + +class Prompts(object): + def __init__(self, shell): + self.shell = shell + + def in_prompt_tokens(self, cli=None): + return [ + (Token.Prompt, 'In ['), + (Token.PromptNum, str(self.shell.execution_count)), + (Token.Prompt, ']: '), + ] + + def _width(self): + return token_list_width(self.in_prompt_tokens()) + + def continuation_prompt_tokens(self, cli=None, width=None): + if width is None: + width = self._width() + return [ + (Token.Prompt, (' ' * (width - 5)) + '...: '), + ] + + def rewrite_prompt_tokens(self): + width = self._width() + return [ + (Token.Prompt, ('-' * (width - 2)) + '> '), + ] + + def out_prompt_tokens(self): + return [ + (Token.OutPrompt, 'Out['), + (Token.OutPromptNum, str(self.shell.execution_count)), + (Token.OutPrompt, ']: '), + ] + +class ClassicPrompts(Prompts): + def in_prompt_tokens(self, cli=None): + return [ + (Token.Prompt, '>>> '), + ] + + def continuation_prompt_tokens(self, cli=None, width=None): + return [ + (Token.Prompt, '... ') + ] + + def rewrite_prompt_tokens(self): + return [] + + def out_prompt_tokens(self): + return [] + +class RichPromptDisplayHook(DisplayHook): + """Subclass of base display hook using coloured prompt""" + def write_output_prompt(self): + sys.stdout.write(self.shell.separate_out) # If we're not displaying a prompt, it effectively ends with a newline, # because the output will be left-aligned. self.prompt_end_newline = True - if self.do_full_cache: - tokens = self.shell.prompts.out_prompt_tokens() + if self.do_full_cache: + tokens = self.shell.prompts.out_prompt_tokens() prompt_txt = ''.join(s for t, s in tokens) if prompt_txt and not prompt_txt.endswith('\n'): # Ask for a newline before multiline output self.prompt_end_newline = False - if self.shell.pt_cli: - self.shell.pt_cli.print_tokens(tokens) - else: + if self.shell.pt_cli: + self.shell.pt_cli.print_tokens(tokens) + else: sys.stdout.write(prompt_txt) diff --git a/contrib/python/ipython/py2/IPython/terminal/pt_inputhooks/__init__.py b/contrib/python/ipython/py2/IPython/terminal/pt_inputhooks/__init__.py index 95fdad0b59..3766973e82 100644 --- a/contrib/python/ipython/py2/IPython/terminal/pt_inputhooks/__init__.py +++ b/contrib/python/ipython/py2/IPython/terminal/pt_inputhooks/__init__.py @@ -1,49 +1,49 @@ -import importlib -import os - -aliases = { - 'qt4': 'qt', - 'gtk2': 'gtk', -} - -backends = [ - 'qt', 'qt4', 'qt5', - 'gtk', 'gtk2', 'gtk3', - 'tk', - 'wx', - 'pyglet', 'glut', - 'osx', -] - -registered = {} - -def register(name, inputhook): - """Register the function *inputhook* as an event loop integration.""" - registered[name] = inputhook - -class UnknownBackend(KeyError): - def __init__(self, name): - self.name = name - - def __str__(self): - return ("No event loop integration for {!r}. " - "Supported event loops are: {}").format(self.name, - ', '.join(backends + sorted(registered))) - +import importlib +import os + +aliases = { + 'qt4': 'qt', + 'gtk2': 'gtk', +} + +backends = [ + 'qt', 'qt4', 'qt5', + 'gtk', 'gtk2', 'gtk3', + 'tk', + 'wx', + 'pyglet', 'glut', + 'osx', +] + +registered = {} + +def register(name, inputhook): + """Register the function *inputhook* as an event loop integration.""" + registered[name] = inputhook + +class UnknownBackend(KeyError): + def __init__(self, name): + self.name = name + + def __str__(self): + return ("No event loop integration for {!r}. " + "Supported event loops are: {}").format(self.name, + ', '.join(backends + sorted(registered))) + def get_inputhook_name_and_func(gui): - if gui in registered: + if gui in registered: return gui, registered[gui] - - if gui not in backends: - raise UnknownBackend(gui) - - if gui in aliases: + + if gui not in backends: + raise UnknownBackend(gui) + + if gui in aliases: return get_inputhook_name_and_func(aliases[gui]) - + gui_mod = gui - if gui == 'qt5': - os.environ['QT_API'] = 'pyqt5' + if gui == 'qt5': + os.environ['QT_API'] = 'pyqt5' gui_mod = 'qt' - + mod = importlib.import_module('IPython.terminal.pt_inputhooks.'+gui_mod) return gui, mod.inputhook diff --git a/contrib/python/ipython/py2/IPython/terminal/pt_inputhooks/glut.py b/contrib/python/ipython/py2/IPython/terminal/pt_inputhooks/glut.py index d6b1387649..f336e6830f 100644 --- a/contrib/python/ipython/py2/IPython/terminal/pt_inputhooks/glut.py +++ b/contrib/python/ipython/py2/IPython/terminal/pt_inputhooks/glut.py @@ -1,141 +1,141 @@ -"""GLUT Input hook for interactive use with prompt_toolkit -""" -from __future__ import print_function - - -# GLUT is quite an old library and it is difficult to ensure proper -# integration within IPython since original GLUT does not allow to handle -# events one by one. Instead, it requires for the mainloop to be entered -# and never returned (there is not even a function to exit he -# mainloop). Fortunately, there are alternatives such as freeglut -# (available for linux and windows) and the OSX implementation gives -# access to a glutCheckLoop() function that blocks itself until a new -# event is received. This means we have to setup the idle callback to -# ensure we got at least one event that will unblock the function. -# -# Furthermore, it is not possible to install these handlers without a window -# being first created. We choose to make this window invisible. This means that -# display mode options are set at this level and user won't be able to change -# them later without modifying the code. This should probably be made available -# via IPython options system. - -import sys -import time -import signal -import OpenGL.GLUT as glut -import OpenGL.platform as platform -from timeit import default_timer as clock - -# Frame per second : 60 -# Should probably be an IPython option -glut_fps = 60 - -# Display mode : double buffeed + rgba + depth -# Should probably be an IPython option -glut_display_mode = (glut.GLUT_DOUBLE | - glut.GLUT_RGBA | - glut.GLUT_DEPTH) - -glutMainLoopEvent = None -if sys.platform == 'darwin': - try: - glutCheckLoop = platform.createBaseFunction( - 'glutCheckLoop', dll=platform.GLUT, resultType=None, - argTypes=[], - doc='glutCheckLoop( ) -> None', - argNames=(), - ) - except AttributeError: - raise RuntimeError( - '''Your glut implementation does not allow interactive sessions''' - '''Consider installing freeglut.''') - glutMainLoopEvent = glutCheckLoop -elif glut.HAVE_FREEGLUT: - glutMainLoopEvent = glut.glutMainLoopEvent -else: - raise RuntimeError( - '''Your glut implementation does not allow interactive sessions. ''' - '''Consider installing freeglut.''') - - -def glut_display(): - # Dummy display function - pass - -def glut_idle(): - # Dummy idle function - pass - -def glut_close(): - # Close function only hides the current window - glut.glutHideWindow() - glutMainLoopEvent() - -def glut_int_handler(signum, frame): - # Catch sigint and print the defaultipyt message - signal.signal(signal.SIGINT, signal.default_int_handler) - print('\nKeyboardInterrupt') - # Need to reprint the prompt at this stage - -# Initialisation code -glut.glutInit( sys.argv ) -glut.glutInitDisplayMode( glut_display_mode ) -# This is specific to freeglut -if bool(glut.glutSetOption): - glut.glutSetOption( glut.GLUT_ACTION_ON_WINDOW_CLOSE, - glut.GLUT_ACTION_GLUTMAINLOOP_RETURNS ) -glut.glutCreateWindow( b'ipython' ) -glut.glutReshapeWindow( 1, 1 ) -glut.glutHideWindow( ) -glut.glutWMCloseFunc( glut_close ) -glut.glutDisplayFunc( glut_display ) -glut.glutIdleFunc( glut_idle ) - - -def inputhook(context): - """Run the pyglet event loop by processing pending events only. - - This keeps processing pending events until stdin is ready. After - processing all pending events, a call to time.sleep is inserted. This is - needed, otherwise, CPU usage is at 100%. This sleep time should be tuned - though for best performance. - """ - # We need to protect against a user pressing Control-C when IPython is - # idle and this is running. We trap KeyboardInterrupt and pass. - - signal.signal(signal.SIGINT, glut_int_handler) - - try: - t = clock() - - # Make sure the default window is set after a window has been closed - if glut.glutGetWindow() == 0: - glut.glutSetWindow( 1 ) - glutMainLoopEvent() - return 0 - - while not context.input_is_ready(): - glutMainLoopEvent() - # We need to sleep at this point to keep the idle CPU load - # low. However, if sleep to long, GUI response is poor. As - # a compromise, we watch how often GUI events are being processed - # and switch between a short and long sleep time. Here are some - # stats useful in helping to tune this. - # time CPU load - # 0.001 13% - # 0.005 3% - # 0.01 1.5% - # 0.05 0.5% - used_time = clock() - t - if used_time > 10.0: - # print 'Sleep for 1 s' # dbg - time.sleep(1.0) - elif used_time > 0.1: - # Few GUI events coming in, so we can sleep longer - # print 'Sleep for 0.05 s' # dbg - time.sleep(0.05) - else: - # Many GUI events coming in, so sleep only very little - time.sleep(0.001) - except KeyboardInterrupt: - pass +"""GLUT Input hook for interactive use with prompt_toolkit +""" +from __future__ import print_function + + +# GLUT is quite an old library and it is difficult to ensure proper +# integration within IPython since original GLUT does not allow to handle +# events one by one. Instead, it requires for the mainloop to be entered +# and never returned (there is not even a function to exit he +# mainloop). Fortunately, there are alternatives such as freeglut +# (available for linux and windows) and the OSX implementation gives +# access to a glutCheckLoop() function that blocks itself until a new +# event is received. This means we have to setup the idle callback to +# ensure we got at least one event that will unblock the function. +# +# Furthermore, it is not possible to install these handlers without a window +# being first created. We choose to make this window invisible. This means that +# display mode options are set at this level and user won't be able to change +# them later without modifying the code. This should probably be made available +# via IPython options system. + +import sys +import time +import signal +import OpenGL.GLUT as glut +import OpenGL.platform as platform +from timeit import default_timer as clock + +# Frame per second : 60 +# Should probably be an IPython option +glut_fps = 60 + +# Display mode : double buffeed + rgba + depth +# Should probably be an IPython option +glut_display_mode = (glut.GLUT_DOUBLE | + glut.GLUT_RGBA | + glut.GLUT_DEPTH) + +glutMainLoopEvent = None +if sys.platform == 'darwin': + try: + glutCheckLoop = platform.createBaseFunction( + 'glutCheckLoop', dll=platform.GLUT, resultType=None, + argTypes=[], + doc='glutCheckLoop( ) -> None', + argNames=(), + ) + except AttributeError: + raise RuntimeError( + '''Your glut implementation does not allow interactive sessions''' + '''Consider installing freeglut.''') + glutMainLoopEvent = glutCheckLoop +elif glut.HAVE_FREEGLUT: + glutMainLoopEvent = glut.glutMainLoopEvent +else: + raise RuntimeError( + '''Your glut implementation does not allow interactive sessions. ''' + '''Consider installing freeglut.''') + + +def glut_display(): + # Dummy display function + pass + +def glut_idle(): + # Dummy idle function + pass + +def glut_close(): + # Close function only hides the current window + glut.glutHideWindow() + glutMainLoopEvent() + +def glut_int_handler(signum, frame): + # Catch sigint and print the defaultipyt message + signal.signal(signal.SIGINT, signal.default_int_handler) + print('\nKeyboardInterrupt') + # Need to reprint the prompt at this stage + +# Initialisation code +glut.glutInit( sys.argv ) +glut.glutInitDisplayMode( glut_display_mode ) +# This is specific to freeglut +if bool(glut.glutSetOption): + glut.glutSetOption( glut.GLUT_ACTION_ON_WINDOW_CLOSE, + glut.GLUT_ACTION_GLUTMAINLOOP_RETURNS ) +glut.glutCreateWindow( b'ipython' ) +glut.glutReshapeWindow( 1, 1 ) +glut.glutHideWindow( ) +glut.glutWMCloseFunc( glut_close ) +glut.glutDisplayFunc( glut_display ) +glut.glutIdleFunc( glut_idle ) + + +def inputhook(context): + """Run the pyglet event loop by processing pending events only. + + This keeps processing pending events until stdin is ready. After + processing all pending events, a call to time.sleep is inserted. This is + needed, otherwise, CPU usage is at 100%. This sleep time should be tuned + though for best performance. + """ + # We need to protect against a user pressing Control-C when IPython is + # idle and this is running. We trap KeyboardInterrupt and pass. + + signal.signal(signal.SIGINT, glut_int_handler) + + try: + t = clock() + + # Make sure the default window is set after a window has been closed + if glut.glutGetWindow() == 0: + glut.glutSetWindow( 1 ) + glutMainLoopEvent() + return 0 + + while not context.input_is_ready(): + glutMainLoopEvent() + # We need to sleep at this point to keep the idle CPU load + # low. However, if sleep to long, GUI response is poor. As + # a compromise, we watch how often GUI events are being processed + # and switch between a short and long sleep time. Here are some + # stats useful in helping to tune this. + # time CPU load + # 0.001 13% + # 0.005 3% + # 0.01 1.5% + # 0.05 0.5% + used_time = clock() - t + if used_time > 10.0: + # print 'Sleep for 1 s' # dbg + time.sleep(1.0) + elif used_time > 0.1: + # Few GUI events coming in, so we can sleep longer + # print 'Sleep for 0.05 s' # dbg + time.sleep(0.05) + else: + # Many GUI events coming in, so sleep only very little + time.sleep(0.001) + except KeyboardInterrupt: + pass diff --git a/contrib/python/ipython/py2/IPython/terminal/pt_inputhooks/gtk.py b/contrib/python/ipython/py2/IPython/terminal/pt_inputhooks/gtk.py index ac7529ca00..8f27e12c46 100644 --- a/contrib/python/ipython/py2/IPython/terminal/pt_inputhooks/gtk.py +++ b/contrib/python/ipython/py2/IPython/terminal/pt_inputhooks/gtk.py @@ -1,59 +1,59 @@ -# Code borrowed from python-prompt-toolkit examples -# https://github.com/jonathanslenders/python-prompt-toolkit/blob/77cdcfbc7f4b4c34a9d2f9a34d422d7152f16209/examples/inputhook.py - -# Copyright (c) 2014, Jonathan Slenders -# All rights reserved. -# -# Redistribution and use in source and binary forms, with or without modification, -# are permitted provided that the following conditions are met: -# -# * Redistributions of source code must retain the above copyright notice, this -# list of conditions and the following disclaimer. -# -# * Redistributions in binary form must reproduce the above copyright notice, this -# list of conditions and the following disclaimer in the documentation and/or -# other materials provided with the distribution. -# -# * Neither the name of the {organization} nor the names of its -# contributors may be used to endorse or promote products derived from -# this software without specific prior written permission. -# -# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND -# ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED -# WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE -# DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR -# ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES -# (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; -# LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON -# ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS -# SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - -""" -PyGTK input hook for prompt_toolkit. - -Listens on the pipe prompt_toolkit sets up for a notification that it should -return control to the terminal event loop. -""" -from __future__ import absolute_import - -import gtk, gobject - -# Enable threading in GTK. (Otherwise, GTK will keep the GIL.) -gtk.gdk.threads_init() - -def inputhook(context): - """ - When the eventloop of prompt-toolkit is idle, call this inputhook. - - This will run the GTK main loop until the file descriptor - `context.fileno()` becomes ready. - - :param context: An `InputHookContext` instance. - """ - def _main_quit(*a, **kw): - gtk.main_quit() - return False - - gobject.io_add_watch(context.fileno(), gobject.IO_IN, _main_quit) - gtk.main() +# Code borrowed from python-prompt-toolkit examples +# https://github.com/jonathanslenders/python-prompt-toolkit/blob/77cdcfbc7f4b4c34a9d2f9a34d422d7152f16209/examples/inputhook.py + +# Copyright (c) 2014, Jonathan Slenders +# All rights reserved. +# +# Redistribution and use in source and binary forms, with or without modification, +# are permitted provided that the following conditions are met: +# +# * Redistributions of source code must retain the above copyright notice, this +# list of conditions and the following disclaimer. +# +# * Redistributions in binary form must reproduce the above copyright notice, this +# list of conditions and the following disclaimer in the documentation and/or +# other materials provided with the distribution. +# +# * Neither the name of the {organization} nor the names of its +# contributors may be used to endorse or promote products derived from +# this software without specific prior written permission. +# +# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND +# ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +# WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +# DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR +# ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES +# (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; +# LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON +# ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS +# SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +""" +PyGTK input hook for prompt_toolkit. + +Listens on the pipe prompt_toolkit sets up for a notification that it should +return control to the terminal event loop. +""" +from __future__ import absolute_import + +import gtk, gobject + +# Enable threading in GTK. (Otherwise, GTK will keep the GIL.) +gtk.gdk.threads_init() + +def inputhook(context): + """ + When the eventloop of prompt-toolkit is idle, call this inputhook. + + This will run the GTK main loop until the file descriptor + `context.fileno()` becomes ready. + + :param context: An `InputHookContext` instance. + """ + def _main_quit(*a, **kw): + gtk.main_quit() + return False + + gobject.io_add_watch(context.fileno(), gobject.IO_IN, _main_quit) + gtk.main() diff --git a/contrib/python/ipython/py2/IPython/terminal/pt_inputhooks/gtk3.py b/contrib/python/ipython/py2/IPython/terminal/pt_inputhooks/gtk3.py index 40d6673359..5c6c545457 100644 --- a/contrib/python/ipython/py2/IPython/terminal/pt_inputhooks/gtk3.py +++ b/contrib/python/ipython/py2/IPython/terminal/pt_inputhooks/gtk3.py @@ -1,12 +1,12 @@ -"""prompt_toolkit input hook for GTK 3 -""" - -from gi.repository import Gtk, GLib - -def _main_quit(*args, **kwargs): - Gtk.main_quit() - return False - -def inputhook(context): - GLib.io_add_watch(context.fileno(), GLib.IO_IN, _main_quit) - Gtk.main() +"""prompt_toolkit input hook for GTK 3 +""" + +from gi.repository import Gtk, GLib + +def _main_quit(*args, **kwargs): + Gtk.main_quit() + return False + +def inputhook(context): + GLib.io_add_watch(context.fileno(), GLib.IO_IN, _main_quit) + Gtk.main() diff --git a/contrib/python/ipython/py2/IPython/terminal/pt_inputhooks/osx.py b/contrib/python/ipython/py2/IPython/terminal/pt_inputhooks/osx.py index b916ee0540..53f4e3838b 100644 --- a/contrib/python/ipython/py2/IPython/terminal/pt_inputhooks/osx.py +++ b/contrib/python/ipython/py2/IPython/terminal/pt_inputhooks/osx.py @@ -1,137 +1,137 @@ -"""Inputhook for OS X - -Calls NSApp / CoreFoundation APIs via ctypes. -""" - -# obj-c boilerplate from appnope, used under BSD 2-clause - -import ctypes -import ctypes.util -from threading import Event - -objc = ctypes.cdll.LoadLibrary(ctypes.util.find_library('objc')) - -void_p = ctypes.c_void_p - -objc.objc_getClass.restype = void_p -objc.sel_registerName.restype = void_p -objc.objc_msgSend.restype = void_p -objc.objc_msgSend.argtypes = [void_p, void_p] - -msg = objc.objc_msgSend - -def _utf8(s): - """ensure utf8 bytes""" - if not isinstance(s, bytes): - s = s.encode('utf8') - return s - -def n(name): - """create a selector name (for ObjC methods)""" - return objc.sel_registerName(_utf8(name)) - -def C(classname): - """get an ObjC Class by name""" - return objc.objc_getClass(_utf8(classname)) - -# end obj-c boilerplate from appnope - -# CoreFoundation C-API calls we will use: -CoreFoundation = ctypes.cdll.LoadLibrary(ctypes.util.find_library('CoreFoundation')) - -CFFileDescriptorCreate = CoreFoundation.CFFileDescriptorCreate -CFFileDescriptorCreate.restype = void_p -CFFileDescriptorCreate.argtypes = [void_p, ctypes.c_int, ctypes.c_bool, void_p] - -CFFileDescriptorGetNativeDescriptor = CoreFoundation.CFFileDescriptorGetNativeDescriptor -CFFileDescriptorGetNativeDescriptor.restype = ctypes.c_int -CFFileDescriptorGetNativeDescriptor.argtypes = [void_p] - -CFFileDescriptorEnableCallBacks = CoreFoundation.CFFileDescriptorEnableCallBacks -CFFileDescriptorEnableCallBacks.restype = None -CFFileDescriptorEnableCallBacks.argtypes = [void_p, ctypes.c_ulong] - -CFFileDescriptorCreateRunLoopSource = CoreFoundation.CFFileDescriptorCreateRunLoopSource -CFFileDescriptorCreateRunLoopSource.restype = void_p -CFFileDescriptorCreateRunLoopSource.argtypes = [void_p, void_p, void_p] - -CFRunLoopGetCurrent = CoreFoundation.CFRunLoopGetCurrent -CFRunLoopGetCurrent.restype = void_p - -CFRunLoopAddSource = CoreFoundation.CFRunLoopAddSource -CFRunLoopAddSource.restype = None -CFRunLoopAddSource.argtypes = [void_p, void_p, void_p] - -CFRelease = CoreFoundation.CFRelease -CFRelease.restype = None -CFRelease.argtypes = [void_p] - -CFFileDescriptorInvalidate = CoreFoundation.CFFileDescriptorInvalidate -CFFileDescriptorInvalidate.restype = None -CFFileDescriptorInvalidate.argtypes = [void_p] - -# From CFFileDescriptor.h -kCFFileDescriptorReadCallBack = 1 -kCFRunLoopCommonModes = void_p.in_dll(CoreFoundation, 'kCFRunLoopCommonModes') - - -def _NSApp(): - """Return the global NSApplication instance (NSApp)""" - return msg(C('NSApplication'), n('sharedApplication')) - - -def _wake(NSApp): - """Wake the Application""" - event = msg(C('NSEvent'), - n('otherEventWithType:location:modifierFlags:' - 'timestamp:windowNumber:context:subtype:data1:data2:'), - 15, # Type - 0, # location - 0, # flags - 0, # timestamp - 0, # window - None, # context - 0, # subtype - 0, # data1 - 0, # data2 - ) - msg(NSApp, n('postEvent:atStart:'), void_p(event), True) - - -_triggered = Event() - -def _input_callback(fdref, flags, info): - """Callback to fire when there's input to be read""" - _triggered.set() - CFFileDescriptorInvalidate(fdref) - CFRelease(fdref) - NSApp = _NSApp() - msg(NSApp, n('stop:'), NSApp) - _wake(NSApp) - -_c_callback_func_type = ctypes.CFUNCTYPE(None, void_p, void_p, void_p) -_c_input_callback = _c_callback_func_type(_input_callback) - - -def _stop_on_read(fd): - """Register callback to stop eventloop when there's data on fd""" - _triggered.clear() - fdref = CFFileDescriptorCreate(None, fd, False, _c_input_callback, None) - CFFileDescriptorEnableCallBacks(fdref, kCFFileDescriptorReadCallBack) - source = CFFileDescriptorCreateRunLoopSource(None, fdref, 0) - loop = CFRunLoopGetCurrent() - CFRunLoopAddSource(loop, source, kCFRunLoopCommonModes) - CFRelease(source) - - -def inputhook(context): - """Inputhook for Cocoa (NSApp)""" - NSApp = _NSApp() - _stop_on_read(context.fileno()) - msg(NSApp, n('run')) - if not _triggered.is_set(): - # app closed without firing callback, - # probably due to last window being closed. - # Run the loop manually in this case, - # since there may be events still to process (#9734) - CoreFoundation.CFRunLoopRun() +"""Inputhook for OS X + +Calls NSApp / CoreFoundation APIs via ctypes. +""" + +# obj-c boilerplate from appnope, used under BSD 2-clause + +import ctypes +import ctypes.util +from threading import Event + +objc = ctypes.cdll.LoadLibrary(ctypes.util.find_library('objc')) + +void_p = ctypes.c_void_p + +objc.objc_getClass.restype = void_p +objc.sel_registerName.restype = void_p +objc.objc_msgSend.restype = void_p +objc.objc_msgSend.argtypes = [void_p, void_p] + +msg = objc.objc_msgSend + +def _utf8(s): + """ensure utf8 bytes""" + if not isinstance(s, bytes): + s = s.encode('utf8') + return s + +def n(name): + """create a selector name (for ObjC methods)""" + return objc.sel_registerName(_utf8(name)) + +def C(classname): + """get an ObjC Class by name""" + return objc.objc_getClass(_utf8(classname)) + +# end obj-c boilerplate from appnope + +# CoreFoundation C-API calls we will use: +CoreFoundation = ctypes.cdll.LoadLibrary(ctypes.util.find_library('CoreFoundation')) + +CFFileDescriptorCreate = CoreFoundation.CFFileDescriptorCreate +CFFileDescriptorCreate.restype = void_p +CFFileDescriptorCreate.argtypes = [void_p, ctypes.c_int, ctypes.c_bool, void_p] + +CFFileDescriptorGetNativeDescriptor = CoreFoundation.CFFileDescriptorGetNativeDescriptor +CFFileDescriptorGetNativeDescriptor.restype = ctypes.c_int +CFFileDescriptorGetNativeDescriptor.argtypes = [void_p] + +CFFileDescriptorEnableCallBacks = CoreFoundation.CFFileDescriptorEnableCallBacks +CFFileDescriptorEnableCallBacks.restype = None +CFFileDescriptorEnableCallBacks.argtypes = [void_p, ctypes.c_ulong] + +CFFileDescriptorCreateRunLoopSource = CoreFoundation.CFFileDescriptorCreateRunLoopSource +CFFileDescriptorCreateRunLoopSource.restype = void_p +CFFileDescriptorCreateRunLoopSource.argtypes = [void_p, void_p, void_p] + +CFRunLoopGetCurrent = CoreFoundation.CFRunLoopGetCurrent +CFRunLoopGetCurrent.restype = void_p + +CFRunLoopAddSource = CoreFoundation.CFRunLoopAddSource +CFRunLoopAddSource.restype = None +CFRunLoopAddSource.argtypes = [void_p, void_p, void_p] + +CFRelease = CoreFoundation.CFRelease +CFRelease.restype = None +CFRelease.argtypes = [void_p] + +CFFileDescriptorInvalidate = CoreFoundation.CFFileDescriptorInvalidate +CFFileDescriptorInvalidate.restype = None +CFFileDescriptorInvalidate.argtypes = [void_p] + +# From CFFileDescriptor.h +kCFFileDescriptorReadCallBack = 1 +kCFRunLoopCommonModes = void_p.in_dll(CoreFoundation, 'kCFRunLoopCommonModes') + + +def _NSApp(): + """Return the global NSApplication instance (NSApp)""" + return msg(C('NSApplication'), n('sharedApplication')) + + +def _wake(NSApp): + """Wake the Application""" + event = msg(C('NSEvent'), + n('otherEventWithType:location:modifierFlags:' + 'timestamp:windowNumber:context:subtype:data1:data2:'), + 15, # Type + 0, # location + 0, # flags + 0, # timestamp + 0, # window + None, # context + 0, # subtype + 0, # data1 + 0, # data2 + ) + msg(NSApp, n('postEvent:atStart:'), void_p(event), True) + + +_triggered = Event() + +def _input_callback(fdref, flags, info): + """Callback to fire when there's input to be read""" + _triggered.set() + CFFileDescriptorInvalidate(fdref) + CFRelease(fdref) + NSApp = _NSApp() + msg(NSApp, n('stop:'), NSApp) + _wake(NSApp) + +_c_callback_func_type = ctypes.CFUNCTYPE(None, void_p, void_p, void_p) +_c_input_callback = _c_callback_func_type(_input_callback) + + +def _stop_on_read(fd): + """Register callback to stop eventloop when there's data on fd""" + _triggered.clear() + fdref = CFFileDescriptorCreate(None, fd, False, _c_input_callback, None) + CFFileDescriptorEnableCallBacks(fdref, kCFFileDescriptorReadCallBack) + source = CFFileDescriptorCreateRunLoopSource(None, fdref, 0) + loop = CFRunLoopGetCurrent() + CFRunLoopAddSource(loop, source, kCFRunLoopCommonModes) + CFRelease(source) + + +def inputhook(context): + """Inputhook for Cocoa (NSApp)""" + NSApp = _NSApp() + _stop_on_read(context.fileno()) + msg(NSApp, n('run')) + if not _triggered.is_set(): + # app closed without firing callback, + # probably due to last window being closed. + # Run the loop manually in this case, + # since there may be events still to process (#9734) + CoreFoundation.CFRunLoopRun() diff --git a/contrib/python/ipython/py2/IPython/terminal/pt_inputhooks/pyglet.py b/contrib/python/ipython/py2/IPython/terminal/pt_inputhooks/pyglet.py index 4fbf790b57..1c5ec44250 100644 --- a/contrib/python/ipython/py2/IPython/terminal/pt_inputhooks/pyglet.py +++ b/contrib/python/ipython/py2/IPython/terminal/pt_inputhooks/pyglet.py @@ -1,68 +1,68 @@ -"""Enable pyglet to be used interacively with prompt_toolkit -""" -from __future__ import absolute_import - -import os -import sys -import time -from timeit import default_timer as clock -import pyglet - -# On linux only, window.flip() has a bug that causes an AttributeError on -# window close. For details, see: -# http://groups.google.com/group/pyglet-users/browse_thread/thread/47c1aab9aa4a3d23/c22f9e819826799e?#c22f9e819826799e - -if sys.platform.startswith('linux'): - def flip(window): - try: - window.flip() - except AttributeError: - pass -else: - def flip(window): - window.flip() - - -def inputhook(context): - """Run the pyglet event loop by processing pending events only. - - This keeps processing pending events until stdin is ready. After - processing all pending events, a call to time.sleep is inserted. This is - needed, otherwise, CPU usage is at 100%. This sleep time should be tuned - though for best performance. - """ - # We need to protect against a user pressing Control-C when IPython is - # idle and this is running. We trap KeyboardInterrupt and pass. - try: - t = clock() - while not context.input_is_ready(): - pyglet.clock.tick() - for window in pyglet.app.windows: - window.switch_to() - window.dispatch_events() - window.dispatch_event('on_draw') - flip(window) - - # We need to sleep at this point to keep the idle CPU load - # low. However, if sleep to long, GUI response is poor. As - # a compromise, we watch how often GUI events are being processed - # and switch between a short and long sleep time. Here are some - # stats useful in helping to tune this. - # time CPU load - # 0.001 13% - # 0.005 3% - # 0.01 1.5% - # 0.05 0.5% - used_time = clock() - t - if used_time > 10.0: - # print 'Sleep for 1 s' # dbg - time.sleep(1.0) - elif used_time > 0.1: - # Few GUI events coming in, so we can sleep longer - # print 'Sleep for 0.05 s' # dbg - time.sleep(0.05) - else: - # Many GUI events coming in, so sleep only very little - time.sleep(0.001) - except KeyboardInterrupt: - pass +"""Enable pyglet to be used interacively with prompt_toolkit +""" +from __future__ import absolute_import + +import os +import sys +import time +from timeit import default_timer as clock +import pyglet + +# On linux only, window.flip() has a bug that causes an AttributeError on +# window close. For details, see: +# http://groups.google.com/group/pyglet-users/browse_thread/thread/47c1aab9aa4a3d23/c22f9e819826799e?#c22f9e819826799e + +if sys.platform.startswith('linux'): + def flip(window): + try: + window.flip() + except AttributeError: + pass +else: + def flip(window): + window.flip() + + +def inputhook(context): + """Run the pyglet event loop by processing pending events only. + + This keeps processing pending events until stdin is ready. After + processing all pending events, a call to time.sleep is inserted. This is + needed, otherwise, CPU usage is at 100%. This sleep time should be tuned + though for best performance. + """ + # We need to protect against a user pressing Control-C when IPython is + # idle and this is running. We trap KeyboardInterrupt and pass. + try: + t = clock() + while not context.input_is_ready(): + pyglet.clock.tick() + for window in pyglet.app.windows: + window.switch_to() + window.dispatch_events() + window.dispatch_event('on_draw') + flip(window) + + # We need to sleep at this point to keep the idle CPU load + # low. However, if sleep to long, GUI response is poor. As + # a compromise, we watch how often GUI events are being processed + # and switch between a short and long sleep time. Here are some + # stats useful in helping to tune this. + # time CPU load + # 0.001 13% + # 0.005 3% + # 0.01 1.5% + # 0.05 0.5% + used_time = clock() - t + if used_time > 10.0: + # print 'Sleep for 1 s' # dbg + time.sleep(1.0) + elif used_time > 0.1: + # Few GUI events coming in, so we can sleep longer + # print 'Sleep for 0.05 s' # dbg + time.sleep(0.05) + else: + # Many GUI events coming in, so sleep only very little + time.sleep(0.001) + except KeyboardInterrupt: + pass diff --git a/contrib/python/ipython/py2/IPython/terminal/pt_inputhooks/qt.py b/contrib/python/ipython/py2/IPython/terminal/pt_inputhooks/qt.py index 5667cd8478..7395ac39eb 100644 --- a/contrib/python/ipython/py2/IPython/terminal/pt_inputhooks/qt.py +++ b/contrib/python/ipython/py2/IPython/terminal/pt_inputhooks/qt.py @@ -1,16 +1,16 @@ -import sys +import sys import os -from IPython.external.qt_for_kernel import QtCore, QtGui - -# If we create a QApplication, keep a reference to it so that it doesn't get -# garbage collected. -_appref = None +from IPython.external.qt_for_kernel import QtCore, QtGui + +# If we create a QApplication, keep a reference to it so that it doesn't get +# garbage collected. +_appref = None _already_warned = False - -def inputhook(context): - global _appref - app = QtCore.QCoreApplication.instance() - if not app: + +def inputhook(context): + global _appref + app = QtCore.QCoreApplication.instance() + if not app: if sys.platform == 'linux': if not os.environ.get('DISPLAY') \ and not os.environ.get('WAYLAND_DISPLAY'): @@ -24,26 +24,26 @@ def inputhook(context): 'variable. Deactivate Qt5 code.' ) return - _appref = app = QtGui.QApplication([" "]) - event_loop = QtCore.QEventLoop(app) - - if sys.platform == 'win32': - # The QSocketNotifier method doesn't appear to work on Windows. - # Use polling instead. - timer = QtCore.QTimer() - timer.timeout.connect(event_loop.quit) - while not context.input_is_ready(): - timer.start(50) # 50 ms - event_loop.exec_() - timer.stop() - else: - # On POSIX platforms, we can use a file descriptor to quit the event - # loop when there is input ready to read. + _appref = app = QtGui.QApplication([" "]) + event_loop = QtCore.QEventLoop(app) + + if sys.platform == 'win32': + # The QSocketNotifier method doesn't appear to work on Windows. + # Use polling instead. + timer = QtCore.QTimer() + timer.timeout.connect(event_loop.quit) + while not context.input_is_ready(): + timer.start(50) # 50 ms + event_loop.exec_() + timer.stop() + else: + # On POSIX platforms, we can use a file descriptor to quit the event + # loop when there is input ready to read. notifier = QtCore.QSocketNotifier(context.fileno(), QtCore.QSocketNotifier.Read) # connect the callback we care about before we turn it on notifier.activated.connect(event_loop.exit) - notifier.setEnabled(True) + notifier.setEnabled(True) # only start the event loop we are not already flipped if not context.input_is_ready(): event_loop.exec_() diff --git a/contrib/python/ipython/py2/IPython/terminal/pt_inputhooks/tk.py b/contrib/python/ipython/py2/IPython/terminal/pt_inputhooks/tk.py index 7d13001a65..db205b0d2c 100644 --- a/contrib/python/ipython/py2/IPython/terminal/pt_inputhooks/tk.py +++ b/contrib/python/ipython/py2/IPython/terminal/pt_inputhooks/tk.py @@ -1,95 +1,95 @@ -# Code borrowed from ptpython -# https://github.com/jonathanslenders/ptpython/blob/86b71a89626114b18898a0af463978bdb32eeb70/ptpython/eventloop.py - -# Copyright (c) 2015, Jonathan Slenders -# All rights reserved. -# -# Redistribution and use in source and binary forms, with or without modification, -# are permitted provided that the following conditions are met: -# -# * Redistributions of source code must retain the above copyright notice, this -# list of conditions and the following disclaimer. -# -# * Redistributions in binary form must reproduce the above copyright notice, this -# list of conditions and the following disclaimer in the documentation and/or -# other materials provided with the distribution. -# -# * Neither the name of the {organization} nor the names of its -# contributors may be used to endorse or promote products derived from -# this software without specific prior written permission. -# -# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND -# ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED -# WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE -# DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR -# ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES -# (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; -# LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON -# ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS -# SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - -""" -Wrapper around the eventloop that gives some time to the Tkinter GUI to process -events when it's loaded and while we are waiting for input at the REPL. This -way we don't block the UI of for instance ``turtle`` and other Tk libraries. - -(Normally Tkinter registeres it's callbacks in ``PyOS_InputHook`` to integrate -in readline. ``prompt-toolkit`` doesn't understand that input hook, but this -will fix it for Tk.) -""" -import time - -from IPython.utils.py3compat import PY3 - -import _tkinter -if PY3: - import tkinter -else: - import Tkinter as tkinter # Python 2 - -def inputhook(inputhook_context): - """ - Inputhook for Tk. - Run the Tk eventloop until prompt-toolkit needs to process the next input. - """ - # Get the current TK application. - root = tkinter._default_root - - def wait_using_filehandler(): - """ - Run the TK eventloop until the file handler that we got from the - inputhook becomes readable. - """ - # Add a handler that sets the stop flag when `prompt-toolkit` has input - # to process. - stop = [False] - def done(*a): - stop[0] = True - - root.createfilehandler(inputhook_context.fileno(), _tkinter.READABLE, done) - - # Run the TK event loop as long as we don't receive input. - while root.dooneevent(_tkinter.ALL_EVENTS): - if stop[0]: - break - - root.deletefilehandler(inputhook_context.fileno()) - - def wait_using_polling(): - """ - Windows TK doesn't support 'createfilehandler'. - So, run the TK eventloop and poll until input is ready. - """ - while not inputhook_context.input_is_ready(): - while root.dooneevent(_tkinter.ALL_EVENTS | _tkinter.DONT_WAIT): - pass - # Sleep to make the CPU idle, but not too long, so that the UI - # stays responsive. - time.sleep(.01) - - if root is not None: - if hasattr(root, 'createfilehandler'): - wait_using_filehandler() - else: - wait_using_polling() +# Code borrowed from ptpython +# https://github.com/jonathanslenders/ptpython/blob/86b71a89626114b18898a0af463978bdb32eeb70/ptpython/eventloop.py + +# Copyright (c) 2015, Jonathan Slenders +# All rights reserved. +# +# Redistribution and use in source and binary forms, with or without modification, +# are permitted provided that the following conditions are met: +# +# * Redistributions of source code must retain the above copyright notice, this +# list of conditions and the following disclaimer. +# +# * Redistributions in binary form must reproduce the above copyright notice, this +# list of conditions and the following disclaimer in the documentation and/or +# other materials provided with the distribution. +# +# * Neither the name of the {organization} nor the names of its +# contributors may be used to endorse or promote products derived from +# this software without specific prior written permission. +# +# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND +# ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +# WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +# DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR +# ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES +# (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; +# LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON +# ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS +# SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +""" +Wrapper around the eventloop that gives some time to the Tkinter GUI to process +events when it's loaded and while we are waiting for input at the REPL. This +way we don't block the UI of for instance ``turtle`` and other Tk libraries. + +(Normally Tkinter registeres it's callbacks in ``PyOS_InputHook`` to integrate +in readline. ``prompt-toolkit`` doesn't understand that input hook, but this +will fix it for Tk.) +""" +import time + +from IPython.utils.py3compat import PY3 + +import _tkinter +if PY3: + import tkinter +else: + import Tkinter as tkinter # Python 2 + +def inputhook(inputhook_context): + """ + Inputhook for Tk. + Run the Tk eventloop until prompt-toolkit needs to process the next input. + """ + # Get the current TK application. + root = tkinter._default_root + + def wait_using_filehandler(): + """ + Run the TK eventloop until the file handler that we got from the + inputhook becomes readable. + """ + # Add a handler that sets the stop flag when `prompt-toolkit` has input + # to process. + stop = [False] + def done(*a): + stop[0] = True + + root.createfilehandler(inputhook_context.fileno(), _tkinter.READABLE, done) + + # Run the TK event loop as long as we don't receive input. + while root.dooneevent(_tkinter.ALL_EVENTS): + if stop[0]: + break + + root.deletefilehandler(inputhook_context.fileno()) + + def wait_using_polling(): + """ + Windows TK doesn't support 'createfilehandler'. + So, run the TK eventloop and poll until input is ready. + """ + while not inputhook_context.input_is_ready(): + while root.dooneevent(_tkinter.ALL_EVENTS | _tkinter.DONT_WAIT): + pass + # Sleep to make the CPU idle, but not too long, so that the UI + # stays responsive. + time.sleep(.01) + + if root is not None: + if hasattr(root, 'createfilehandler'): + wait_using_filehandler() + else: + wait_using_polling() diff --git a/contrib/python/ipython/py2/IPython/terminal/pt_inputhooks/wx.py b/contrib/python/ipython/py2/IPython/terminal/pt_inputhooks/wx.py index 6dde092500..4371b21cb4 100644 --- a/contrib/python/ipython/py2/IPython/terminal/pt_inputhooks/wx.py +++ b/contrib/python/ipython/py2/IPython/terminal/pt_inputhooks/wx.py @@ -1,148 +1,148 @@ -"""Enable wxPython to be used interacively in prompt_toolkit -""" -from __future__ import absolute_import - -import sys -import signal -import time -from timeit import default_timer as clock -import wx - - -def inputhook_wx1(context): - """Run the wx event loop by processing pending events only. - - This approach seems to work, but its performance is not great as it - relies on having PyOS_InputHook called regularly. - """ - try: - app = wx.GetApp() - if app is not None: - assert wx.Thread_IsMain() - - # Make a temporary event loop and process system events until - # there are no more waiting, then allow idle events (which - # will also deal with pending or posted wx events.) - evtloop = wx.EventLoop() - ea = wx.EventLoopActivator(evtloop) - while evtloop.Pending(): - evtloop.Dispatch() - app.ProcessIdle() - del ea - except KeyboardInterrupt: - pass - return 0 - -class EventLoopTimer(wx.Timer): - - def __init__(self, func): - self.func = func - wx.Timer.__init__(self) - - def Notify(self): - self.func() - -class EventLoopRunner(object): - - def Run(self, time, input_is_ready): - self.input_is_ready = input_is_ready - self.evtloop = wx.EventLoop() - self.timer = EventLoopTimer(self.check_stdin) - self.timer.Start(time) - self.evtloop.Run() - - def check_stdin(self): - if self.input_is_ready(): - self.timer.Stop() - self.evtloop.Exit() - -def inputhook_wx2(context): - """Run the wx event loop, polling for stdin. - - This version runs the wx eventloop for an undetermined amount of time, - during which it periodically checks to see if anything is ready on - stdin. If anything is ready on stdin, the event loop exits. - - The argument to elr.Run controls how often the event loop looks at stdin. - This determines the responsiveness at the keyboard. A setting of 1000 - enables a user to type at most 1 char per second. I have found that a - setting of 10 gives good keyboard response. We can shorten it further, - but eventually performance would suffer from calling select/kbhit too - often. - """ - try: - app = wx.GetApp() - if app is not None: - assert wx.Thread_IsMain() - elr = EventLoopRunner() - # As this time is made shorter, keyboard response improves, but idle - # CPU load goes up. 10 ms seems like a good compromise. - elr.Run(time=10, # CHANGE time here to control polling interval - input_is_ready=context.input_is_ready) - except KeyboardInterrupt: - pass - return 0 - -def inputhook_wx3(context): - """Run the wx event loop by processing pending events only. - - This is like inputhook_wx1, but it keeps processing pending events - until stdin is ready. After processing all pending events, a call to - time.sleep is inserted. This is needed, otherwise, CPU usage is at 100%. - This sleep time should be tuned though for best performance. - """ - # We need to protect against a user pressing Control-C when IPython is - # idle and this is running. We trap KeyboardInterrupt and pass. - try: - app = wx.GetApp() - if app is not None: - assert wx.Thread_IsMain() - - # The import of wx on Linux sets the handler for signal.SIGINT - # to 0. This is a bug in wx or gtk. We fix by just setting it - # back to the Python default. - if not callable(signal.getsignal(signal.SIGINT)): - signal.signal(signal.SIGINT, signal.default_int_handler) - - evtloop = wx.EventLoop() - ea = wx.EventLoopActivator(evtloop) - t = clock() - while not context.input_is_ready(): - while evtloop.Pending(): - t = clock() - evtloop.Dispatch() - app.ProcessIdle() - # We need to sleep at this point to keep the idle CPU load - # low. However, if sleep to long, GUI response is poor. As - # a compromise, we watch how often GUI events are being processed - # and switch between a short and long sleep time. Here are some - # stats useful in helping to tune this. - # time CPU load - # 0.001 13% - # 0.005 3% - # 0.01 1.5% - # 0.05 0.5% - used_time = clock() - t - if used_time > 10.0: - # print 'Sleep for 1 s' # dbg - time.sleep(1.0) - elif used_time > 0.1: - # Few GUI events coming in, so we can sleep longer - # print 'Sleep for 0.05 s' # dbg - time.sleep(0.05) - else: - # Many GUI events coming in, so sleep only very little - time.sleep(0.001) - del ea - except KeyboardInterrupt: - pass - return 0 - -if sys.platform == 'darwin': - # On OSX, evtloop.Pending() always returns True, regardless of there being - # any events pending. As such we can't use implementations 1 or 3 of the - # inputhook as those depend on a pending/dispatch loop. - inputhook = inputhook_wx2 -else: - # This is our default implementation - inputhook = inputhook_wx3 +"""Enable wxPython to be used interacively in prompt_toolkit +""" +from __future__ import absolute_import + +import sys +import signal +import time +from timeit import default_timer as clock +import wx + + +def inputhook_wx1(context): + """Run the wx event loop by processing pending events only. + + This approach seems to work, but its performance is not great as it + relies on having PyOS_InputHook called regularly. + """ + try: + app = wx.GetApp() + if app is not None: + assert wx.Thread_IsMain() + + # Make a temporary event loop and process system events until + # there are no more waiting, then allow idle events (which + # will also deal with pending or posted wx events.) + evtloop = wx.EventLoop() + ea = wx.EventLoopActivator(evtloop) + while evtloop.Pending(): + evtloop.Dispatch() + app.ProcessIdle() + del ea + except KeyboardInterrupt: + pass + return 0 + +class EventLoopTimer(wx.Timer): + + def __init__(self, func): + self.func = func + wx.Timer.__init__(self) + + def Notify(self): + self.func() + +class EventLoopRunner(object): + + def Run(self, time, input_is_ready): + self.input_is_ready = input_is_ready + self.evtloop = wx.EventLoop() + self.timer = EventLoopTimer(self.check_stdin) + self.timer.Start(time) + self.evtloop.Run() + + def check_stdin(self): + if self.input_is_ready(): + self.timer.Stop() + self.evtloop.Exit() + +def inputhook_wx2(context): + """Run the wx event loop, polling for stdin. + + This version runs the wx eventloop for an undetermined amount of time, + during which it periodically checks to see if anything is ready on + stdin. If anything is ready on stdin, the event loop exits. + + The argument to elr.Run controls how often the event loop looks at stdin. + This determines the responsiveness at the keyboard. A setting of 1000 + enables a user to type at most 1 char per second. I have found that a + setting of 10 gives good keyboard response. We can shorten it further, + but eventually performance would suffer from calling select/kbhit too + often. + """ + try: + app = wx.GetApp() + if app is not None: + assert wx.Thread_IsMain() + elr = EventLoopRunner() + # As this time is made shorter, keyboard response improves, but idle + # CPU load goes up. 10 ms seems like a good compromise. + elr.Run(time=10, # CHANGE time here to control polling interval + input_is_ready=context.input_is_ready) + except KeyboardInterrupt: + pass + return 0 + +def inputhook_wx3(context): + """Run the wx event loop by processing pending events only. + + This is like inputhook_wx1, but it keeps processing pending events + until stdin is ready. After processing all pending events, a call to + time.sleep is inserted. This is needed, otherwise, CPU usage is at 100%. + This sleep time should be tuned though for best performance. + """ + # We need to protect against a user pressing Control-C when IPython is + # idle and this is running. We trap KeyboardInterrupt and pass. + try: + app = wx.GetApp() + if app is not None: + assert wx.Thread_IsMain() + + # The import of wx on Linux sets the handler for signal.SIGINT + # to 0. This is a bug in wx or gtk. We fix by just setting it + # back to the Python default. + if not callable(signal.getsignal(signal.SIGINT)): + signal.signal(signal.SIGINT, signal.default_int_handler) + + evtloop = wx.EventLoop() + ea = wx.EventLoopActivator(evtloop) + t = clock() + while not context.input_is_ready(): + while evtloop.Pending(): + t = clock() + evtloop.Dispatch() + app.ProcessIdle() + # We need to sleep at this point to keep the idle CPU load + # low. However, if sleep to long, GUI response is poor. As + # a compromise, we watch how often GUI events are being processed + # and switch between a short and long sleep time. Here are some + # stats useful in helping to tune this. + # time CPU load + # 0.001 13% + # 0.005 3% + # 0.01 1.5% + # 0.05 0.5% + used_time = clock() - t + if used_time > 10.0: + # print 'Sleep for 1 s' # dbg + time.sleep(1.0) + elif used_time > 0.1: + # Few GUI events coming in, so we can sleep longer + # print 'Sleep for 0.05 s' # dbg + time.sleep(0.05) + else: + # Many GUI events coming in, so sleep only very little + time.sleep(0.001) + del ea + except KeyboardInterrupt: + pass + return 0 + +if sys.platform == 'darwin': + # On OSX, evtloop.Pending() always returns True, regardless of there being + # any events pending. As such we can't use implementations 1 or 3 of the + # inputhook as those depend on a pending/dispatch loop. + inputhook = inputhook_wx2 +else: + # This is our default implementation + inputhook = inputhook_wx3 diff --git a/contrib/python/ipython/py2/IPython/terminal/ptshell.py b/contrib/python/ipython/py2/IPython/terminal/ptshell.py index aad111b041..666d3c5b51 100644 --- a/contrib/python/ipython/py2/IPython/terminal/ptshell.py +++ b/contrib/python/ipython/py2/IPython/terminal/ptshell.py @@ -1,8 +1,8 @@ -raise DeprecationWarning("""DEPRECATED: - -After Popular request and decision from the BDFL: -`IPython.terminal.ptshell` has been moved back to `IPython.terminal.interactiveshell` -during the beta cycle (after IPython 5.0.beta3) Sorry about that. - -This file will be removed in 5.0 rc or final. -""") +raise DeprecationWarning("""DEPRECATED: + +After Popular request and decision from the BDFL: +`IPython.terminal.ptshell` has been moved back to `IPython.terminal.interactiveshell` +during the beta cycle (after IPython 5.0.beta3) Sorry about that. + +This file will be removed in 5.0 rc or final. +""") diff --git a/contrib/python/ipython/py2/IPython/terminal/ptutils.py b/contrib/python/ipython/py2/IPython/terminal/ptutils.py index 90def9d209..c9ff705642 100644 --- a/contrib/python/ipython/py2/IPython/terminal/ptutils.py +++ b/contrib/python/ipython/py2/IPython/terminal/ptutils.py @@ -1,47 +1,47 @@ -"""prompt-toolkit utilities - -Everything in this module is a private API, -not to be used outside IPython. -""" - -# Copyright (c) IPython Development Team. -# Distributed under the terms of the Modified BSD License. - -import unicodedata -from wcwidth import wcwidth - -from IPython.utils.py3compat import PY3 - -from IPython.core.completer import IPCompleter -from prompt_toolkit.completion import Completer, Completion -from prompt_toolkit.layout.lexers import Lexer -from prompt_toolkit.layout.lexers import PygmentsLexer - -import pygments.lexers as pygments_lexers - - -class IPythonPTCompleter(Completer): - """Adaptor to provide IPython completions to prompt_toolkit""" +"""prompt-toolkit utilities + +Everything in this module is a private API, +not to be used outside IPython. +""" + +# Copyright (c) IPython Development Team. +# Distributed under the terms of the Modified BSD License. + +import unicodedata +from wcwidth import wcwidth + +from IPython.utils.py3compat import PY3 + +from IPython.core.completer import IPCompleter +from prompt_toolkit.completion import Completer, Completion +from prompt_toolkit.layout.lexers import Lexer +from prompt_toolkit.layout.lexers import PygmentsLexer + +import pygments.lexers as pygments_lexers + + +class IPythonPTCompleter(Completer): + """Adaptor to provide IPython completions to prompt_toolkit""" def __init__(self, ipy_completer=None, shell=None, patch_stdout=None): - if shell is None and ipy_completer is None: - raise TypeError("Please pass shell=an InteractiveShell instance.") - self._ipy_completer = ipy_completer - self.shell = shell + if shell is None and ipy_completer is None: + raise TypeError("Please pass shell=an InteractiveShell instance.") + self._ipy_completer = ipy_completer + self.shell = shell if patch_stdout is None: raise TypeError("Please pass patch_stdout") self.patch_stdout = patch_stdout - - @property - def ipy_completer(self): - if self._ipy_completer: - return self._ipy_completer - else: - return self.shell.Completer - - def get_completions(self, document, complete_event): - if not document.current_line.strip(): - return - + + @property + def ipy_completer(self): + if self._ipy_completer: + return self._ipy_completer + else: + return self.shell.Completer + + def get_completions(self, document, complete_event): + if not document.current_line.strip(): + return + # Some bits of our completion system may print stuff (e.g. if a module # is imported). This context manager ensures that doesn't interfere with # the prompt. @@ -50,66 +50,66 @@ class IPythonPTCompleter(Completer): line_buffer=document.current_line, cursor_pos=document.cursor_position_col ) - start_pos = -len(used) - for m in matches: - if not m: - # Guard against completion machinery giving us an empty string. - continue - - m = unicodedata.normalize('NFC', m) - - # When the first character of the completion has a zero length, - # then it's probably a decomposed unicode character. E.g. caused by - # the "\dot" completion. Try to compose again with the previous - # character. - if wcwidth(m[0]) == 0: - if document.cursor_position + start_pos > 0: - char_before = document.text[document.cursor_position + start_pos - 1] - m = unicodedata.normalize('NFC', char_before + m) - - # Yield the modified completion instead, if this worked. - if wcwidth(m[0:1]) == 1: - yield Completion(m, start_position=start_pos - 1) - continue - - # TODO: Use Jedi to determine meta_text - # (Jedi currently has a bug that results in incorrect information.) - # meta_text = '' - # yield Completion(m, start_position=start_pos, - # display_meta=meta_text) - yield Completion(m, start_position=start_pos) - -class IPythonPTLexer(Lexer): - """ - Wrapper around PythonLexer and BashLexer. - """ - def __init__(self): - l = pygments_lexers - self.python_lexer = PygmentsLexer(l.Python3Lexer if PY3 else l.PythonLexer) - self.shell_lexer = PygmentsLexer(l.BashLexer) - - self.magic_lexers = { - 'HTML': PygmentsLexer(l.HtmlLexer), - 'html': PygmentsLexer(l.HtmlLexer), - 'javascript': PygmentsLexer(l.JavascriptLexer), - 'js': PygmentsLexer(l.JavascriptLexer), - 'perl': PygmentsLexer(l.PerlLexer), - 'ruby': PygmentsLexer(l.RubyLexer), - 'latex': PygmentsLexer(l.TexLexer), - } - - def lex_document(self, cli, document): - text = document.text.lstrip() - - lexer = self.python_lexer - - if text.startswith('!') or text.startswith('%%bash'): - lexer = self.shell_lexer - - elif text.startswith('%%'): - for magic, l in self.magic_lexers.items(): - if text.startswith('%%' + magic): - lexer = l - break - - return lexer.lex_document(cli, document) + start_pos = -len(used) + for m in matches: + if not m: + # Guard against completion machinery giving us an empty string. + continue + + m = unicodedata.normalize('NFC', m) + + # When the first character of the completion has a zero length, + # then it's probably a decomposed unicode character. E.g. caused by + # the "\dot" completion. Try to compose again with the previous + # character. + if wcwidth(m[0]) == 0: + if document.cursor_position + start_pos > 0: + char_before = document.text[document.cursor_position + start_pos - 1] + m = unicodedata.normalize('NFC', char_before + m) + + # Yield the modified completion instead, if this worked. + if wcwidth(m[0:1]) == 1: + yield Completion(m, start_position=start_pos - 1) + continue + + # TODO: Use Jedi to determine meta_text + # (Jedi currently has a bug that results in incorrect information.) + # meta_text = '' + # yield Completion(m, start_position=start_pos, + # display_meta=meta_text) + yield Completion(m, start_position=start_pos) + +class IPythonPTLexer(Lexer): + """ + Wrapper around PythonLexer and BashLexer. + """ + def __init__(self): + l = pygments_lexers + self.python_lexer = PygmentsLexer(l.Python3Lexer if PY3 else l.PythonLexer) + self.shell_lexer = PygmentsLexer(l.BashLexer) + + self.magic_lexers = { + 'HTML': PygmentsLexer(l.HtmlLexer), + 'html': PygmentsLexer(l.HtmlLexer), + 'javascript': PygmentsLexer(l.JavascriptLexer), + 'js': PygmentsLexer(l.JavascriptLexer), + 'perl': PygmentsLexer(l.PerlLexer), + 'ruby': PygmentsLexer(l.RubyLexer), + 'latex': PygmentsLexer(l.TexLexer), + } + + def lex_document(self, cli, document): + text = document.text.lstrip() + + lexer = self.python_lexer + + if text.startswith('!') or text.startswith('%%bash'): + lexer = self.shell_lexer + + elif text.startswith('%%'): + for magic, l in self.magic_lexers.items(): + if text.startswith('%%' + magic): + lexer = l + break + + return lexer.lex_document(cli, document) diff --git a/contrib/python/ipython/py2/IPython/terminal/shortcuts.py b/contrib/python/ipython/py2/IPython/terminal/shortcuts.py index 2769cf8e8e..8f0ae43e84 100644 --- a/contrib/python/ipython/py2/IPython/terminal/shortcuts.py +++ b/contrib/python/ipython/py2/IPython/terminal/shortcuts.py @@ -1,101 +1,101 @@ -import signal -import sys - -from prompt_toolkit.enums import DEFAULT_BUFFER, SEARCH_BUFFER -from prompt_toolkit.filters import (HasFocus, HasSelection, Condition, - ViInsertMode, EmacsInsertMode, HasCompletions) -from prompt_toolkit.filters.cli import ViMode -from prompt_toolkit.keys import Keys -from prompt_toolkit.key_binding.bindings.completion import display_completions_like_readline - -from IPython.utils.decorators import undoc - -@Condition -def cursor_in_leading_ws(cli): - before = cli.application.buffer.document.current_line_before_cursor - return (not before) or before.isspace() - -def register_ipython_shortcuts(registry, shell): - """Set up the prompt_toolkit keyboard shortcuts for IPython""" - insert_mode = ViInsertMode() | EmacsInsertMode() - - # Ctrl+J == Enter, seemingly - registry.add_binding(Keys.ControlJ, - filter=(HasFocus(DEFAULT_BUFFER) - & ~HasSelection() - & insert_mode - ))(newline_or_execute_outer(shell)) - - registry.add_binding(Keys.ControlBackslash)(force_exit) - - registry.add_binding(Keys.ControlP, - filter=(ViInsertMode() & HasFocus(DEFAULT_BUFFER) - ))(previous_history_or_previous_completion) - - registry.add_binding(Keys.ControlN, - filter=(ViInsertMode() & HasFocus(DEFAULT_BUFFER) - ))(next_history_or_next_completion) - - registry.add_binding(Keys.ControlG, - filter=(HasFocus(DEFAULT_BUFFER) & HasCompletions() - ))(dismiss_completion) - - registry.add_binding(Keys.ControlC, filter=HasFocus(DEFAULT_BUFFER) - )(reset_buffer) - - registry.add_binding(Keys.ControlC, filter=HasFocus(SEARCH_BUFFER) - )(reset_search_buffer) - - supports_suspend = Condition(lambda cli: hasattr(signal, 'SIGTSTP')) - registry.add_binding(Keys.ControlZ, filter=supports_suspend - )(suspend_to_bg) - - # Ctrl+I == Tab - registry.add_binding(Keys.ControlI, - filter=(HasFocus(DEFAULT_BUFFER) - & ~HasSelection() - & insert_mode - & cursor_in_leading_ws - ))(indent_buffer) - - registry.add_binding(Keys.ControlO, - filter=(HasFocus(DEFAULT_BUFFER) - & EmacsInsertMode()))(newline_with_copy_margin) - +import signal +import sys + +from prompt_toolkit.enums import DEFAULT_BUFFER, SEARCH_BUFFER +from prompt_toolkit.filters import (HasFocus, HasSelection, Condition, + ViInsertMode, EmacsInsertMode, HasCompletions) +from prompt_toolkit.filters.cli import ViMode +from prompt_toolkit.keys import Keys +from prompt_toolkit.key_binding.bindings.completion import display_completions_like_readline + +from IPython.utils.decorators import undoc + +@Condition +def cursor_in_leading_ws(cli): + before = cli.application.buffer.document.current_line_before_cursor + return (not before) or before.isspace() + +def register_ipython_shortcuts(registry, shell): + """Set up the prompt_toolkit keyboard shortcuts for IPython""" + insert_mode = ViInsertMode() | EmacsInsertMode() + + # Ctrl+J == Enter, seemingly + registry.add_binding(Keys.ControlJ, + filter=(HasFocus(DEFAULT_BUFFER) + & ~HasSelection() + & insert_mode + ))(newline_or_execute_outer(shell)) + + registry.add_binding(Keys.ControlBackslash)(force_exit) + + registry.add_binding(Keys.ControlP, + filter=(ViInsertMode() & HasFocus(DEFAULT_BUFFER) + ))(previous_history_or_previous_completion) + + registry.add_binding(Keys.ControlN, + filter=(ViInsertMode() & HasFocus(DEFAULT_BUFFER) + ))(next_history_or_next_completion) + + registry.add_binding(Keys.ControlG, + filter=(HasFocus(DEFAULT_BUFFER) & HasCompletions() + ))(dismiss_completion) + + registry.add_binding(Keys.ControlC, filter=HasFocus(DEFAULT_BUFFER) + )(reset_buffer) + + registry.add_binding(Keys.ControlC, filter=HasFocus(SEARCH_BUFFER) + )(reset_search_buffer) + + supports_suspend = Condition(lambda cli: hasattr(signal, 'SIGTSTP')) + registry.add_binding(Keys.ControlZ, filter=supports_suspend + )(suspend_to_bg) + + # Ctrl+I == Tab + registry.add_binding(Keys.ControlI, + filter=(HasFocus(DEFAULT_BUFFER) + & ~HasSelection() + & insert_mode + & cursor_in_leading_ws + ))(indent_buffer) + + registry.add_binding(Keys.ControlO, + filter=(HasFocus(DEFAULT_BUFFER) + & EmacsInsertMode()))(newline_with_copy_margin) + registry.add_binding(Keys.F2, filter=HasFocus(DEFAULT_BUFFER) )(open_input_in_editor) - if shell.display_completions == 'readlinelike': - registry.add_binding(Keys.ControlI, - filter=(HasFocus(DEFAULT_BUFFER) - & ~HasSelection() - & insert_mode - & ~cursor_in_leading_ws - ))(display_completions_like_readline) - - if sys.platform == 'win32': - registry.add_binding(Keys.ControlV, - filter=( - HasFocus( - DEFAULT_BUFFER) & ~ViMode() - ))(win_paste) - - -def newline_or_execute_outer(shell): - def newline_or_execute(event): - """When the user presses return, insert a newline or execute the code.""" - b = event.current_buffer - d = b.document - - if b.complete_state: - cc = b.complete_state.current_completion - if cc: - b.apply_completion(cc) - else: - b.cancel_completion() - return - + if shell.display_completions == 'readlinelike': + registry.add_binding(Keys.ControlI, + filter=(HasFocus(DEFAULT_BUFFER) + & ~HasSelection() + & insert_mode + & ~cursor_in_leading_ws + ))(display_completions_like_readline) + + if sys.platform == 'win32': + registry.add_binding(Keys.ControlV, + filter=( + HasFocus( + DEFAULT_BUFFER) & ~ViMode() + ))(win_paste) + + +def newline_or_execute_outer(shell): + def newline_or_execute(event): + """When the user presses return, insert a newline or execute the code.""" + b = event.current_buffer + d = b.document + + if b.complete_state: + cc = b.complete_state.current_completion + if cc: + b.apply_completion(cc) + else: + b.cancel_completion() + return + # If there's only one line, treat it as if the cursor is at the end. # See https://github.com/ipython/ipython/issues/10425 if d.line_count == 1: @@ -108,99 +108,99 @@ def newline_or_execute_outer(shell): d.cursor_position_row >= d.line_count - d.empty_line_count_at_the_end() ): b.insert_text('\n' + (' ' * (indent or 0))) - return - - if (status != 'incomplete') and b.accept_action.is_returnable: - b.accept_action.validate_and_handle(event.cli, b) - else: - b.insert_text('\n' + (' ' * (indent or 0))) - return newline_or_execute - - -def previous_history_or_previous_completion(event): - """ - Control-P in vi edit mode on readline is history next, unlike default prompt toolkit. - - If completer is open this still select previous completion. - """ - event.current_buffer.auto_up() - - -def next_history_or_next_completion(event): - """ - Control-N in vi edit mode on readline is history previous, unlike default prompt toolkit. - - If completer is open this still select next completion. - """ - event.current_buffer.auto_down() - - -def dismiss_completion(event): - b = event.current_buffer - if b.complete_state: - b.cancel_completion() - - -def reset_buffer(event): - b = event.current_buffer - if b.complete_state: - b.cancel_completion() - else: - b.reset() - - -def reset_search_buffer(event): - if event.current_buffer.document.text: - event.current_buffer.reset() - else: - event.cli.push_focus(DEFAULT_BUFFER) - -def suspend_to_bg(event): - event.cli.suspend_to_background() - -def force_exit(event): - """ - Force exit (with a non-zero return value) - """ - sys.exit("Quit") - -def indent_buffer(event): - event.current_buffer.insert_text(' ' * 4) - -def newline_with_copy_margin(event): - """ - Preserve margin and cursor position when using - Control-O to insert a newline in EMACS mode - """ - b = event.current_buffer - cursor_start_pos = b.document.cursor_position_col - b.newline(copy_margin=True) - b.cursor_up(count=1) - cursor_end_pos = b.document.cursor_position_col - if cursor_start_pos != cursor_end_pos: - pos_diff = cursor_start_pos - cursor_end_pos - b.cursor_right(count=pos_diff) - + return + + if (status != 'incomplete') and b.accept_action.is_returnable: + b.accept_action.validate_and_handle(event.cli, b) + else: + b.insert_text('\n' + (' ' * (indent or 0))) + return newline_or_execute + + +def previous_history_or_previous_completion(event): + """ + Control-P in vi edit mode on readline is history next, unlike default prompt toolkit. + + If completer is open this still select previous completion. + """ + event.current_buffer.auto_up() + + +def next_history_or_next_completion(event): + """ + Control-N in vi edit mode on readline is history previous, unlike default prompt toolkit. + + If completer is open this still select next completion. + """ + event.current_buffer.auto_down() + + +def dismiss_completion(event): + b = event.current_buffer + if b.complete_state: + b.cancel_completion() + + +def reset_buffer(event): + b = event.current_buffer + if b.complete_state: + b.cancel_completion() + else: + b.reset() + + +def reset_search_buffer(event): + if event.current_buffer.document.text: + event.current_buffer.reset() + else: + event.cli.push_focus(DEFAULT_BUFFER) + +def suspend_to_bg(event): + event.cli.suspend_to_background() + +def force_exit(event): + """ + Force exit (with a non-zero return value) + """ + sys.exit("Quit") + +def indent_buffer(event): + event.current_buffer.insert_text(' ' * 4) + +def newline_with_copy_margin(event): + """ + Preserve margin and cursor position when using + Control-O to insert a newline in EMACS mode + """ + b = event.current_buffer + cursor_start_pos = b.document.cursor_position_col + b.newline(copy_margin=True) + b.cursor_up(count=1) + cursor_end_pos = b.document.cursor_position_col + if cursor_start_pos != cursor_end_pos: + pos_diff = cursor_start_pos - cursor_end_pos + b.cursor_right(count=pos_diff) + def open_input_in_editor(event): event.cli.current_buffer.tempfile_suffix = ".py" event.cli.current_buffer.open_in_editor(event.cli) - - -if sys.platform == 'win32': - from IPython.core.error import TryNext - from IPython.lib.clipboard import (ClipboardEmpty, - win32_clipboard_get, - tkinter_clipboard_get) - - @undoc - def win_paste(event): - try: - text = win32_clipboard_get() - except TryNext: - try: - text = tkinter_clipboard_get() - except (TryNext, ClipboardEmpty): - return - except ClipboardEmpty: - return - event.current_buffer.insert_text(text.replace('\t', ' ' * 4)) + + +if sys.platform == 'win32': + from IPython.core.error import TryNext + from IPython.lib.clipboard import (ClipboardEmpty, + win32_clipboard_get, + tkinter_clipboard_get) + + @undoc + def win_paste(event): + try: + text = win32_clipboard_get() + except TryNext: + try: + text = tkinter_clipboard_get() + except (TryNext, ClipboardEmpty): + return + except ClipboardEmpty: + return + event.current_buffer.insert_text(text.replace('\t', ' ' * 4)) |