aboutsummaryrefslogtreecommitdiffstats
path: root/contrib/python/ipython/py3/IPython/terminal
diff options
context:
space:
mode:
authorshadchin <shadchin@yandex-team.ru>2022-02-10 16:44:39 +0300
committerDaniil Cherednik <dcherednik@yandex-team.ru>2022-02-10 16:44:39 +0300
commite9656aae26e0358d5378e5b63dcac5c8dbe0e4d0 (patch)
tree64175d5cadab313b3e7039ebaa06c5bc3295e274 /contrib/python/ipython/py3/IPython/terminal
parent2598ef1d0aee359b4b6d5fdd1758916d5907d04f (diff)
downloadydb-e9656aae26e0358d5378e5b63dcac5c8dbe0e4d0.tar.gz
Restoring authorship annotation for <shadchin@yandex-team.ru>. Commit 2 of 2.
Diffstat (limited to 'contrib/python/ipython/py3/IPython/terminal')
-rw-r--r--contrib/python/ipython/py3/IPython/terminal/console.py38
-rw-r--r--contrib/python/ipython/py3/IPython/terminal/debugger.py292
-rw-r--r--contrib/python/ipython/py3/IPython/terminal/embed.py798
-rw-r--r--contrib/python/ipython/py3/IPython/terminal/interactiveshell.py1296
-rw-r--r--contrib/python/ipython/py3/IPython/terminal/ipapp.py760
-rw-r--r--contrib/python/ipython/py3/IPython/terminal/magics.py426
-rw-r--r--contrib/python/ipython/py3/IPython/terminal/prompts.py216
-rw-r--r--contrib/python/ipython/py3/IPython/terminal/pt_inputhooks/__init__.py124
-rw-r--r--contrib/python/ipython/py3/IPython/terminal/pt_inputhooks/asyncio.py128
-rw-r--r--contrib/python/ipython/py3/IPython/terminal/pt_inputhooks/glut.py280
-rw-r--r--contrib/python/ipython/py3/IPython/terminal/pt_inputhooks/gtk.py116
-rw-r--r--contrib/python/ipython/py3/IPython/terminal/pt_inputhooks/gtk3.py24
-rw-r--r--contrib/python/ipython/py3/IPython/terminal/pt_inputhooks/gtk4.py54
-rw-r--r--contrib/python/ipython/py3/IPython/terminal/pt_inputhooks/osx.py314
-rw-r--r--contrib/python/ipython/py3/IPython/terminal/pt_inputhooks/pyglet.py132
-rw-r--r--contrib/python/ipython/py3/IPython/terminal/pt_inputhooks/qt.py166
-rw-r--r--contrib/python/ipython/py3/IPython/terminal/pt_inputhooks/tk.py180
-rw-r--r--contrib/python/ipython/py3/IPython/terminal/pt_inputhooks/wx.py438
-rw-r--r--contrib/python/ipython/py3/IPython/terminal/ptshell.py16
-rw-r--r--contrib/python/ipython/py3/IPython/terminal/ptutils.py394
-rw-r--r--contrib/python/ipython/py3/IPython/terminal/shortcuts.py552
21 files changed, 3372 insertions, 3372 deletions
diff --git a/contrib/python/ipython/py3/IPython/terminal/console.py b/contrib/python/ipython/py3/IPython/terminal/console.py
index ccf3478c3d..65571a7572 100644
--- a/contrib/python/ipython/py3/IPython/terminal/console.py
+++ b/contrib/python/ipython/py3/IPython/terminal/console.py
@@ -1,19 +1,19 @@
-"""
-Shim to maintain backwards compatibility with old IPython.terminal.console imports.
-"""
-# Copyright (c) IPython Development Team.
-# Distributed under the terms of the Modified BSD License.
-
-import sys
-from warnings import warn
-
-from IPython.utils.shimmodule import ShimModule, ShimWarning
-
-warn("The `IPython.terminal.console` package has been deprecated since IPython 4.0. "
- "You should import from jupyter_console instead.", ShimWarning)
-
-# Unconditionally insert the shim into sys.modules so that further import calls
-# trigger the custom attribute access above
-
-sys.modules['IPython.terminal.console'] = ShimModule(
- src='IPython.terminal.console', mirror='jupyter_console')
+"""
+Shim to maintain backwards compatibility with old IPython.terminal.console imports.
+"""
+# Copyright (c) IPython Development Team.
+# Distributed under the terms of the Modified BSD License.
+
+import sys
+from warnings import warn
+
+from IPython.utils.shimmodule import ShimModule, ShimWarning
+
+warn("The `IPython.terminal.console` package has been deprecated since IPython 4.0. "
+ "You should import from jupyter_console instead.", ShimWarning)
+
+# Unconditionally insert the shim into sys.modules so that further import calls
+# trigger the custom attribute access above
+
+sys.modules['IPython.terminal.console'] = ShimModule(
+ src='IPython.terminal.console', mirror='jupyter_console')
diff --git a/contrib/python/ipython/py3/IPython/terminal/debugger.py b/contrib/python/ipython/py3/IPython/terminal/debugger.py
index f9a4ca445f..db8ecac0d2 100644
--- a/contrib/python/ipython/py3/IPython/terminal/debugger.py
+++ b/contrib/python/ipython/py3/IPython/terminal/debugger.py
@@ -1,146 +1,146 @@
-import asyncio
-import signal
-import sys
-
-from IPython.core.debugger import Pdb
-from IPython.core.completer import IPCompleter
-from .ptutils import IPythonPTCompleter
-from .shortcuts import create_ipython_shortcuts, suspend_to_bg, cursor_in_leading_ws
-
-from prompt_toolkit.enums import DEFAULT_BUFFER
-from prompt_toolkit.filters import (Condition, has_focus, has_selection,
- vi_insert_mode, emacs_insert_mode)
-from prompt_toolkit.key_binding import KeyBindings
-from prompt_toolkit.key_binding.bindings.completion import display_completions_like_readline
-from pygments.token import Token
-from prompt_toolkit.shortcuts.prompt import PromptSession
-from prompt_toolkit.enums import EditingMode
-from prompt_toolkit.formatted_text import PygmentsTokens
-from concurrent.futures import ThreadPoolExecutor
-
-from prompt_toolkit import __version__ as ptk_version
-PTK3 = ptk_version.startswith('3.')
-
-
-class TerminalPdb(Pdb):
- """Standalone IPython debugger."""
-
- def __init__(self, *args, pt_session_options=None, **kwargs):
- Pdb.__init__(self, *args, **kwargs)
- self._ptcomp = None
- self.pt_init(pt_session_options)
- self.thread_executor = ThreadPoolExecutor(1)
-
- def pt_init(self, pt_session_options=None):
- """Initialize the prompt session and the prompt loop
- and store them in self.pt_app and self.pt_loop.
-
- Additional keyword arguments for the PromptSession class
- can be specified in pt_session_options.
- """
- if pt_session_options is None:
- pt_session_options = {}
-
- def get_prompt_tokens():
- return [(Token.Prompt, self.prompt)]
-
- if self._ptcomp is None:
- compl = IPCompleter(shell=self.shell,
- namespace={},
- global_namespace={},
- parent=self.shell,
- )
- # add a completer for all the do_ methods
- methods_names = [m[3:] for m in dir(self) if m.startswith("do_")]
-
- def gen_comp(self, text):
- return [m for m in methods_names if m.startswith(text)]
- import types
- newcomp = types.MethodType(gen_comp, compl)
- compl.custom_matchers.insert(0, newcomp)
- # end add completer.
-
- self._ptcomp = IPythonPTCompleter(compl)
-
- options = dict(
- message=(lambda: PygmentsTokens(get_prompt_tokens())),
- editing_mode=getattr(EditingMode, self.shell.editing_mode.upper()),
- key_bindings=create_ipython_shortcuts(self.shell),
- history=self.shell.debugger_history,
- completer=self._ptcomp,
- enable_history_search=True,
- mouse_support=self.shell.mouse_support,
- complete_style=self.shell.pt_complete_style,
- style=getattr(self.shell, "style", None),
- color_depth=self.shell.color_depth,
- )
-
- if not PTK3:
- options['inputhook'] = self.shell.inputhook
- options.update(pt_session_options)
- self.pt_loop = asyncio.new_event_loop()
- self.pt_app = PromptSession(**options)
-
- 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')
-
- # In order to make sure that prompt, which uses asyncio doesn't
- # interfere with applications in which it's used, we always run the
- # prompt itself in a different thread (we can't start an event loop
- # within an event loop). This new thread won't have any event loop
- # running, and here we run our prompt-loop.
- self.preloop()
-
- try:
- if intro is not None:
- self.intro = intro
- if self.intro:
- print(self.intro, file=self.stdout)
- 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
-
- # Run the prompt in a different thread.
- try:
- line = self.thread_executor.submit(self.pt_app.prompt).result()
- 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`.
-
- If frame is not specified, debugging starts from caller's frame.
- """
- TerminalPdb().set_trace(frame or sys._getframe().f_back)
-
-
-if __name__ == '__main__':
- import pdb
- # IPython.core.debugger.Pdb.trace_dispatch shall not catch
- # bdb.BdbQuit. When started through __main__ and an exception
- # happened after hitting "c", this is needed in order to
- # be able to quit the debugging session (see #9950).
- old_trace_dispatch = pdb.Pdb.trace_dispatch
- pdb.Pdb = TerminalPdb
- pdb.Pdb.trace_dispatch = old_trace_dispatch
- pdb.main()
+import asyncio
+import signal
+import sys
+
+from IPython.core.debugger import Pdb
+from IPython.core.completer import IPCompleter
+from .ptutils import IPythonPTCompleter
+from .shortcuts import create_ipython_shortcuts, suspend_to_bg, cursor_in_leading_ws
+
+from prompt_toolkit.enums import DEFAULT_BUFFER
+from prompt_toolkit.filters import (Condition, has_focus, has_selection,
+ vi_insert_mode, emacs_insert_mode)
+from prompt_toolkit.key_binding import KeyBindings
+from prompt_toolkit.key_binding.bindings.completion import display_completions_like_readline
+from pygments.token import Token
+from prompt_toolkit.shortcuts.prompt import PromptSession
+from prompt_toolkit.enums import EditingMode
+from prompt_toolkit.formatted_text import PygmentsTokens
+from concurrent.futures import ThreadPoolExecutor
+
+from prompt_toolkit import __version__ as ptk_version
+PTK3 = ptk_version.startswith('3.')
+
+
+class TerminalPdb(Pdb):
+ """Standalone IPython debugger."""
+
+ def __init__(self, *args, pt_session_options=None, **kwargs):
+ Pdb.__init__(self, *args, **kwargs)
+ self._ptcomp = None
+ self.pt_init(pt_session_options)
+ self.thread_executor = ThreadPoolExecutor(1)
+
+ def pt_init(self, pt_session_options=None):
+ """Initialize the prompt session and the prompt loop
+ and store them in self.pt_app and self.pt_loop.
+
+ Additional keyword arguments for the PromptSession class
+ can be specified in pt_session_options.
+ """
+ if pt_session_options is None:
+ pt_session_options = {}
+
+ def get_prompt_tokens():
+ return [(Token.Prompt, self.prompt)]
+
+ if self._ptcomp is None:
+ compl = IPCompleter(shell=self.shell,
+ namespace={},
+ global_namespace={},
+ parent=self.shell,
+ )
+ # add a completer for all the do_ methods
+ methods_names = [m[3:] for m in dir(self) if m.startswith("do_")]
+
+ def gen_comp(self, text):
+ return [m for m in methods_names if m.startswith(text)]
+ import types
+ newcomp = types.MethodType(gen_comp, compl)
+ compl.custom_matchers.insert(0, newcomp)
+ # end add completer.
+
+ self._ptcomp = IPythonPTCompleter(compl)
+
+ options = dict(
+ message=(lambda: PygmentsTokens(get_prompt_tokens())),
+ editing_mode=getattr(EditingMode, self.shell.editing_mode.upper()),
+ key_bindings=create_ipython_shortcuts(self.shell),
+ history=self.shell.debugger_history,
+ completer=self._ptcomp,
+ enable_history_search=True,
+ mouse_support=self.shell.mouse_support,
+ complete_style=self.shell.pt_complete_style,
+ style=getattr(self.shell, "style", None),
+ color_depth=self.shell.color_depth,
+ )
+
+ if not PTK3:
+ options['inputhook'] = self.shell.inputhook
+ options.update(pt_session_options)
+ self.pt_loop = asyncio.new_event_loop()
+ self.pt_app = PromptSession(**options)
+
+ 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')
+
+ # In order to make sure that prompt, which uses asyncio doesn't
+ # interfere with applications in which it's used, we always run the
+ # prompt itself in a different thread (we can't start an event loop
+ # within an event loop). This new thread won't have any event loop
+ # running, and here we run our prompt-loop.
+ self.preloop()
+
+ try:
+ if intro is not None:
+ self.intro = intro
+ if self.intro:
+ print(self.intro, file=self.stdout)
+ 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
+
+ # Run the prompt in a different thread.
+ try:
+ line = self.thread_executor.submit(self.pt_app.prompt).result()
+ 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`.
+
+ If frame is not specified, debugging starts from caller's frame.
+ """
+ TerminalPdb().set_trace(frame or sys._getframe().f_back)
+
+
+if __name__ == '__main__':
+ import pdb
+ # IPython.core.debugger.Pdb.trace_dispatch shall not catch
+ # bdb.BdbQuit. When started through __main__ and an exception
+ # happened after hitting "c", this is needed in order to
+ # be able to quit the debugging session (see #9950).
+ old_trace_dispatch = pdb.Pdb.trace_dispatch
+ pdb.Pdb = TerminalPdb
+ pdb.Pdb.trace_dispatch = old_trace_dispatch
+ pdb.main()
diff --git a/contrib/python/ipython/py3/IPython/terminal/embed.py b/contrib/python/ipython/py3/IPython/terminal/embed.py
index 25ddd53afa..188844fadd 100644
--- a/contrib/python/ipython/py3/IPython/terminal/embed.py
+++ b/contrib/python/ipython/py3/IPython/terminal/embed.py
@@ -1,399 +1,399 @@
-# encoding: utf-8
-"""
-An embedded IPython shell.
-"""
-# Copyright (c) IPython Development Team.
-# Distributed under the terms of the Modified BSD License.
-
-
-import sys
-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.terminal.interactiveshell import TerminalInteractiveShell
-from IPython.terminal.ipapp import load_default_config
-
-from traitlets import Bool, CBool, Unicode
-from IPython.utils.io import ask_yes_no
-
-class KillEmbedded(Exception):pass
-
-# kept for backward compatibility as IPython 6 was released with
-# the typo. See https://github.com/ipython/ipython/pull/10706
-KillEmbeded = KillEmbedded
-
-# This is an additional magic that is exposed in embedded shells.
-@magics_class
-class EmbeddedMagics(Magics):
-
- @line_magic
- @magic_arguments.magic_arguments()
- @magic_arguments.argument('-i', '--instance', action='store_true',
- help='Kill instance instead of call location')
- @magic_arguments.argument('-x', '--exit', action='store_true',
- help='Also exit the current session')
- @magic_arguments.argument('-y', '--yes', action='store_true',
- help='Do not ask confirmation')
- def kill_embedded(self, parameter_s=''):
- """%kill_embedded : deactivate for good the current embedded IPython
-
- This function (after asking for confirmation) sets an internal flag so
- that an embedded IPython will never activate again for the given call
- location. This is useful to permanently disable a shell that is being
- called inside a loop: once you've figured out what you needed from it,
- you may then kill it and the program will then continue to run without
- the interactive shell interfering again.
-
-
- Kill Instance Option:
-
- If for some reasons you need to kill the location where the instance
- is created and not called, for example if you create a single
- instance in one place and debug in many locations, you can use the
- ``--instance`` option to kill this specific instance. Like for the
- ``call location`` killing an "instance" should work even if it is
- recreated within a loop.
-
- .. note::
-
- This was the default behavior before IPython 5.2
-
- """
-
- args = magic_arguments.parse_argstring(self.kill_embedded, parameter_s)
- print(args)
- if args.instance:
- # let no ask
- if not args.yes:
- kill = ask_yes_no(
- "Are you sure you want to kill this embedded instance? [y/N] ", 'n')
- else:
- kill = True
- if kill:
- self.shell._disable_init_location()
- print("This embedded IPython instance will not reactivate anymore "
- "once you exit.")
- else:
- if not args.yes:
- kill = ask_yes_no(
- "Are you sure you want to kill this embedded call_location? [y/N] ", 'n')
- else:
- kill = True
- if kill:
- self.shell.embedded_active = False
- print("This embedded IPython call location will not reactivate anymore "
- "once you exit.")
-
- if args.exit:
- # Ask-exit does not really ask, it just set internals flags to exit
- # on next loop.
- self.shell.ask_exit()
-
-
- @line_magic
- def exit_raise(self, parameter_s=''):
- """%exit_raise Make the current embedded kernel exit and raise and exception.
-
- This function sets an internal flag so that an embedded IPython will
- raise a `IPython.terminal.embed.KillEmbedded` Exception on exit, and then exit the current I. This is
- useful to permanently exit a loop that create IPython embed instance.
- """
-
- self.shell.should_raise = True
- self.shell.ask_exit()
-
-
-
-class InteractiveShellEmbed(TerminalInteractiveShell):
-
- dummy_mode = Bool(False)
- exit_msg = Unicode('')
- embedded = CBool(True)
- should_raise = CBool(False)
- # Like the base class display_banner is not configurable, but here it
- # is True by default.
- 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):
- 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):
- if value:
- InteractiveShellEmbed._inactive_locations.discard(
- self._call_location_id)
- InteractiveShellEmbed._inactive_locations.discard(
- self._init_location_id)
- 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(
- "Key word argument `user_global_ns` has been replaced by `user_module` since IPython 4.0.")
-
- clid = kw.pop('_init_location_id', None)
- if not clid:
- 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
- # trapped
- sys.excepthook = ultratb.FormattedTB(color_scheme=self.colors,
- mode=self.xmode,
- call_pdb=self.pdb)
-
- def init_sys_modules(self):
- """
- Explicitly overwrite :mod:`IPython.core.interactiveshell` to do nothing.
- """
- pass
-
- def init_magics(self):
- super(InteractiveShellEmbed, self).init_magics()
- self.register_magics(EmbeddedMagics)
-
- def __call__(self, header='', local_ns=None, module=None, dummy=None,
- stack_depth=1, global_ns=None, compile_flags=None, **kw):
- """Activate the interactive interpreter.
-
- __call__(self,header='',local_ns=None,module=None,dummy=None) -> Start
- the interpreter shell with the given local and global namespaces, and
- optionally print a header string at startup.
-
- The shell can be globally activated/deactivated using the
- dummy_mode attribute. This allows you to turn off a shell used
- for debugging globally.
-
- However, *each* time you call the shell you can override the current
- state of dummy_mode with the optional keyword parameter 'dummy'. For
- example, if you set dummy mode on with IPShell.dummy_mode = True, you
- can still have a specific call work by making it as IPShell(dummy=False).
- """
-
- # we are called, set the underlying interactiveshell not to exit.
- self.keep_running = True
-
- # If the user has turned it off, go away
- clid = kw.pop('_call_location_id', None)
- if not clid:
- frame = sys._getframe(1)
- clid = '%s:%s' % (frame.f_code.co_filename, frame.f_lineno)
- self._call_location_id = clid
-
- if not self.embedded_active:
- return
-
- # Normal exits from interactive mode set this flag, so the shell can't
- # re-enter (it checks this variable at the start of interactive mode).
- self.exit_now = False
-
- # Allow the dummy parameter to override the global __dummy_mode
- if dummy or (dummy != 0 and self.dummy_mode):
- return
-
- # self.banner is auto computed
- if header:
- self.old_banner2 = self.banner2
- self.banner2 = self.banner2 + '\n' + header + '\n'
- else:
- self.old_banner2 = ''
-
- 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,
- global_ns=global_ns, compile_flags=compile_flags)
-
- self.banner2 = self.old_banner2
-
- if self.exit_msg is not None:
- print(self.exit_msg)
-
- if self.should_raise:
- raise KillEmbedded('Embedded IPython raising error, as user requested.')
-
-
- def mainloop(self, local_ns=None, module=None, stack_depth=0,
- display_banner=None, global_ns=None, compile_flags=None):
- """Embeds IPython into a running python program.
-
- Parameters
- ----------
-
- local_ns, module
- Working local namespace (a dict) and module (a module or similar
- object). If given as None, they are automatically taken from the scope
- where the shell was called, so that program variables become visible.
-
- stack_depth : int
- How many levels in the stack to go to looking for namespaces (when
- local_ns or module is None). This allows an intermediate caller to
- make sure that this function gets the namespace from the intended
- level in the stack. By default (0) it will get its locals and globals
- from the immediate caller.
-
- compile_flags
- A bit field identifying the __future__ features
- that are enabled, as passed to the builtin :func:`compile` function.
- If given as None, they are automatically taken from the scope where
- the shell was called.
-
- """
-
- 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.")
-
- 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):
- call_frame = sys._getframe(stack_depth).f_back
-
- if local_ns is None:
- 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
- if compile_flags is None:
- compile_flags = (call_frame.f_code.co_flags &
- compilerop.PyCF_MASK)
-
- # Save original namespace and module so we can restore them after
- # embedding; otherwise the shell doesn't shut down correctly.
- orig_user_module = self.user_module
- orig_user_ns = self.user_ns
- orig_compile_flags = self.compile.flags
-
- # Update namespaces and fire up interpreter
-
- # The global one is easy, we can just throw it in
- if module is not None:
- self.user_module = module
-
- # But the user/local one is tricky: ipython needs it to store internal
- # data, but we also need the locals. We'll throw our hidden variables
- # like _ih and get_ipython() into the local namespace, but delete them
- # later.
- if local_ns is not None:
- reentrant_local_ns = {k: v for (k, v) in local_ns.items() if k not in self.user_ns_hidden.keys()}
- self.user_ns = reentrant_local_ns
- self.init_user_ns()
-
- # Compiler flags
- if compile_flags is not None:
- self.compile.flags = compile_flags
-
- # make sure the tab-completer has the correct frame information, so it
- # actually completes using the frame's locals/globals
- self.set_completer_frame()
-
- with self.builtin_trap, self.display_trap:
- self.interact()
-
- # now, purge out the local namespace of IPython's hidden variables.
- if local_ns is not None:
- local_ns.update({k: v for (k, v) in self.user_ns.items() if k not in self.user_ns_hidden.keys()})
-
-
- # Restore original namespace so shell can shut down when we exit.
- self.user_module = orig_user_module
- self.user_ns = orig_user_ns
- self.compile.flags = orig_compile_flags
-
-
-def embed(**kwargs):
- """Call this to embed IPython at the current point in your program.
-
- The first invocation of this will create an :class:`InteractiveShellEmbed`
- instance and then call it. Consecutive calls just call the already
- created instance.
-
- If you don't want the kernel to initialize the namespace
- from the scope of the surrounding function,
- and/or you want to load full IPython configuration,
- you probably want `IPython.start_ipython()` instead.
-
- Here is a simple example::
-
- from IPython import embed
- a = 10
- b = 20
- embed(header='First time')
- c = 30
- d = 40
- embed()
-
- Full customization can be done by passing a :class:`Config` in as the
- config argument.
- """
- config = kwargs.get('config')
- header = kwargs.pop('header', u'')
- compile_flags = kwargs.pop('compile_flags', None)
- if config is None:
- config = load_default_config()
- config.InteractiveShellEmbed = config.TerminalInteractiveShell
- kwargs['config'] = config
- using = kwargs.get('using', 'sync')
- if using :
- kwargs['config'].update({'TerminalInteractiveShell':{'loop_runner':using, 'colors':'NoColor', 'autoawait': using!='sync'}})
- #save ps1/ps2 if defined
- ps1 = None
- ps2 = None
- try:
- ps1 = sys.ps1
- ps2 = sys.ps2
- except AttributeError:
- pass
- #save previous instance
- saved_shell_instance = InteractiveShell._instance
- if saved_shell_instance is not None:
- cls = type(saved_shell_instance)
- cls.clear_instance()
- 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,
- _call_location_id='%s:%s' % (frame.f_code.co_filename, frame.f_lineno))
- InteractiveShellEmbed.clear_instance()
- #restore previous instance
- if saved_shell_instance is not None:
- cls = type(saved_shell_instance)
- cls.clear_instance()
- for subclass in cls._walk_mro():
- subclass._instance = saved_shell_instance
- if ps1 is not None:
- sys.ps1 = ps1
- sys.ps2 = ps2
+# encoding: utf-8
+"""
+An embedded IPython shell.
+"""
+# Copyright (c) IPython Development Team.
+# Distributed under the terms of the Modified BSD License.
+
+
+import sys
+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.terminal.interactiveshell import TerminalInteractiveShell
+from IPython.terminal.ipapp import load_default_config
+
+from traitlets import Bool, CBool, Unicode
+from IPython.utils.io import ask_yes_no
+
+class KillEmbedded(Exception):pass
+
+# kept for backward compatibility as IPython 6 was released with
+# the typo. See https://github.com/ipython/ipython/pull/10706
+KillEmbeded = KillEmbedded
+
+# This is an additional magic that is exposed in embedded shells.
+@magics_class
+class EmbeddedMagics(Magics):
+
+ @line_magic
+ @magic_arguments.magic_arguments()
+ @magic_arguments.argument('-i', '--instance', action='store_true',
+ help='Kill instance instead of call location')
+ @magic_arguments.argument('-x', '--exit', action='store_true',
+ help='Also exit the current session')
+ @magic_arguments.argument('-y', '--yes', action='store_true',
+ help='Do not ask confirmation')
+ def kill_embedded(self, parameter_s=''):
+ """%kill_embedded : deactivate for good the current embedded IPython
+
+ This function (after asking for confirmation) sets an internal flag so
+ that an embedded IPython will never activate again for the given call
+ location. This is useful to permanently disable a shell that is being
+ called inside a loop: once you've figured out what you needed from it,
+ you may then kill it and the program will then continue to run without
+ the interactive shell interfering again.
+
+
+ Kill Instance Option:
+
+ If for some reasons you need to kill the location where the instance
+ is created and not called, for example if you create a single
+ instance in one place and debug in many locations, you can use the
+ ``--instance`` option to kill this specific instance. Like for the
+ ``call location`` killing an "instance" should work even if it is
+ recreated within a loop.
+
+ .. note::
+
+ This was the default behavior before IPython 5.2
+
+ """
+
+ args = magic_arguments.parse_argstring(self.kill_embedded, parameter_s)
+ print(args)
+ if args.instance:
+ # let no ask
+ if not args.yes:
+ kill = ask_yes_no(
+ "Are you sure you want to kill this embedded instance? [y/N] ", 'n')
+ else:
+ kill = True
+ if kill:
+ self.shell._disable_init_location()
+ print("This embedded IPython instance will not reactivate anymore "
+ "once you exit.")
+ else:
+ if not args.yes:
+ kill = ask_yes_no(
+ "Are you sure you want to kill this embedded call_location? [y/N] ", 'n')
+ else:
+ kill = True
+ if kill:
+ self.shell.embedded_active = False
+ print("This embedded IPython call location will not reactivate anymore "
+ "once you exit.")
+
+ if args.exit:
+ # Ask-exit does not really ask, it just set internals flags to exit
+ # on next loop.
+ self.shell.ask_exit()
+
+
+ @line_magic
+ def exit_raise(self, parameter_s=''):
+ """%exit_raise Make the current embedded kernel exit and raise and exception.
+
+ This function sets an internal flag so that an embedded IPython will
+ raise a `IPython.terminal.embed.KillEmbedded` Exception on exit, and then exit the current I. This is
+ useful to permanently exit a loop that create IPython embed instance.
+ """
+
+ self.shell.should_raise = True
+ self.shell.ask_exit()
+
+
+
+class InteractiveShellEmbed(TerminalInteractiveShell):
+
+ dummy_mode = Bool(False)
+ exit_msg = Unicode('')
+ embedded = CBool(True)
+ should_raise = CBool(False)
+ # Like the base class display_banner is not configurable, but here it
+ # is True by default.
+ 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):
+ 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):
+ if value:
+ InteractiveShellEmbed._inactive_locations.discard(
+ self._call_location_id)
+ InteractiveShellEmbed._inactive_locations.discard(
+ self._init_location_id)
+ 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(
+ "Key word argument `user_global_ns` has been replaced by `user_module` since IPython 4.0.")
+
+ clid = kw.pop('_init_location_id', None)
+ if not clid:
+ 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
+ # trapped
+ sys.excepthook = ultratb.FormattedTB(color_scheme=self.colors,
+ mode=self.xmode,
+ call_pdb=self.pdb)
+
+ def init_sys_modules(self):
+ """
+ Explicitly overwrite :mod:`IPython.core.interactiveshell` to do nothing.
+ """
+ pass
+
+ def init_magics(self):
+ super(InteractiveShellEmbed, self).init_magics()
+ self.register_magics(EmbeddedMagics)
+
+ def __call__(self, header='', local_ns=None, module=None, dummy=None,
+ stack_depth=1, global_ns=None, compile_flags=None, **kw):
+ """Activate the interactive interpreter.
+
+ __call__(self,header='',local_ns=None,module=None,dummy=None) -> Start
+ the interpreter shell with the given local and global namespaces, and
+ optionally print a header string at startup.
+
+ The shell can be globally activated/deactivated using the
+ dummy_mode attribute. This allows you to turn off a shell used
+ for debugging globally.
+
+ However, *each* time you call the shell you can override the current
+ state of dummy_mode with the optional keyword parameter 'dummy'. For
+ example, if you set dummy mode on with IPShell.dummy_mode = True, you
+ can still have a specific call work by making it as IPShell(dummy=False).
+ """
+
+ # we are called, set the underlying interactiveshell not to exit.
+ self.keep_running = True
+
+ # If the user has turned it off, go away
+ clid = kw.pop('_call_location_id', None)
+ if not clid:
+ frame = sys._getframe(1)
+ clid = '%s:%s' % (frame.f_code.co_filename, frame.f_lineno)
+ self._call_location_id = clid
+
+ if not self.embedded_active:
+ return
+
+ # Normal exits from interactive mode set this flag, so the shell can't
+ # re-enter (it checks this variable at the start of interactive mode).
+ self.exit_now = False
+
+ # Allow the dummy parameter to override the global __dummy_mode
+ if dummy or (dummy != 0 and self.dummy_mode):
+ return
+
+ # self.banner is auto computed
+ if header:
+ self.old_banner2 = self.banner2
+ self.banner2 = self.banner2 + '\n' + header + '\n'
+ else:
+ self.old_banner2 = ''
+
+ 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,
+ global_ns=global_ns, compile_flags=compile_flags)
+
+ self.banner2 = self.old_banner2
+
+ if self.exit_msg is not None:
+ print(self.exit_msg)
+
+ if self.should_raise:
+ raise KillEmbedded('Embedded IPython raising error, as user requested.')
+
+
+ def mainloop(self, local_ns=None, module=None, stack_depth=0,
+ display_banner=None, global_ns=None, compile_flags=None):
+ """Embeds IPython into a running python program.
+
+ Parameters
+ ----------
+
+ local_ns, module
+ Working local namespace (a dict) and module (a module or similar
+ object). If given as None, they are automatically taken from the scope
+ where the shell was called, so that program variables become visible.
+
+ stack_depth : int
+ How many levels in the stack to go to looking for namespaces (when
+ local_ns or module is None). This allows an intermediate caller to
+ make sure that this function gets the namespace from the intended
+ level in the stack. By default (0) it will get its locals and globals
+ from the immediate caller.
+
+ compile_flags
+ A bit field identifying the __future__ features
+ that are enabled, as passed to the builtin :func:`compile` function.
+ If given as None, they are automatically taken from the scope where
+ the shell was called.
+
+ """
+
+ 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.")
+
+ 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):
+ call_frame = sys._getframe(stack_depth).f_back
+
+ if local_ns is None:
+ 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
+ if compile_flags is None:
+ compile_flags = (call_frame.f_code.co_flags &
+ compilerop.PyCF_MASK)
+
+ # Save original namespace and module so we can restore them after
+ # embedding; otherwise the shell doesn't shut down correctly.
+ orig_user_module = self.user_module
+ orig_user_ns = self.user_ns
+ orig_compile_flags = self.compile.flags
+
+ # Update namespaces and fire up interpreter
+
+ # The global one is easy, we can just throw it in
+ if module is not None:
+ self.user_module = module
+
+ # But the user/local one is tricky: ipython needs it to store internal
+ # data, but we also need the locals. We'll throw our hidden variables
+ # like _ih and get_ipython() into the local namespace, but delete them
+ # later.
+ if local_ns is not None:
+ reentrant_local_ns = {k: v for (k, v) in local_ns.items() if k not in self.user_ns_hidden.keys()}
+ self.user_ns = reentrant_local_ns
+ self.init_user_ns()
+
+ # Compiler flags
+ if compile_flags is not None:
+ self.compile.flags = compile_flags
+
+ # make sure the tab-completer has the correct frame information, so it
+ # actually completes using the frame's locals/globals
+ self.set_completer_frame()
+
+ with self.builtin_trap, self.display_trap:
+ self.interact()
+
+ # now, purge out the local namespace of IPython's hidden variables.
+ if local_ns is not None:
+ local_ns.update({k: v for (k, v) in self.user_ns.items() if k not in self.user_ns_hidden.keys()})
+
+
+ # Restore original namespace so shell can shut down when we exit.
+ self.user_module = orig_user_module
+ self.user_ns = orig_user_ns
+ self.compile.flags = orig_compile_flags
+
+
+def embed(**kwargs):
+ """Call this to embed IPython at the current point in your program.
+
+ The first invocation of this will create an :class:`InteractiveShellEmbed`
+ instance and then call it. Consecutive calls just call the already
+ created instance.
+
+ If you don't want the kernel to initialize the namespace
+ from the scope of the surrounding function,
+ and/or you want to load full IPython configuration,
+ you probably want `IPython.start_ipython()` instead.
+
+ Here is a simple example::
+
+ from IPython import embed
+ a = 10
+ b = 20
+ embed(header='First time')
+ c = 30
+ d = 40
+ embed()
+
+ Full customization can be done by passing a :class:`Config` in as the
+ config argument.
+ """
+ config = kwargs.get('config')
+ header = kwargs.pop('header', u'')
+ compile_flags = kwargs.pop('compile_flags', None)
+ if config is None:
+ config = load_default_config()
+ config.InteractiveShellEmbed = config.TerminalInteractiveShell
+ kwargs['config'] = config
+ using = kwargs.get('using', 'sync')
+ if using :
+ kwargs['config'].update({'TerminalInteractiveShell':{'loop_runner':using, 'colors':'NoColor', 'autoawait': using!='sync'}})
+ #save ps1/ps2 if defined
+ ps1 = None
+ ps2 = None
+ try:
+ ps1 = sys.ps1
+ ps2 = sys.ps2
+ except AttributeError:
+ pass
+ #save previous instance
+ saved_shell_instance = InteractiveShell._instance
+ if saved_shell_instance is not None:
+ cls = type(saved_shell_instance)
+ cls.clear_instance()
+ 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,
+ _call_location_id='%s:%s' % (frame.f_code.co_filename, frame.f_lineno))
+ InteractiveShellEmbed.clear_instance()
+ #restore previous instance
+ if saved_shell_instance is not None:
+ cls = type(saved_shell_instance)
+ cls.clear_instance()
+ for subclass in cls._walk_mro():
+ subclass._instance = saved_shell_instance
+ if ps1 is not None:
+ sys.ps1 = ps1
+ sys.ps2 = ps2
diff --git a/contrib/python/ipython/py3/IPython/terminal/interactiveshell.py b/contrib/python/ipython/py3/IPython/terminal/interactiveshell.py
index f3b697b993..4e35aadd61 100644
--- a/contrib/python/ipython/py3/IPython/terminal/interactiveshell.py
+++ b/contrib/python/ipython/py3/IPython/terminal/interactiveshell.py
@@ -1,648 +1,648 @@
-"""IPython terminal interface using prompt_toolkit"""
-
-import asyncio
-import os
-import sys
-import warnings
-from warnings import warn
-
-from IPython.core.interactiveshell import InteractiveShell, InteractiveShellABC
-from IPython.utils import io
-from IPython.utils.py3compat import input
-from IPython.utils.terminal import toggle_set_term_title, set_term_title, restore_term_title
-from IPython.utils.process import abbrev_cwd
-from traitlets import (
- Bool, Unicode, Dict, Integer, observe, Instance, Type, default, Enum, Union,
- Any, validate
-)
-
-from prompt_toolkit.enums import DEFAULT_BUFFER, EditingMode
-from prompt_toolkit.filters import (HasFocus, Condition, IsDone)
-from prompt_toolkit.formatted_text import PygmentsTokens
-from prompt_toolkit.history import InMemoryHistory
-from prompt_toolkit.layout.processors import ConditionalProcessor, HighlightMatchingBracketProcessor
-from prompt_toolkit.output import ColorDepth
-from prompt_toolkit.patch_stdout import patch_stdout
-from prompt_toolkit.shortcuts import PromptSession, CompleteStyle, print_formatted_text
-from prompt_toolkit.styles import DynamicStyle, merge_styles
-from prompt_toolkit.styles.pygments import style_from_pygments_cls, style_from_pygments_dict
-from prompt_toolkit import __version__ as ptk_version
-
-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 .pt_inputhooks import get_inputhook_name_and_func
-from .prompts import Prompts, ClassicPrompts, RichPromptDisplayHook
-from .ptutils import IPythonPTCompleter, IPythonPTLexer
-from .shortcuts import create_ipython_shortcuts
-
-DISPLAY_BANNER_DEPRECATED = object()
-PTK3 = ptk_version.startswith('3.')
-
-
-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:
- return os.environ['EDITOR']
- except KeyError:
- pass
- except UnicodeError:
- warn("$EDITOR environment variable is not pure ASCII. Using platform "
- "default editor.")
-
- if os.name == 'posix':
- return 'vi' # the only one guaranteed to be there!
- 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
-
-
-_use_simple_prompt = ('IPY_TEST_SIMPLE_PROMPT' in os.environ) or (not _is_tty)
-
-def black_reformat_handler(text_before_cursor):
- import black
- formatted_text = black.format_str(text_before_cursor, mode=black.FileMode())
- if not text_before_cursor.endswith('\n') and formatted_text.endswith('\n'):
- formatted_text = formatted_text[:-1]
- return formatted_text
-
-
-class TerminalInteractiveShell(InteractiveShell):
- mime_renderers = Dict().tag(config=True)
-
- space_for_menu = Integer(6, help='Number of line at the bottom of the screen '
- 'to reserve for the tab completion menu, '
- 'search history, ...etc, the height of '
- 'these menus will at most this value. '
- 'Increase it is you prefer long and skinny '
- 'menus, decrease for short and wide.'
- ).tag(config=True)
-
- pt_app = None
- debugger_history = None
-
- 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.
-
- 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)
-
- @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)
-
- editing_mode = Unicode('emacs',
- help="Shortcut style to use at the prompt. 'vi' or 'emacs'.",
- ).tag(config=True)
-
- autoformatter = Unicode(None,
- help="Autoformatter to reformat Terminal code. Can be `'black'` or `None`",
- allow_none=True
- ).tag(config=True)
-
- mouse_support = Bool(False,
- help="Enable mouse support in the prompt\n(Note: prevents selecting text with the mouse)"
- ).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)
-
- @validate('editing_mode')
- def _validate_editing_mode(self, proposal):
- if proposal['value'].lower() == 'vim':
- proposal['value']= 'vi'
- elif proposal['value'].lower() == 'default':
- proposal['value']= 'emacs'
-
- if hasattr(EditingMode, proposal['value'].upper()):
- return proposal['value'].lower()
-
- return self.editing_mode
-
-
- @observe('editing_mode')
- def _editing_mode(self, change):
- if self.pt_app:
- self.pt_app.editing_mode = getattr(EditingMode, change.new.upper())
-
- @observe('autoformatter')
- def _autoformatter_changed(self, change):
- formatter = change.new
- if formatter is None:
- self.reformat_handler = lambda x:x
- elif formatter == 'black':
- self.reformat_handler = black_reformat_handler
- else:
- raise ValueError
-
- @observe('highlighting_style')
- @observe('colors')
- def _highlighting_style_changed(self, change):
- self.refresh_style()
-
- 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)
-
- 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)
-
- prompts_class = Type(Prompts, help='Class used to generate Prompt token for prompt_toolkit').tag(config=True)
-
- prompts = Instance(Prompts)
-
- @default('prompts')
- def _prompts_default(self):
- return self.prompts_class(self)
-
-# @observe('prompts')
-# def _(self, change):
-# self._update_layout()
-
- @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_format = Unicode("IPython: {cwd}",
- help="Customize the terminal title format. This is a python format string. " +
- "Available substitutions are: {cwd}."
- ).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)
-
- highlight_matching_brackets = Bool(True,
- help="Highlight matching brackets.",
- ).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)
-
- handle_return = Any(None,
- help="Provide an alternative handler to be called when the user presses "
- "Return. This is an advanced option intended for debugging, which "
- "may be changed or removed in later releases."
- ).tag(config=True)
-
- enable_history_search = Bool(True,
- help="Allows to enable/disable the prompt toolkit history search"
- ).tag(config=True)
-
- prompt_includes_vi_mode = Bool(True,
- help="Display the current vi mode (when using vi editing mode)."
- ).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(self.term_title_format.format(cwd=abbrev_cwd()))
- else:
- toggle_set_term_title(False)
-
- def restore_term_title(self):
- if self.term_title:
- restore_term_title()
-
- 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.
- def prompt():
- prompt_text = "".join(x[1] for x in self.prompts.in_prompt_tokens())
- lines = [input(prompt_text)]
- prompt_continuation = "".join(x[1] for x in self.prompts.continuation_prompt_tokens())
- while self.check_complete('\n'.join(lines))[0] == 'incomplete':
- lines.append( input(prompt_continuation) )
- return '\n'.join(lines)
- self.prompt_for_code = prompt
- return
-
- # Set up keyboard shortcuts
- key_bindings = create_ipython_shortcuts(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_string(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())
-
- self.pt_loop = asyncio.new_event_loop()
- self.pt_app = PromptSession(
- editing_mode=editing_mode,
- key_bindings=key_bindings,
- history=history,
- completer=IPythonPTCompleter(shell=self),
- enable_history_search = self.enable_history_search,
- style=self.style,
- include_default_pygments_style=False,
- mouse_support=self.mouse_support,
- enable_open_in_editor=self.extra_open_editor_shortcuts,
- color_depth=self.color_depth,
- tempfile_suffix=".py",
- **self._extra_prompt_options())
-
- def _make_style_from_name_or_cls(self, name_or_cls):
- """
- Small wrapper that make an IPython compatible style from a style name
-
- We need that to add style for prompt ... etc.
- """
- 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.Name.Variable.Magic: '#ansiblue',
- Token.Prompt: '#009900',
- Token.PromptNum: '#ansibrightgreen bold',
- Token.OutPrompt: '#990000',
- Token.OutPromptNum: '#ansibrightred bold',
- })
-
- # Hack: Due to limited color support on the Windows console
- # the prompt colors will be wrong without this
- if os.name == 'nt':
- style_overrides.update({
- Token.Prompt: '#ansidarkgreen',
- Token.PromptNum: '#ansigreen bold',
- Token.OutPrompt: '#ansidarkred',
- Token.OutPromptNum: '#ansired bold',
- })
- elif legacy =='nocolor':
- style_cls=_NoStyle
- style_overrides = {}
- else :
- raise ValueError('Got unknown colors: ', legacy)
- else :
- if isinstance(name_or_cls, str):
- style_cls = get_style_by_name(name_or_cls)
- else:
- style_cls = name_or_cls
- style_overrides = {
- Token.Prompt: '#009900',
- Token.PromptNum: '#ansibrightgreen bold',
- Token.OutPrompt: '#990000',
- Token.OutPromptNum: '#ansibrightred bold',
- }
- style_overrides.update(self.highlighting_style_overrides)
- style = merge_styles([
- style_from_pygments_cls(style_cls),
- style_from_pygments_dict(style_overrides),
- ])
-
- return style
-
- @property
- def pt_complete_style(self):
- return {
- 'multicolumn': CompleteStyle.MULTI_COLUMN,
- 'column': CompleteStyle.COLUMN,
- 'readlinelike': CompleteStyle.READLINE_LIKE,
- }[self.display_completions]
-
- @property
- def color_depth(self):
- return (ColorDepth.TRUE_COLOR if self.true_color else None)
-
- def _extra_prompt_options(self):
- """
- Return the current layout option for the current Terminal InteractiveShell
- """
- def get_message():
- return PygmentsTokens(self.prompts.in_prompt_tokens())
-
- if self.editing_mode == 'emacs':
- # with emacs mode the prompt is (usually) static, so we call only
- # the function once. With VI mode it can toggle between [ins] and
- # [nor] so we can't precompute.
- # here I'm going to favor the default keybinding which almost
- # everybody uses to decrease CPU usage.
- # if we have issues with users with custom Prompts we can see how to
- # work around this.
- get_message = get_message()
-
- options = {
- 'complete_in_thread': False,
- 'lexer':IPythonPTLexer(),
- 'reserve_space_for_menu':self.space_for_menu,
- 'message': get_message,
- 'prompt_continuation': (
- lambda width, lineno, is_soft_wrap:
- PygmentsTokens(self.prompts.continuation_prompt_tokens(width))),
- 'multiline': True,
- 'complete_style': self.pt_complete_style,
-
- # Highlight matching brackets, but only when this setting is
- # enabled, and only when the DEFAULT_BUFFER has the focus.
- 'input_processors': [ConditionalProcessor(
- processor=HighlightMatchingBracketProcessor(chars='[](){}'),
- filter=HasFocus(DEFAULT_BUFFER) & ~IsDone() &
- Condition(lambda: self.highlight_matching_brackets))],
- }
- if not PTK3:
- options['inputhook'] = self.inputhook
-
- return options
-
- def prompt_for_code(self):
- if self.rl_next_input:
- default = self.rl_next_input
- self.rl_next_input = None
- else:
- default = ''
-
- # In order to make sure that asyncio code written in the
- # interactive shell doesn't interfere with the prompt, we run the
- # prompt in a different event loop.
- # If we don't do this, people could spawn coroutine with a
- # while/true inside which will freeze the prompt.
-
- policy = asyncio.get_event_loop_policy()
- try:
- old_loop = policy.get_event_loop()
- except RuntimeError:
- # This happens when the the event loop is closed,
- # e.g. by calling `asyncio.run()`.
- old_loop = None
-
- policy.set_event_loop(self.pt_loop)
- try:
- with patch_stdout(raw=True):
- text = self.pt_app.prompt(
- default=default,
- **self._extra_prompt_options())
- finally:
- # Restore the original event loop.
- if old_loop is not None:
- policy.set_event_loop(old_loop)
-
- return text
-
- def enable_win_unicode_console(self):
- # Since IPython 7.10 doesn't support python < 3.6 and PEP 528, Python uses the unicode APIs for the Windows
- # console by default, so WUC shouldn't be needed.
- from warnings import warn
- warn("`enable_win_unicode_console` is deprecated since IPython 7.10, does not do anything and will be removed in the future",
- DeprecationWarning,
- stacklevel=2)
-
- def init_io(self):
- if sys.platform not in {'win32', 'cli'}:
- return
-
- 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)
-
- 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
- # frontend.
- super(TerminalInteractiveShell, self).init_alias()
-
- # Now define aliases that only make sense on the terminal, because they
- # need direct access to the console in a way that we can't emulate in
- # GUI or web frontend
- if os.name == 'posix':
- 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
-
- self.debugger_history = InMemoryHistory()
-
- def ask_exit(self):
- self.keep_running = False
-
- rl_next_input = None
-
- 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)
-
- 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()
-
- 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:
- try:
- self.interact()
- break
- except KeyboardInterrupt as e:
- print("\n%s escaped interact()\n" % type(e).__name__)
- finally:
- # An interrupt during the eventloop will mess up the
- # internal state of the prompt_toolkit library.
- # Stopping the eventloop fixes this, see
- # https://github.com/ipython/ipython/pull/9867
- if hasattr(self, '_eventloop'):
- self._eventloop.stop()
-
- self.restore_term_title()
-
-
- _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 and (gui != 'inline') :
- self.active_eventloop, self._inputhook =\
- get_inputhook_name_and_func(gui)
- else:
- self.active_eventloop = self._inputhook = None
-
- # For prompt_toolkit 3.0. We have to create an asyncio event loop with
- # this inputhook.
- if PTK3:
- import asyncio
- from prompt_toolkit.eventloop import new_eventloop_with_inputhook
-
- if gui == 'asyncio':
- # When we integrate the asyncio event loop, run the UI in the
- # same event loop as the rest of the code. don't use an actual
- # input hook. (Asyncio is not made for nesting event loops.)
- self.pt_loop = asyncio.get_event_loop()
-
- elif self._inputhook:
- # If an inputhook was set, create a new asyncio event loop with
- # this inputhook for the prompt.
- self.pt_loop = new_eventloop_with_inputhook(self._inputhook)
- else:
- # When there's no inputhook, run the prompt in a separate
- # asyncio event loop.
- self.pt_loop = asyncio.new_event_loop()
-
- # 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
-
- tokens = self.prompts.rewrite_prompt_tokens()
- if self.pt_app:
- print_formatted_text(PygmentsTokens(tokens), end='',
- style=self.pt_app.app.style)
- print(cmd)
- else:
- 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()
-
-
-InteractiveShellABC.register(TerminalInteractiveShell)
-
-if __name__ == '__main__':
- TerminalInteractiveShell.instance().interact()
+"""IPython terminal interface using prompt_toolkit"""
+
+import asyncio
+import os
+import sys
+import warnings
+from warnings import warn
+
+from IPython.core.interactiveshell import InteractiveShell, InteractiveShellABC
+from IPython.utils import io
+from IPython.utils.py3compat import input
+from IPython.utils.terminal import toggle_set_term_title, set_term_title, restore_term_title
+from IPython.utils.process import abbrev_cwd
+from traitlets import (
+ Bool, Unicode, Dict, Integer, observe, Instance, Type, default, Enum, Union,
+ Any, validate
+)
+
+from prompt_toolkit.enums import DEFAULT_BUFFER, EditingMode
+from prompt_toolkit.filters import (HasFocus, Condition, IsDone)
+from prompt_toolkit.formatted_text import PygmentsTokens
+from prompt_toolkit.history import InMemoryHistory
+from prompt_toolkit.layout.processors import ConditionalProcessor, HighlightMatchingBracketProcessor
+from prompt_toolkit.output import ColorDepth
+from prompt_toolkit.patch_stdout import patch_stdout
+from prompt_toolkit.shortcuts import PromptSession, CompleteStyle, print_formatted_text
+from prompt_toolkit.styles import DynamicStyle, merge_styles
+from prompt_toolkit.styles.pygments import style_from_pygments_cls, style_from_pygments_dict
+from prompt_toolkit import __version__ as ptk_version
+
+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 .pt_inputhooks import get_inputhook_name_and_func
+from .prompts import Prompts, ClassicPrompts, RichPromptDisplayHook
+from .ptutils import IPythonPTCompleter, IPythonPTLexer
+from .shortcuts import create_ipython_shortcuts
+
+DISPLAY_BANNER_DEPRECATED = object()
+PTK3 = ptk_version.startswith('3.')
+
+
+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:
+ return os.environ['EDITOR']
+ except KeyError:
+ pass
+ except UnicodeError:
+ warn("$EDITOR environment variable is not pure ASCII. Using platform "
+ "default editor.")
+
+ if os.name == 'posix':
+ return 'vi' # the only one guaranteed to be there!
+ 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
+
+
+_use_simple_prompt = ('IPY_TEST_SIMPLE_PROMPT' in os.environ) or (not _is_tty)
+
+def black_reformat_handler(text_before_cursor):
+ import black
+ formatted_text = black.format_str(text_before_cursor, mode=black.FileMode())
+ if not text_before_cursor.endswith('\n') and formatted_text.endswith('\n'):
+ formatted_text = formatted_text[:-1]
+ return formatted_text
+
+
+class TerminalInteractiveShell(InteractiveShell):
+ mime_renderers = Dict().tag(config=True)
+
+ space_for_menu = Integer(6, help='Number of line at the bottom of the screen '
+ 'to reserve for the tab completion menu, '
+ 'search history, ...etc, the height of '
+ 'these menus will at most this value. '
+ 'Increase it is you prefer long and skinny '
+ 'menus, decrease for short and wide.'
+ ).tag(config=True)
+
+ pt_app = None
+ debugger_history = None
+
+ 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.
+
+ 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)
+
+ @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)
+
+ editing_mode = Unicode('emacs',
+ help="Shortcut style to use at the prompt. 'vi' or 'emacs'.",
+ ).tag(config=True)
+
+ autoformatter = Unicode(None,
+ help="Autoformatter to reformat Terminal code. Can be `'black'` or `None`",
+ allow_none=True
+ ).tag(config=True)
+
+ mouse_support = Bool(False,
+ help="Enable mouse support in the prompt\n(Note: prevents selecting text with the mouse)"
+ ).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)
+
+ @validate('editing_mode')
+ def _validate_editing_mode(self, proposal):
+ if proposal['value'].lower() == 'vim':
+ proposal['value']= 'vi'
+ elif proposal['value'].lower() == 'default':
+ proposal['value']= 'emacs'
+
+ if hasattr(EditingMode, proposal['value'].upper()):
+ return proposal['value'].lower()
+
+ return self.editing_mode
+
+
+ @observe('editing_mode')
+ def _editing_mode(self, change):
+ if self.pt_app:
+ self.pt_app.editing_mode = getattr(EditingMode, change.new.upper())
+
+ @observe('autoformatter')
+ def _autoformatter_changed(self, change):
+ formatter = change.new
+ if formatter is None:
+ self.reformat_handler = lambda x:x
+ elif formatter == 'black':
+ self.reformat_handler = black_reformat_handler
+ else:
+ raise ValueError
+
+ @observe('highlighting_style')
+ @observe('colors')
+ def _highlighting_style_changed(self, change):
+ self.refresh_style()
+
+ 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)
+
+ 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)
+
+ prompts_class = Type(Prompts, help='Class used to generate Prompt token for prompt_toolkit').tag(config=True)
+
+ prompts = Instance(Prompts)
+
+ @default('prompts')
+ def _prompts_default(self):
+ return self.prompts_class(self)
+
+# @observe('prompts')
+# def _(self, change):
+# self._update_layout()
+
+ @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_format = Unicode("IPython: {cwd}",
+ help="Customize the terminal title format. This is a python format string. " +
+ "Available substitutions are: {cwd}."
+ ).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)
+
+ highlight_matching_brackets = Bool(True,
+ help="Highlight matching brackets.",
+ ).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)
+
+ handle_return = Any(None,
+ help="Provide an alternative handler to be called when the user presses "
+ "Return. This is an advanced option intended for debugging, which "
+ "may be changed or removed in later releases."
+ ).tag(config=True)
+
+ enable_history_search = Bool(True,
+ help="Allows to enable/disable the prompt toolkit history search"
+ ).tag(config=True)
+
+ prompt_includes_vi_mode = Bool(True,
+ help="Display the current vi mode (when using vi editing mode)."
+ ).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(self.term_title_format.format(cwd=abbrev_cwd()))
+ else:
+ toggle_set_term_title(False)
+
+ def restore_term_title(self):
+ if self.term_title:
+ restore_term_title()
+
+ 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.
+ def prompt():
+ prompt_text = "".join(x[1] for x in self.prompts.in_prompt_tokens())
+ lines = [input(prompt_text)]
+ prompt_continuation = "".join(x[1] for x in self.prompts.continuation_prompt_tokens())
+ while self.check_complete('\n'.join(lines))[0] == 'incomplete':
+ lines.append( input(prompt_continuation) )
+ return '\n'.join(lines)
+ self.prompt_for_code = prompt
+ return
+
+ # Set up keyboard shortcuts
+ key_bindings = create_ipython_shortcuts(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_string(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())
+
+ self.pt_loop = asyncio.new_event_loop()
+ self.pt_app = PromptSession(
+ editing_mode=editing_mode,
+ key_bindings=key_bindings,
+ history=history,
+ completer=IPythonPTCompleter(shell=self),
+ enable_history_search = self.enable_history_search,
+ style=self.style,
+ include_default_pygments_style=False,
+ mouse_support=self.mouse_support,
+ enable_open_in_editor=self.extra_open_editor_shortcuts,
+ color_depth=self.color_depth,
+ tempfile_suffix=".py",
+ **self._extra_prompt_options())
+
+ def _make_style_from_name_or_cls(self, name_or_cls):
+ """
+ Small wrapper that make an IPython compatible style from a style name
+
+ We need that to add style for prompt ... etc.
+ """
+ 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.Name.Variable.Magic: '#ansiblue',
+ Token.Prompt: '#009900',
+ Token.PromptNum: '#ansibrightgreen bold',
+ Token.OutPrompt: '#990000',
+ Token.OutPromptNum: '#ansibrightred bold',
+ })
+
+ # Hack: Due to limited color support on the Windows console
+ # the prompt colors will be wrong without this
+ if os.name == 'nt':
+ style_overrides.update({
+ Token.Prompt: '#ansidarkgreen',
+ Token.PromptNum: '#ansigreen bold',
+ Token.OutPrompt: '#ansidarkred',
+ Token.OutPromptNum: '#ansired bold',
+ })
+ elif legacy =='nocolor':
+ style_cls=_NoStyle
+ style_overrides = {}
+ else :
+ raise ValueError('Got unknown colors: ', legacy)
+ else :
+ if isinstance(name_or_cls, str):
+ style_cls = get_style_by_name(name_or_cls)
+ else:
+ style_cls = name_or_cls
+ style_overrides = {
+ Token.Prompt: '#009900',
+ Token.PromptNum: '#ansibrightgreen bold',
+ Token.OutPrompt: '#990000',
+ Token.OutPromptNum: '#ansibrightred bold',
+ }
+ style_overrides.update(self.highlighting_style_overrides)
+ style = merge_styles([
+ style_from_pygments_cls(style_cls),
+ style_from_pygments_dict(style_overrides),
+ ])
+
+ return style
+
+ @property
+ def pt_complete_style(self):
+ return {
+ 'multicolumn': CompleteStyle.MULTI_COLUMN,
+ 'column': CompleteStyle.COLUMN,
+ 'readlinelike': CompleteStyle.READLINE_LIKE,
+ }[self.display_completions]
+
+ @property
+ def color_depth(self):
+ return (ColorDepth.TRUE_COLOR if self.true_color else None)
+
+ def _extra_prompt_options(self):
+ """
+ Return the current layout option for the current Terminal InteractiveShell
+ """
+ def get_message():
+ return PygmentsTokens(self.prompts.in_prompt_tokens())
+
+ if self.editing_mode == 'emacs':
+ # with emacs mode the prompt is (usually) static, so we call only
+ # the function once. With VI mode it can toggle between [ins] and
+ # [nor] so we can't precompute.
+ # here I'm going to favor the default keybinding which almost
+ # everybody uses to decrease CPU usage.
+ # if we have issues with users with custom Prompts we can see how to
+ # work around this.
+ get_message = get_message()
+
+ options = {
+ 'complete_in_thread': False,
+ 'lexer':IPythonPTLexer(),
+ 'reserve_space_for_menu':self.space_for_menu,
+ 'message': get_message,
+ 'prompt_continuation': (
+ lambda width, lineno, is_soft_wrap:
+ PygmentsTokens(self.prompts.continuation_prompt_tokens(width))),
+ 'multiline': True,
+ 'complete_style': self.pt_complete_style,
+
+ # Highlight matching brackets, but only when this setting is
+ # enabled, and only when the DEFAULT_BUFFER has the focus.
+ 'input_processors': [ConditionalProcessor(
+ processor=HighlightMatchingBracketProcessor(chars='[](){}'),
+ filter=HasFocus(DEFAULT_BUFFER) & ~IsDone() &
+ Condition(lambda: self.highlight_matching_brackets))],
+ }
+ if not PTK3:
+ options['inputhook'] = self.inputhook
+
+ return options
+
+ def prompt_for_code(self):
+ if self.rl_next_input:
+ default = self.rl_next_input
+ self.rl_next_input = None
+ else:
+ default = ''
+
+ # In order to make sure that asyncio code written in the
+ # interactive shell doesn't interfere with the prompt, we run the
+ # prompt in a different event loop.
+ # If we don't do this, people could spawn coroutine with a
+ # while/true inside which will freeze the prompt.
+
+ policy = asyncio.get_event_loop_policy()
+ try:
+ old_loop = policy.get_event_loop()
+ except RuntimeError:
+ # This happens when the the event loop is closed,
+ # e.g. by calling `asyncio.run()`.
+ old_loop = None
+
+ policy.set_event_loop(self.pt_loop)
+ try:
+ with patch_stdout(raw=True):
+ text = self.pt_app.prompt(
+ default=default,
+ **self._extra_prompt_options())
+ finally:
+ # Restore the original event loop.
+ if old_loop is not None:
+ policy.set_event_loop(old_loop)
+
+ return text
+
+ def enable_win_unicode_console(self):
+ # Since IPython 7.10 doesn't support python < 3.6 and PEP 528, Python uses the unicode APIs for the Windows
+ # console by default, so WUC shouldn't be needed.
+ from warnings import warn
+ warn("`enable_win_unicode_console` is deprecated since IPython 7.10, does not do anything and will be removed in the future",
+ DeprecationWarning,
+ stacklevel=2)
+
+ def init_io(self):
+ if sys.platform not in {'win32', 'cli'}:
+ return
+
+ 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)
+
+ 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
+ # frontend.
+ super(TerminalInteractiveShell, self).init_alias()
+
+ # Now define aliases that only make sense on the terminal, because they
+ # need direct access to the console in a way that we can't emulate in
+ # GUI or web frontend
+ if os.name == 'posix':
+ 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
+
+ self.debugger_history = InMemoryHistory()
+
+ def ask_exit(self):
+ self.keep_running = False
+
+ rl_next_input = None
+
+ 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)
+
+ 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()
+
+ 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:
+ try:
+ self.interact()
+ break
+ except KeyboardInterrupt as e:
+ print("\n%s escaped interact()\n" % type(e).__name__)
+ finally:
+ # An interrupt during the eventloop will mess up the
+ # internal state of the prompt_toolkit library.
+ # Stopping the eventloop fixes this, see
+ # https://github.com/ipython/ipython/pull/9867
+ if hasattr(self, '_eventloop'):
+ self._eventloop.stop()
+
+ self.restore_term_title()
+
+
+ _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 and (gui != 'inline') :
+ self.active_eventloop, self._inputhook =\
+ get_inputhook_name_and_func(gui)
+ else:
+ self.active_eventloop = self._inputhook = None
+
+ # For prompt_toolkit 3.0. We have to create an asyncio event loop with
+ # this inputhook.
+ if PTK3:
+ import asyncio
+ from prompt_toolkit.eventloop import new_eventloop_with_inputhook
+
+ if gui == 'asyncio':
+ # When we integrate the asyncio event loop, run the UI in the
+ # same event loop as the rest of the code. don't use an actual
+ # input hook. (Asyncio is not made for nesting event loops.)
+ self.pt_loop = asyncio.get_event_loop()
+
+ elif self._inputhook:
+ # If an inputhook was set, create a new asyncio event loop with
+ # this inputhook for the prompt.
+ self.pt_loop = new_eventloop_with_inputhook(self._inputhook)
+ else:
+ # When there's no inputhook, run the prompt in a separate
+ # asyncio event loop.
+ self.pt_loop = asyncio.new_event_loop()
+
+ # 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
+
+ tokens = self.prompts.rewrite_prompt_tokens()
+ if self.pt_app:
+ print_formatted_text(PygmentsTokens(tokens), end='',
+ style=self.pt_app.app.style)
+ print(cmd)
+ else:
+ 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()
+
+
+InteractiveShellABC.register(TerminalInteractiveShell)
+
+if __name__ == '__main__':
+ TerminalInteractiveShell.instance().interact()
diff --git a/contrib/python/ipython/py3/IPython/terminal/ipapp.py b/contrib/python/ipython/py3/IPython/terminal/ipapp.py
index 180cec1158..defe3e79fa 100644
--- a/contrib/python/ipython/py3/IPython/terminal/ipapp.py
+++ b/contrib/python/ipython/py3/IPython/terminal/ipapp.py
@@ -1,380 +1,380 @@
-#!/usr/bin/env python
-# encoding: utf-8
-"""
-The :class:`~IPython.core.application.Application` object for the command
-line :command:`ipython` program.
-"""
-
-# Copyright (c) IPython Development Team.
-# Distributed under the terms of the Modified BSD License.
-
-
-import logging
-import os
-import sys
-import warnings
-
-from traitlets.config.loader import Config
-from traitlets.config.application import boolean_flag, catch_config_error
-from IPython.core import release
-from IPython.core import usage
-from IPython.core.completer import IPCompleter
-from IPython.core.crashhandler import CrashHandler
-from IPython.core.formatters import PlainTextFormatter
-from IPython.core.history import HistoryManager
-from IPython.core.application import (
- ProfileDir, BaseIPythonApplication, base_flags, base_aliases
-)
-from IPython.core.magics import (
- ScriptMagics, LoggingMagics
-)
-from IPython.core.shellapp import (
- InteractiveShellApp, shell_flags, shell_aliases
-)
-from IPython.extensions.storemagic import StoreMagics
-from .interactiveshell import TerminalInteractiveShell
-from IPython.paths import get_ipython_dir
-from traitlets import (
- Bool, List, default, observe, Type
-)
-
-#-----------------------------------------------------------------------------
-# Globals, utilities and helpers
-#-----------------------------------------------------------------------------
-
-_examples = """
-ipython --matplotlib # enable matplotlib integration
-ipython --matplotlib=qt # enable matplotlib integration with qt4 backend
-
-ipython --log-level=DEBUG # set logging to DEBUG
-ipython --profile=foo # start with profile foo
-
-ipython profile create foo # create profile foo w/ default config files
-ipython help profile # show the help for the profile subcmd
-
-ipython locate # print the path to the IPython directory
-ipython locate profile foo # print the path to the directory for profile `foo`
-"""
-
-#-----------------------------------------------------------------------------
-# Crash handler for this application
-#-----------------------------------------------------------------------------
-
-class IPAppCrashHandler(CrashHandler):
- """sys.excepthook for IPython itself, leaves a detailed report on disk."""
-
- def __init__(self, app):
- contact_name = release.author
- contact_email = release.author_email
- bug_tracker = 'https://github.com/ipython/ipython/issues'
- super(IPAppCrashHandler,self).__init__(
- app, contact_name, contact_email, bug_tracker
- )
-
- def make_report(self,traceback):
- """Return a string containing a crash report."""
-
- sec_sep = self.section_sep
- # Start with parent report
- report = [super(IPAppCrashHandler, self).make_report(traceback)]
- # Add interactive-specific info we may have
- rpt_add = report.append
- try:
- rpt_add(sec_sep+"History of session input:")
- for line in self.app.shell.user_ns['_ih']:
- rpt_add(line)
- rpt_add('\n*** Last line of input (may not be in above history):\n')
- rpt_add(self.app.shell._last_input_line+'\n')
- except:
- pass
-
- return ''.join(report)
-
-#-----------------------------------------------------------------------------
-# Aliases and Flags
-#-----------------------------------------------------------------------------
-flags = dict(base_flags)
-flags.update(shell_flags)
-frontend_flags = {}
-addflag = lambda *args: frontend_flags.update(boolean_flag(*args))
-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('banner', 'TerminalIPythonApp.display_banner',
- "Display a banner upon starting IPython.",
- "Don't display a banner upon starting IPython."
-)
-addflag('confirm-exit', 'TerminalInteractiveShell.confirm_exit',
- """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.""",
- "Don't prompt the user when exiting."
-)
-addflag('term-title', 'TerminalInteractiveShell.term_title',
- "Enable auto setting the terminal title.",
- "Disable auto setting the terminal 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.InteractiveShell.separate_in = ''
-classic_config.InteractiveShell.separate_out = ''
-classic_config.InteractiveShell.separate_out2 = ''
-classic_config.InteractiveShell.colors = 'NoColor'
-classic_config.InteractiveShell.xmode = 'Plain'
-
-frontend_flags['classic']=(
- classic_config,
- "Gives IPython a similar feel to the classic Python prompt."
-)
-# # log doesn't make so much sense this way anymore
-# paa('--log','-l',
-# action='store_true', dest='InteractiveShell.logstart',
-# help="Start logging to the default log file (./ipython_log.py).")
-#
-# # quick is harder to implement
-frontend_flags['quick']=(
- {'TerminalIPythonApp' : {'quick' : True}},
- "Enable quick startup with no config files."
-)
-
-frontend_flags['i'] = (
- {'TerminalIPythonApp' : {'force_interact' : True}},
- """If running code from the command line, become interactive afterwards.
- It is often useful to follow this with `--` to treat remaining flags as
- script arguments.
- """
-)
-flags.update(frontend_flags)
-
-aliases = dict(base_aliases)
-aliases.update(shell_aliases)
-
-#-----------------------------------------------------------------------------
-# Main classes and functions
-#-----------------------------------------------------------------------------
-
-
-class LocateIPythonApp(BaseIPythonApplication):
- description = """print the path to the IPython dir"""
- subcommands = dict(
- profile=('IPython.core.profileapp.ProfileLocate',
- "print the path to an IPython profile directory",
- ),
- )
- def start(self):
- if self.subapp is not None:
- return self.subapp.start()
- else:
- print(self.ipython_dir)
-
-
-class TerminalIPythonApp(BaseIPythonApplication, InteractiveShellApp):
- name = u'ipython'
- description = usage.cl_usage
- crash_handler_class = IPAppCrashHandler
- examples = _examples
-
- flags = flags
- aliases = aliases
- classes = List()
-
- interactive_shell_class = Type(
- klass=object, # use default_value otherwise which only allow subclasses.
- default_value=TerminalInteractiveShell,
- help="Class to use to instantiate the TerminalInteractiveShell object. Useful for custom Frontends"
- ).tag(config=True)
-
- @default('classes')
- def _classes_default(self):
- """This has to be in a method, for TerminalIPythonApp to be available."""
- return [
- InteractiveShellApp, # ShellApp comes before TerminalApp, because
- self.__class__, # it will also affect subclasses (e.g. QtConsole)
- TerminalInteractiveShell,
- HistoryManager,
- ProfileDir,
- PlainTextFormatter,
- IPCompleter,
- ScriptMagics,
- LoggingMagics,
- StoreMagics,
- ]
-
- deprecated_subcommands = dict(
- qtconsole=('qtconsole.qtconsoleapp.JupyterQtConsoleApp',
- """DEPRECATED, Will be removed in IPython 6.0 : Launch the Jupyter Qt Console."""
- ),
- notebook=('notebook.notebookapp.NotebookApp',
- """DEPRECATED, Will be removed in IPython 6.0 : Launch the Jupyter HTML Notebook Server."""
- ),
- console=('jupyter_console.app.ZMQTerminalIPythonApp',
- """DEPRECATED, Will be removed in IPython 6.0 : Launch the Jupyter terminal-based Console."""
- ),
- nbconvert=('nbconvert.nbconvertapp.NbConvertApp',
- "DEPRECATED, Will be removed in IPython 6.0 : Convert notebooks to/from other formats."
- ),
- trust=('nbformat.sign.TrustNotebookApp',
- "DEPRECATED, Will be removed in IPython 6.0 : Sign notebooks to trust their potentially unsafe contents at load."
- ),
- kernelspec=('jupyter_client.kernelspecapp.KernelSpecApp',
- "DEPRECATED, Will be removed in IPython 6.0 : Manage Jupyter kernel specifications."
- ),
- )
- subcommands = dict(
- profile = ("IPython.core.profileapp.ProfileApp",
- "Create and manage IPython profiles."
- ),
- kernel = ("ipykernel.kernelapp.IPKernelApp",
- "Start a kernel without an attached frontend."
- ),
- locate=('IPython.terminal.ipapp.LocateIPythonApp',
- LocateIPythonApp.description
- ),
- history=('IPython.core.historyapp.HistoryApp',
- "Manage the IPython history database."
- ),
- )
- deprecated_subcommands['install-nbextension'] = (
- "notebook.nbextensions.InstallNBExtensionApp",
- "DEPRECATED, Will be removed in IPython 6.0 : Install Jupyter notebook extension files"
- )
- subcommands.update(deprecated_subcommands)
-
- # *do* autocreate requested profile, but don't create the config file.
- auto_create=Bool(True)
- # configurables
- 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']:
- self.load_config_file = lambda *a, **kw: None
-
- display_banner = Bool(True,
- help="Whether to display a banner upon starting IPython."
- ).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,
- 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']:
- self.interact = True
-
- @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:
- self.interact = False
-
- # internal, not-configurable
- something_to_run=Bool(False)
-
- def parse_command_line(self, argv=None):
- """override to allow old '-pylab' flag with deprecation warning"""
-
- argv = sys.argv[1:] if argv is None else argv
-
- if '-pylab' in argv:
- # deprecated `-pylab` given,
- # warn and transform into current syntax
- argv = argv[:] # copy, don't clobber
- idx = argv.index('-pylab')
- warnings.warn("`-pylab` flag has been deprecated.\n"
- " Use `--matplotlib <backend>` and import pylab manually.")
- argv[idx] = '--pylab'
-
- return super(TerminalIPythonApp, self).parse_command_line(argv)
-
- @catch_config_error
- def initialize(self, argv=None):
- """Do actions after construct, but before starting the app."""
- super(TerminalIPythonApp, self).initialize(argv)
- if self.subapp is not None:
- # don't bother initializing further, starting subapp
- return
- # print self.extra_args
- if self.extra_args and not self.something_to_run:
- self.file_to_run = self.extra_args[0]
- self.init_path()
- # create the shell
- self.init_shell()
- # and draw the banner
- self.init_banner()
- # Now a variety of things that happen after the banner is printed.
- self.init_gui_pylab()
- self.init_extensions()
- self.init_code()
-
- def init_shell(self):
- """initialize the InteractiveShell instance"""
- # Create an InteractiveShell instance.
- # shell.display_banner should always be False for the terminal
- # 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,
- ipython_dir=self.ipython_dir, user_ns=self.user_ns)
- self.shell.configurables.append(self)
-
- def init_banner(self):
- """optionally display the banner"""
- if self.display_banner and self.interact:
- self.shell.show_banner()
- # Make sure there is a space below the banner.
- if self.log_level <= logging.INFO: print()
-
- def _pylab_changed(self, name, old, new):
- """Replace --pylab='inline' with --pylab='auto'"""
- if new == 'inline':
- warnings.warn("'inline' not available as pylab backend, "
- "using 'auto' instead.")
- self.pylab = 'auto'
-
- def start(self):
- if self.subapp is not None:
- return self.subapp.start()
- # perform any prexec steps:
- if self.interact:
- self.log.debug("Starting IPython's mainloop...")
- self.shell.mainloop()
- else:
- self.log.debug("IPython not interactive...")
- if not self.shell.last_execution_succeeded:
- sys.exit(1)
-
-def load_default_config(ipython_dir=None):
- """Load the default config file from the default ipython_dir.
-
- This is useful for embedded shells.
- """
- if ipython_dir is None:
- ipython_dir = get_ipython_dir()
-
- profile_dir = os.path.join(ipython_dir, 'profile_default')
- app = TerminalIPythonApp()
- app.config_file_paths.append(profile_dir)
- app.load_config_file()
- return app.config
-
-launch_new_instance = TerminalIPythonApp.launch_instance
-
-
-if __name__ == '__main__':
- launch_new_instance()
+#!/usr/bin/env python
+# encoding: utf-8
+"""
+The :class:`~IPython.core.application.Application` object for the command
+line :command:`ipython` program.
+"""
+
+# Copyright (c) IPython Development Team.
+# Distributed under the terms of the Modified BSD License.
+
+
+import logging
+import os
+import sys
+import warnings
+
+from traitlets.config.loader import Config
+from traitlets.config.application import boolean_flag, catch_config_error
+from IPython.core import release
+from IPython.core import usage
+from IPython.core.completer import IPCompleter
+from IPython.core.crashhandler import CrashHandler
+from IPython.core.formatters import PlainTextFormatter
+from IPython.core.history import HistoryManager
+from IPython.core.application import (
+ ProfileDir, BaseIPythonApplication, base_flags, base_aliases
+)
+from IPython.core.magics import (
+ ScriptMagics, LoggingMagics
+)
+from IPython.core.shellapp import (
+ InteractiveShellApp, shell_flags, shell_aliases
+)
+from IPython.extensions.storemagic import StoreMagics
+from .interactiveshell import TerminalInteractiveShell
+from IPython.paths import get_ipython_dir
+from traitlets import (
+ Bool, List, default, observe, Type
+)
+
+#-----------------------------------------------------------------------------
+# Globals, utilities and helpers
+#-----------------------------------------------------------------------------
+
+_examples = """
+ipython --matplotlib # enable matplotlib integration
+ipython --matplotlib=qt # enable matplotlib integration with qt4 backend
+
+ipython --log-level=DEBUG # set logging to DEBUG
+ipython --profile=foo # start with profile foo
+
+ipython profile create foo # create profile foo w/ default config files
+ipython help profile # show the help for the profile subcmd
+
+ipython locate # print the path to the IPython directory
+ipython locate profile foo # print the path to the directory for profile `foo`
+"""
+
+#-----------------------------------------------------------------------------
+# Crash handler for this application
+#-----------------------------------------------------------------------------
+
+class IPAppCrashHandler(CrashHandler):
+ """sys.excepthook for IPython itself, leaves a detailed report on disk."""
+
+ def __init__(self, app):
+ contact_name = release.author
+ contact_email = release.author_email
+ bug_tracker = 'https://github.com/ipython/ipython/issues'
+ super(IPAppCrashHandler,self).__init__(
+ app, contact_name, contact_email, bug_tracker
+ )
+
+ def make_report(self,traceback):
+ """Return a string containing a crash report."""
+
+ sec_sep = self.section_sep
+ # Start with parent report
+ report = [super(IPAppCrashHandler, self).make_report(traceback)]
+ # Add interactive-specific info we may have
+ rpt_add = report.append
+ try:
+ rpt_add(sec_sep+"History of session input:")
+ for line in self.app.shell.user_ns['_ih']:
+ rpt_add(line)
+ rpt_add('\n*** Last line of input (may not be in above history):\n')
+ rpt_add(self.app.shell._last_input_line+'\n')
+ except:
+ pass
+
+ return ''.join(report)
+
+#-----------------------------------------------------------------------------
+# Aliases and Flags
+#-----------------------------------------------------------------------------
+flags = dict(base_flags)
+flags.update(shell_flags)
+frontend_flags = {}
+addflag = lambda *args: frontend_flags.update(boolean_flag(*args))
+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('banner', 'TerminalIPythonApp.display_banner',
+ "Display a banner upon starting IPython.",
+ "Don't display a banner upon starting IPython."
+)
+addflag('confirm-exit', 'TerminalInteractiveShell.confirm_exit',
+ """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.""",
+ "Don't prompt the user when exiting."
+)
+addflag('term-title', 'TerminalInteractiveShell.term_title',
+ "Enable auto setting the terminal title.",
+ "Disable auto setting the terminal 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.InteractiveShell.separate_in = ''
+classic_config.InteractiveShell.separate_out = ''
+classic_config.InteractiveShell.separate_out2 = ''
+classic_config.InteractiveShell.colors = 'NoColor'
+classic_config.InteractiveShell.xmode = 'Plain'
+
+frontend_flags['classic']=(
+ classic_config,
+ "Gives IPython a similar feel to the classic Python prompt."
+)
+# # log doesn't make so much sense this way anymore
+# paa('--log','-l',
+# action='store_true', dest='InteractiveShell.logstart',
+# help="Start logging to the default log file (./ipython_log.py).")
+#
+# # quick is harder to implement
+frontend_flags['quick']=(
+ {'TerminalIPythonApp' : {'quick' : True}},
+ "Enable quick startup with no config files."
+)
+
+frontend_flags['i'] = (
+ {'TerminalIPythonApp' : {'force_interact' : True}},
+ """If running code from the command line, become interactive afterwards.
+ It is often useful to follow this with `--` to treat remaining flags as
+ script arguments.
+ """
+)
+flags.update(frontend_flags)
+
+aliases = dict(base_aliases)
+aliases.update(shell_aliases)
+
+#-----------------------------------------------------------------------------
+# Main classes and functions
+#-----------------------------------------------------------------------------
+
+
+class LocateIPythonApp(BaseIPythonApplication):
+ description = """print the path to the IPython dir"""
+ subcommands = dict(
+ profile=('IPython.core.profileapp.ProfileLocate',
+ "print the path to an IPython profile directory",
+ ),
+ )
+ def start(self):
+ if self.subapp is not None:
+ return self.subapp.start()
+ else:
+ print(self.ipython_dir)
+
+
+class TerminalIPythonApp(BaseIPythonApplication, InteractiveShellApp):
+ name = u'ipython'
+ description = usage.cl_usage
+ crash_handler_class = IPAppCrashHandler
+ examples = _examples
+
+ flags = flags
+ aliases = aliases
+ classes = List()
+
+ interactive_shell_class = Type(
+ klass=object, # use default_value otherwise which only allow subclasses.
+ default_value=TerminalInteractiveShell,
+ help="Class to use to instantiate the TerminalInteractiveShell object. Useful for custom Frontends"
+ ).tag(config=True)
+
+ @default('classes')
+ def _classes_default(self):
+ """This has to be in a method, for TerminalIPythonApp to be available."""
+ return [
+ InteractiveShellApp, # ShellApp comes before TerminalApp, because
+ self.__class__, # it will also affect subclasses (e.g. QtConsole)
+ TerminalInteractiveShell,
+ HistoryManager,
+ ProfileDir,
+ PlainTextFormatter,
+ IPCompleter,
+ ScriptMagics,
+ LoggingMagics,
+ StoreMagics,
+ ]
+
+ deprecated_subcommands = dict(
+ qtconsole=('qtconsole.qtconsoleapp.JupyterQtConsoleApp',
+ """DEPRECATED, Will be removed in IPython 6.0 : Launch the Jupyter Qt Console."""
+ ),
+ notebook=('notebook.notebookapp.NotebookApp',
+ """DEPRECATED, Will be removed in IPython 6.0 : Launch the Jupyter HTML Notebook Server."""
+ ),
+ console=('jupyter_console.app.ZMQTerminalIPythonApp',
+ """DEPRECATED, Will be removed in IPython 6.0 : Launch the Jupyter terminal-based Console."""
+ ),
+ nbconvert=('nbconvert.nbconvertapp.NbConvertApp',
+ "DEPRECATED, Will be removed in IPython 6.0 : Convert notebooks to/from other formats."
+ ),
+ trust=('nbformat.sign.TrustNotebookApp',
+ "DEPRECATED, Will be removed in IPython 6.0 : Sign notebooks to trust their potentially unsafe contents at load."
+ ),
+ kernelspec=('jupyter_client.kernelspecapp.KernelSpecApp',
+ "DEPRECATED, Will be removed in IPython 6.0 : Manage Jupyter kernel specifications."
+ ),
+ )
+ subcommands = dict(
+ profile = ("IPython.core.profileapp.ProfileApp",
+ "Create and manage IPython profiles."
+ ),
+ kernel = ("ipykernel.kernelapp.IPKernelApp",
+ "Start a kernel without an attached frontend."
+ ),
+ locate=('IPython.terminal.ipapp.LocateIPythonApp',
+ LocateIPythonApp.description
+ ),
+ history=('IPython.core.historyapp.HistoryApp',
+ "Manage the IPython history database."
+ ),
+ )
+ deprecated_subcommands['install-nbextension'] = (
+ "notebook.nbextensions.InstallNBExtensionApp",
+ "DEPRECATED, Will be removed in IPython 6.0 : Install Jupyter notebook extension files"
+ )
+ subcommands.update(deprecated_subcommands)
+
+ # *do* autocreate requested profile, but don't create the config file.
+ auto_create=Bool(True)
+ # configurables
+ 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']:
+ self.load_config_file = lambda *a, **kw: None
+
+ display_banner = Bool(True,
+ help="Whether to display a banner upon starting IPython."
+ ).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,
+ 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']:
+ self.interact = True
+
+ @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:
+ self.interact = False
+
+ # internal, not-configurable
+ something_to_run=Bool(False)
+
+ def parse_command_line(self, argv=None):
+ """override to allow old '-pylab' flag with deprecation warning"""
+
+ argv = sys.argv[1:] if argv is None else argv
+
+ if '-pylab' in argv:
+ # deprecated `-pylab` given,
+ # warn and transform into current syntax
+ argv = argv[:] # copy, don't clobber
+ idx = argv.index('-pylab')
+ warnings.warn("`-pylab` flag has been deprecated.\n"
+ " Use `--matplotlib <backend>` and import pylab manually.")
+ argv[idx] = '--pylab'
+
+ return super(TerminalIPythonApp, self).parse_command_line(argv)
+
+ @catch_config_error
+ def initialize(self, argv=None):
+ """Do actions after construct, but before starting the app."""
+ super(TerminalIPythonApp, self).initialize(argv)
+ if self.subapp is not None:
+ # don't bother initializing further, starting subapp
+ return
+ # print self.extra_args
+ if self.extra_args and not self.something_to_run:
+ self.file_to_run = self.extra_args[0]
+ self.init_path()
+ # create the shell
+ self.init_shell()
+ # and draw the banner
+ self.init_banner()
+ # Now a variety of things that happen after the banner is printed.
+ self.init_gui_pylab()
+ self.init_extensions()
+ self.init_code()
+
+ def init_shell(self):
+ """initialize the InteractiveShell instance"""
+ # Create an InteractiveShell instance.
+ # shell.display_banner should always be False for the terminal
+ # 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,
+ ipython_dir=self.ipython_dir, user_ns=self.user_ns)
+ self.shell.configurables.append(self)
+
+ def init_banner(self):
+ """optionally display the banner"""
+ if self.display_banner and self.interact:
+ self.shell.show_banner()
+ # Make sure there is a space below the banner.
+ if self.log_level <= logging.INFO: print()
+
+ def _pylab_changed(self, name, old, new):
+ """Replace --pylab='inline' with --pylab='auto'"""
+ if new == 'inline':
+ warnings.warn("'inline' not available as pylab backend, "
+ "using 'auto' instead.")
+ self.pylab = 'auto'
+
+ def start(self):
+ if self.subapp is not None:
+ return self.subapp.start()
+ # perform any prexec steps:
+ if self.interact:
+ self.log.debug("Starting IPython's mainloop...")
+ self.shell.mainloop()
+ else:
+ self.log.debug("IPython not interactive...")
+ if not self.shell.last_execution_succeeded:
+ sys.exit(1)
+
+def load_default_config(ipython_dir=None):
+ """Load the default config file from the default ipython_dir.
+
+ This is useful for embedded shells.
+ """
+ if ipython_dir is None:
+ ipython_dir = get_ipython_dir()
+
+ profile_dir = os.path.join(ipython_dir, 'profile_default')
+ app = TerminalIPythonApp()
+ app.config_file_paths.append(profile_dir)
+ app.load_config_file()
+ return app.config
+
+launch_new_instance = TerminalIPythonApp.launch_instance
+
+
+if __name__ == '__main__':
+ launch_new_instance()
diff --git a/contrib/python/ipython/py3/IPython/terminal/magics.py b/contrib/python/ipython/py3/IPython/terminal/magics.py
index d6f9c1d701..42231c3f80 100644
--- a/contrib/python/ipython/py3/IPython/terminal/magics.py
+++ b/contrib/python/ipython/py3/IPython/terminal/magics.py
@@ -1,213 +1,213 @@
-"""Extra magics for terminal use."""
-
-# Copyright (c) IPython Development Team.
-# Distributed under the terms of the Modified BSD License.
-
-
-from logging import error
-import os
-import sys
-
-from IPython.core.error import TryNext, UsageError
-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 = 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)
-
- 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, str):
- 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)"""
- 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.
-
- 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!
-
- ::
- In [8]: %cpaste
- Pasting code; enter '--' alone on the line to stop.
- :>>> %alias_magic t timeit
- :>>> %t -n1 pass
- :--
- Created `%t` as an alias for `%timeit`.
- Created `%%t` as an alias for `%%timeit`.
- 354 ns ± 224 ns per loop (mean ± std. dev. of 7 runs, 1 loop each)
- """
- 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")
+"""Extra magics for terminal use."""
+
+# Copyright (c) IPython Development Team.
+# Distributed under the terms of the Modified BSD License.
+
+
+from logging import error
+import os
+import sys
+
+from IPython.core.error import TryNext, UsageError
+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 = 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)
+
+ 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, str):
+ 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)"""
+ 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.
+
+ 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!
+
+ ::
+ In [8]: %cpaste
+ Pasting code; enter '--' alone on the line to stop.
+ :>>> %alias_magic t timeit
+ :>>> %t -n1 pass
+ :--
+ Created `%t` as an alias for `%timeit`.
+ Created `%%t` as an alias for `%%timeit`.
+ 354 ns ± 224 ns per loop (mean ± std. dev. of 7 runs, 1 loop each)
+ """
+ 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/py3/IPython/terminal/prompts.py b/contrib/python/ipython/py3/IPython/terminal/prompts.py
index 55e90ccdd3..3f5c07b980 100644
--- a/contrib/python/ipython/py3/IPython/terminal/prompts.py
+++ b/contrib/python/ipython/py3/IPython/terminal/prompts.py
@@ -1,108 +1,108 @@
-"""Terminal input and output prompts."""
-
-from pygments.token import Token
-import sys
-
-from IPython.core.displayhook import DisplayHook
-
-from prompt_toolkit.formatted_text import fragment_list_width, PygmentsTokens
-from prompt_toolkit.shortcuts import print_formatted_text
-from prompt_toolkit.enums import EditingMode
-
-
-class Prompts(object):
- def __init__(self, shell):
- self.shell = shell
-
- def vi_mode(self):
- if (getattr(self.shell.pt_app, 'editing_mode', None) == EditingMode.VI
- and self.shell.prompt_includes_vi_mode):
- mode = str(self.shell.pt_app.app.vi_state.input_mode)
- if mode.startswith('InputMode.'):
- mode = mode[10:13].lower()
- elif mode.startswith('vi-'):
- mode = mode[3:6]
- return '['+mode+'] '
- return ''
-
-
- def in_prompt_tokens(self):
- return [
- (Token.Prompt, self.vi_mode() ),
- (Token.Prompt, 'In ['),
- (Token.PromptNum, str(self.shell.execution_count)),
- (Token.Prompt, ']: '),
- ]
-
- def _width(self):
- return fragment_list_width(self.in_prompt_tokens())
-
- def continuation_prompt_tokens(self, 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):
- return [
- (Token.Prompt, '>>> '),
- ]
-
- def continuation_prompt_tokens(self, 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()
- 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_app:
- print_formatted_text(PygmentsTokens(tokens),
- style=self.shell.pt_app.app.style, end='',
- )
- else:
- sys.stdout.write(prompt_txt)
-
- def write_format_data(self, format_dict, md_dict=None) -> None:
- if self.shell.mime_renderers:
-
- for mime, handler in self.shell.mime_renderers.items():
- if mime in format_dict:
- handler(format_dict[mime], None)
- return
-
- super().write_format_data(format_dict, md_dict)
-
+"""Terminal input and output prompts."""
+
+from pygments.token import Token
+import sys
+
+from IPython.core.displayhook import DisplayHook
+
+from prompt_toolkit.formatted_text import fragment_list_width, PygmentsTokens
+from prompt_toolkit.shortcuts import print_formatted_text
+from prompt_toolkit.enums import EditingMode
+
+
+class Prompts(object):
+ def __init__(self, shell):
+ self.shell = shell
+
+ def vi_mode(self):
+ if (getattr(self.shell.pt_app, 'editing_mode', None) == EditingMode.VI
+ and self.shell.prompt_includes_vi_mode):
+ mode = str(self.shell.pt_app.app.vi_state.input_mode)
+ if mode.startswith('InputMode.'):
+ mode = mode[10:13].lower()
+ elif mode.startswith('vi-'):
+ mode = mode[3:6]
+ return '['+mode+'] '
+ return ''
+
+
+ def in_prompt_tokens(self):
+ return [
+ (Token.Prompt, self.vi_mode() ),
+ (Token.Prompt, 'In ['),
+ (Token.PromptNum, str(self.shell.execution_count)),
+ (Token.Prompt, ']: '),
+ ]
+
+ def _width(self):
+ return fragment_list_width(self.in_prompt_tokens())
+
+ def continuation_prompt_tokens(self, 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):
+ return [
+ (Token.Prompt, '>>> '),
+ ]
+
+ def continuation_prompt_tokens(self, 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()
+ 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_app:
+ print_formatted_text(PygmentsTokens(tokens),
+ style=self.shell.pt_app.app.style, end='',
+ )
+ else:
+ sys.stdout.write(prompt_txt)
+
+ def write_format_data(self, format_dict, md_dict=None) -> None:
+ if self.shell.mime_renderers:
+
+ for mime, handler in self.shell.mime_renderers.items():
+ if mime in format_dict:
+ handler(format_dict[mime], None)
+ return
+
+ super().write_format_data(format_dict, md_dict)
+
diff --git a/contrib/python/ipython/py3/IPython/terminal/pt_inputhooks/__init__.py b/contrib/python/ipython/py3/IPython/terminal/pt_inputhooks/__init__.py
index e41e26a5f5..69ff0ba1e6 100644
--- a/contrib/python/ipython/py3/IPython/terminal/pt_inputhooks/__init__.py
+++ b/contrib/python/ipython/py3/IPython/terminal/pt_inputhooks/__init__.py
@@ -1,62 +1,62 @@
-import importlib
-import os
-
-aliases = {
- 'qt4': 'qt',
- 'gtk2': 'gtk',
-}
-
-backends = [
- "qt",
- "qt4",
- "qt5",
- "qt6",
- "gtk",
- "gtk2",
- "gtk3",
- "gtk4",
- "tk",
- "wx",
- "pyglet",
- "glut",
- "osx",
- "asyncio",
-]
-
-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:
- return gui, registered[gui]
-
- 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"
- gui_mod = "qt"
- elif gui == "qt6":
- os.environ["QT_API"] = "pyqt6"
- gui_mod = "qt"
-
- mod = importlib.import_module('IPython.terminal.pt_inputhooks.'+gui_mod)
- return gui, mod.inputhook
+import importlib
+import os
+
+aliases = {
+ 'qt4': 'qt',
+ 'gtk2': 'gtk',
+}
+
+backends = [
+ "qt",
+ "qt4",
+ "qt5",
+ "qt6",
+ "gtk",
+ "gtk2",
+ "gtk3",
+ "gtk4",
+ "tk",
+ "wx",
+ "pyglet",
+ "glut",
+ "osx",
+ "asyncio",
+]
+
+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:
+ return gui, registered[gui]
+
+ 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"
+ gui_mod = "qt"
+ elif gui == "qt6":
+ os.environ["QT_API"] = "pyqt6"
+ gui_mod = "qt"
+
+ mod = importlib.import_module('IPython.terminal.pt_inputhooks.'+gui_mod)
+ return gui, mod.inputhook
diff --git a/contrib/python/ipython/py3/IPython/terminal/pt_inputhooks/asyncio.py b/contrib/python/ipython/py3/IPython/terminal/pt_inputhooks/asyncio.py
index 44d480527d..95cf194f86 100644
--- a/contrib/python/ipython/py3/IPython/terminal/pt_inputhooks/asyncio.py
+++ b/contrib/python/ipython/py3/IPython/terminal/pt_inputhooks/asyncio.py
@@ -1,64 +1,64 @@
-"""
-Inputhook for running the original asyncio event loop while we're waiting for
-input.
-
-By default, in IPython, we run the prompt with a different asyncio event loop,
-because otherwise we risk that people are freezing the prompt by scheduling bad
-coroutines. E.g., a coroutine that does a while/true and never yield back
-control to the loop. We can't cancel that.
-
-However, sometimes we want the asyncio loop to keep running while waiting for
-a prompt.
-
-The following example will print the numbers from 1 to 10 above the prompt,
-while we are waiting for input. (This works also because we use
-prompt_toolkit`s `patch_stdout`)::
-
- In [1]: import asyncio
-
- In [2]: %gui asyncio
-
- In [3]: async def f():
- ...: for i in range(10):
- ...: await asyncio.sleep(1)
- ...: print(i)
-
-
- In [4]: asyncio.ensure_future(f())
-
-"""
-import asyncio
-from prompt_toolkit import __version__ as ptk_version
-
-PTK3 = ptk_version.startswith('3.')
-
-
-# Keep reference to the original asyncio loop, because getting the event loop
-# within the input hook would return the other loop.
-loop = asyncio.get_event_loop()
-
-
-def inputhook(context):
- """
- Inputhook for asyncio event loop integration.
- """
- # For prompt_toolkit 3.0, this input hook literally doesn't do anything.
- # The event loop integration here is implemented in `interactiveshell.py`
- # by running the prompt itself in the current asyncio loop. The main reason
- # for this is that nesting asyncio event loops is unreliable.
- if PTK3:
- return
-
- # For prompt_toolkit 2.0, we can run the current asyncio event loop,
- # because prompt_toolkit 2.0 uses a different event loop internally.
-
- def stop():
- loop.stop()
-
- fileno = context.fileno()
- loop.add_reader(fileno, stop)
- try:
- loop.run_forever()
- finally:
- loop.remove_reader(fileno)
-
+"""
+Inputhook for running the original asyncio event loop while we're waiting for
+input.
+
+By default, in IPython, we run the prompt with a different asyncio event loop,
+because otherwise we risk that people are freezing the prompt by scheduling bad
+coroutines. E.g., a coroutine that does a while/true and never yield back
+control to the loop. We can't cancel that.
+
+However, sometimes we want the asyncio loop to keep running while waiting for
+a prompt.
+
+The following example will print the numbers from 1 to 10 above the prompt,
+while we are waiting for input. (This works also because we use
+prompt_toolkit`s `patch_stdout`)::
+
+ In [1]: import asyncio
+
+ In [2]: %gui asyncio
+
+ In [3]: async def f():
+ ...: for i in range(10):
+ ...: await asyncio.sleep(1)
+ ...: print(i)
+
+
+ In [4]: asyncio.ensure_future(f())
+
+"""
+import asyncio
+from prompt_toolkit import __version__ as ptk_version
+
+PTK3 = ptk_version.startswith('3.')
+
+
+# Keep reference to the original asyncio loop, because getting the event loop
+# within the input hook would return the other loop.
+loop = asyncio.get_event_loop()
+
+
+def inputhook(context):
+ """
+ Inputhook for asyncio event loop integration.
+ """
+ # For prompt_toolkit 3.0, this input hook literally doesn't do anything.
+ # The event loop integration here is implemented in `interactiveshell.py`
+ # by running the prompt itself in the current asyncio loop. The main reason
+ # for this is that nesting asyncio event loops is unreliable.
+ if PTK3:
+ return
+
+ # For prompt_toolkit 2.0, we can run the current asyncio event loop,
+ # because prompt_toolkit 2.0 uses a different event loop internally.
+
+ def stop():
+ loop.stop()
+
+ fileno = context.fileno()
+ loop.add_reader(fileno, stop)
+ try:
+ loop.run_forever()
+ finally:
+ loop.remove_reader(fileno)
+
diff --git a/contrib/python/ipython/py3/IPython/terminal/pt_inputhooks/glut.py b/contrib/python/ipython/py3/IPython/terminal/pt_inputhooks/glut.py
index 6715c77fd8..f6d54a55b4 100644
--- a/contrib/python/ipython/py3/IPython/terminal/pt_inputhooks/glut.py
+++ b/contrib/python/ipython/py3/IPython/terminal/pt_inputhooks/glut.py
@@ -1,140 +1,140 @@
-"""GLUT Input hook for interactive use with prompt_toolkit
-"""
-
-
-# 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
+"""
+
+
+# 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/py3/IPython/terminal/pt_inputhooks/gtk.py b/contrib/python/ipython/py3/IPython/terminal/pt_inputhooks/gtk.py
index 13ce1f7d1e..6e246ba837 100644
--- a/contrib/python/ipython/py3/IPython/terminal/pt_inputhooks/gtk.py
+++ b/contrib/python/ipython/py3/IPython/terminal/pt_inputhooks/gtk.py
@@ -1,58 +1,58 @@
-# 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.
-"""
-
-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.
+"""
+
+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/py3/IPython/terminal/pt_inputhooks/gtk3.py b/contrib/python/ipython/py3/IPython/terminal/pt_inputhooks/gtk3.py
index 2c6243c072..ae82b4edaa 100644
--- a/contrib/python/ipython/py3/IPython/terminal/pt_inputhooks/gtk3.py
+++ b/contrib/python/ipython/py3/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.PRIORITY_DEFAULT, 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.PRIORITY_DEFAULT, GLib.IO_IN, _main_quit)
+ Gtk.main()
diff --git a/contrib/python/ipython/py3/IPython/terminal/pt_inputhooks/gtk4.py b/contrib/python/ipython/py3/IPython/terminal/pt_inputhooks/gtk4.py
index 38fce01f8c..009fbf1212 100644
--- a/contrib/python/ipython/py3/IPython/terminal/pt_inputhooks/gtk4.py
+++ b/contrib/python/ipython/py3/IPython/terminal/pt_inputhooks/gtk4.py
@@ -1,27 +1,27 @@
-"""
-prompt_toolkit input hook for GTK 4.
-"""
-
-from gi.repository import GLib
-
-
-class _InputHook:
- def __init__(self, context):
- self._quit = False
- GLib.io_add_watch(
- context.fileno(), GLib.PRIORITY_DEFAULT, GLib.IO_IN, self.quit
- )
-
- def quit(self, *args, **kwargs):
- self._quit = True
- return False
-
- def run(self):
- context = GLib.MainContext.default()
- while not self._quit:
- context.iteration(True)
-
-
-def inputhook(context):
- hook = _InputHook(context)
- hook.run()
+"""
+prompt_toolkit input hook for GTK 4.
+"""
+
+from gi.repository import GLib
+
+
+class _InputHook:
+ def __init__(self, context):
+ self._quit = False
+ GLib.io_add_watch(
+ context.fileno(), GLib.PRIORITY_DEFAULT, GLib.IO_IN, self.quit
+ )
+
+ def quit(self, *args, **kwargs):
+ self._quit = True
+ return False
+
+ def run(self):
+ context = GLib.MainContext.default()
+ while not self._quit:
+ context.iteration(True)
+
+
+def inputhook(context):
+ hook = _InputHook(context)
+ hook.run()
diff --git a/contrib/python/ipython/py3/IPython/terminal/pt_inputhooks/osx.py b/contrib/python/ipython/py3/IPython/terminal/pt_inputhooks/osx.py
index 4b48d0d1e3..80440196fb 100644
--- a/contrib/python/ipython/py3/IPython/terminal/pt_inputhooks/osx.py
+++ b/contrib/python/ipython/py3/IPython/terminal/pt_inputhooks/osx.py
@@ -1,157 +1,157 @@
-"""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, 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)"""
- objc.objc_msgSend.argtypes = [void_p, void_p]
- return msg(C('NSApplication'), n('sharedApplication'))
-
-
-def _wake(NSApp):
- """Wake the Application"""
- objc.objc_msgSend.argtypes = [
- void_p,
- void_p,
- void_p,
- void_p,
- void_p,
- void_p,
- void_p,
- void_p,
- void_p,
- void_p,
- void_p,
- ]
- 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
- )
- objc.objc_msgSend.argtypes = [void_p, void_p, void_p, void_p]
- 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()
- objc.objc_msgSend.argtypes = [void_p, void_p, void_p]
- 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())
- objc.objc_msgSend.argtypes = [void_p, void_p]
- 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, 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)"""
+ objc.objc_msgSend.argtypes = [void_p, void_p]
+ return msg(C('NSApplication'), n('sharedApplication'))
+
+
+def _wake(NSApp):
+ """Wake the Application"""
+ objc.objc_msgSend.argtypes = [
+ void_p,
+ void_p,
+ void_p,
+ void_p,
+ void_p,
+ void_p,
+ void_p,
+ void_p,
+ void_p,
+ void_p,
+ void_p,
+ ]
+ 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
+ )
+ objc.objc_msgSend.argtypes = [void_p, void_p, void_p, void_p]
+ 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()
+ objc.objc_msgSend.argtypes = [void_p, void_p, void_p]
+ 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())
+ objc.objc_msgSend.argtypes = [void_p, void_p]
+ 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/py3/IPython/terminal/pt_inputhooks/pyglet.py b/contrib/python/ipython/py3/IPython/terminal/pt_inputhooks/pyglet.py
index f34ed85845..49ec86d223 100644
--- a/contrib/python/ipython/py3/IPython/terminal/pt_inputhooks/pyglet.py
+++ b/contrib/python/ipython/py3/IPython/terminal/pt_inputhooks/pyglet.py
@@ -1,66 +1,66 @@
-"""Enable pyglet to be used interactively with prompt_toolkit
-"""
-
-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 interactively with prompt_toolkit
+"""
+
+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/py3/IPython/terminal/pt_inputhooks/qt.py b/contrib/python/ipython/py3/IPython/terminal/pt_inputhooks/qt.py
index dde9238236..b999f5aa17 100644
--- a/contrib/python/ipython/py3/IPython/terminal/pt_inputhooks/qt.py
+++ b/contrib/python/ipython/py3/IPython/terminal/pt_inputhooks/qt.py
@@ -1,83 +1,83 @@
-import sys
-import os
-from IPython.external.qt_for_kernel import QtCore, QtGui, enum_helper
-from IPython import get_ipython
-
-# If we create a QApplication, keep a reference to it so that it doesn't get
-# garbage collected.
-_appref = None
-_already_warned = False
-
-
-def _exec(obj):
- # exec on PyQt6, exec_ elsewhere.
- obj.exec() if hasattr(obj, "exec") else obj.exec_()
-
-
-def _reclaim_excepthook():
- shell = get_ipython()
- if shell is not None:
- sys.excepthook = shell.excepthook
-
-
-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'):
- import warnings
- global _already_warned
- if not _already_warned:
- _already_warned = True
- warnings.warn(
- 'The DISPLAY or WAYLAND_DISPLAY environment variable is '
- 'not set or empty and Qt5 requires this environment '
- 'variable. Deactivate Qt5 code.'
- )
- return
- try:
- QtCore.QApplication.setAttribute(QtCore.Qt.AA_EnableHighDpiScaling)
- except AttributeError: # Only for Qt>=5.6, <6.
- pass
- try:
- QtCore.QApplication.setHighDpiScaleFactorRoundingPolicy(
- QtCore.Qt.HighDpiScaleFactorRoundingPolicy.PassThrough
- )
- except AttributeError: # Only for Qt>=5.14.
- pass
- _appref = app = QtGui.QApplication([" "])
-
- # "reclaim" IPython sys.excepthook after event loop starts
- # without this, it defaults back to BaseIPythonApplication.excepthook
- # and exceptions in the Qt event loop are rendered without traceback
- # formatting and look like "bug in IPython".
- QtCore.QTimer.singleShot(0, _reclaim_excepthook)
-
- 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
- _exec(event_loop)
- 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(), enum_helper("QtCore.QSocketNotifier.Type").Read
- )
- try:
- # connect the callback we care about before we turn it on
- notifier.activated.connect(lambda: event_loop.exit())
- notifier.setEnabled(True)
- # only start the event loop we are not already flipped
- if not context.input_is_ready():
- _exec(event_loop)
- finally:
- notifier.setEnabled(False)
+import sys
+import os
+from IPython.external.qt_for_kernel import QtCore, QtGui, enum_helper
+from IPython import get_ipython
+
+# If we create a QApplication, keep a reference to it so that it doesn't get
+# garbage collected.
+_appref = None
+_already_warned = False
+
+
+def _exec(obj):
+ # exec on PyQt6, exec_ elsewhere.
+ obj.exec() if hasattr(obj, "exec") else obj.exec_()
+
+
+def _reclaim_excepthook():
+ shell = get_ipython()
+ if shell is not None:
+ sys.excepthook = shell.excepthook
+
+
+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'):
+ import warnings
+ global _already_warned
+ if not _already_warned:
+ _already_warned = True
+ warnings.warn(
+ 'The DISPLAY or WAYLAND_DISPLAY environment variable is '
+ 'not set or empty and Qt5 requires this environment '
+ 'variable. Deactivate Qt5 code.'
+ )
+ return
+ try:
+ QtCore.QApplication.setAttribute(QtCore.Qt.AA_EnableHighDpiScaling)
+ except AttributeError: # Only for Qt>=5.6, <6.
+ pass
+ try:
+ QtCore.QApplication.setHighDpiScaleFactorRoundingPolicy(
+ QtCore.Qt.HighDpiScaleFactorRoundingPolicy.PassThrough
+ )
+ except AttributeError: # Only for Qt>=5.14.
+ pass
+ _appref = app = QtGui.QApplication([" "])
+
+ # "reclaim" IPython sys.excepthook after event loop starts
+ # without this, it defaults back to BaseIPythonApplication.excepthook
+ # and exceptions in the Qt event loop are rendered without traceback
+ # formatting and look like "bug in IPython".
+ QtCore.QTimer.singleShot(0, _reclaim_excepthook)
+
+ 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
+ _exec(event_loop)
+ 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(), enum_helper("QtCore.QSocketNotifier.Type").Read
+ )
+ try:
+ # connect the callback we care about before we turn it on
+ notifier.activated.connect(lambda: event_loop.exit())
+ notifier.setEnabled(True)
+ # only start the event loop we are not already flipped
+ if not context.input_is_ready():
+ _exec(event_loop)
+ finally:
+ notifier.setEnabled(False)
diff --git a/contrib/python/ipython/py3/IPython/terminal/pt_inputhooks/tk.py b/contrib/python/ipython/py3/IPython/terminal/pt_inputhooks/tk.py
index 6afc276747..2715505f1f 100644
--- a/contrib/python/ipython/py3/IPython/terminal/pt_inputhooks/tk.py
+++ b/contrib/python/ipython/py3/IPython/terminal/pt_inputhooks/tk.py
@@ -1,90 +1,90 @@
-# 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 registers 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
-
-import _tkinter
-import tkinter
-
-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 registers 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
+
+import _tkinter
+import tkinter
+
+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/py3/IPython/terminal/pt_inputhooks/wx.py b/contrib/python/ipython/py3/IPython/terminal/pt_inputhooks/wx.py
index 3b7b0e0a33..a0f4442c77 100644
--- a/contrib/python/ipython/py3/IPython/terminal/pt_inputhooks/wx.py
+++ b/contrib/python/ipython/py3/IPython/terminal/pt_inputhooks/wx.py
@@ -1,219 +1,219 @@
-"""Enable wxPython to be used interactively in prompt_toolkit
-"""
-
-import sys
-import signal
-import time
-from timeit import default_timer as clock
-import wx
-
-
-def ignore_keyboardinterrupts(func):
- """Decorator which causes KeyboardInterrupt exceptions to be ignored during
- execution of the decorated function.
-
- This is used by the inputhook functions to handle the event where the user
- presses CTRL+C while IPython is idle, and the inputhook loop is running. In
- this case, we want to ignore interrupts.
- """
- def wrapper(*args, **kwargs):
- try:
- func(*args, **kwargs)
- except KeyboardInterrupt:
- pass
- return wrapper
-
-
-@ignore_keyboardinterrupts
-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.
- """
- 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
- 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()
-
-
-@ignore_keyboardinterrupts
-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.
- """
- 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)
- return 0
-
-
-@ignore_keyboardinterrupts
-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.
- """
- 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
- return 0
-
-
-@ignore_keyboardinterrupts
-def inputhook_wxphoenix(context):
- """Run the wx event loop until the user provides more input.
-
- This input hook is suitable for use with wxPython >= 4 (a.k.a. Phoenix).
-
- It uses the same approach to that used in
- ipykernel.eventloops.loop_wx. The wx.MainLoop is executed, and a wx.Timer
- is used to periodically poll the context for input. As soon as input is
- ready, the wx.MainLoop is stopped.
- """
-
- app = wx.GetApp()
-
- if app is None:
- return
-
- if context.input_is_ready():
- return
-
- assert wx.IsMainThread()
-
- # Wx uses milliseconds
- poll_interval = 100
-
- # Use a wx.Timer to periodically check whether input is ready - as soon as
- # it is, we exit the main loop
- timer = wx.Timer()
-
- def poll(ev):
- if context.input_is_ready():
- timer.Stop()
- app.ExitMainLoop()
-
- timer.Start(poll_interval)
- timer.Bind(wx.EVT_TIMER, poll)
-
- # 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)
-
- # The SetExitOnFrameDelete call allows us to run the wx mainloop without
- # having a frame open.
- app.SetExitOnFrameDelete(False)
- app.MainLoop()
-
-
-# Get the major wx version number to figure out what input hook we should use.
-major_version = 3
-
-try:
- major_version = int(wx.__version__[0])
-except Exception:
- pass
-
-# Use the phoenix hook on all platforms for wxpython >= 4
-if major_version >= 4:
- inputhook = inputhook_wxphoenix
-# 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.
-elif sys.platform == 'darwin':
- inputhook = inputhook_wx2
-else:
- inputhook = inputhook_wx3
+"""Enable wxPython to be used interactively in prompt_toolkit
+"""
+
+import sys
+import signal
+import time
+from timeit import default_timer as clock
+import wx
+
+
+def ignore_keyboardinterrupts(func):
+ """Decorator which causes KeyboardInterrupt exceptions to be ignored during
+ execution of the decorated function.
+
+ This is used by the inputhook functions to handle the event where the user
+ presses CTRL+C while IPython is idle, and the inputhook loop is running. In
+ this case, we want to ignore interrupts.
+ """
+ def wrapper(*args, **kwargs):
+ try:
+ func(*args, **kwargs)
+ except KeyboardInterrupt:
+ pass
+ return wrapper
+
+
+@ignore_keyboardinterrupts
+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.
+ """
+ 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
+ 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()
+
+
+@ignore_keyboardinterrupts
+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.
+ """
+ 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)
+ return 0
+
+
+@ignore_keyboardinterrupts
+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.
+ """
+ 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
+ return 0
+
+
+@ignore_keyboardinterrupts
+def inputhook_wxphoenix(context):
+ """Run the wx event loop until the user provides more input.
+
+ This input hook is suitable for use with wxPython >= 4 (a.k.a. Phoenix).
+
+ It uses the same approach to that used in
+ ipykernel.eventloops.loop_wx. The wx.MainLoop is executed, and a wx.Timer
+ is used to periodically poll the context for input. As soon as input is
+ ready, the wx.MainLoop is stopped.
+ """
+
+ app = wx.GetApp()
+
+ if app is None:
+ return
+
+ if context.input_is_ready():
+ return
+
+ assert wx.IsMainThread()
+
+ # Wx uses milliseconds
+ poll_interval = 100
+
+ # Use a wx.Timer to periodically check whether input is ready - as soon as
+ # it is, we exit the main loop
+ timer = wx.Timer()
+
+ def poll(ev):
+ if context.input_is_ready():
+ timer.Stop()
+ app.ExitMainLoop()
+
+ timer.Start(poll_interval)
+ timer.Bind(wx.EVT_TIMER, poll)
+
+ # 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)
+
+ # The SetExitOnFrameDelete call allows us to run the wx mainloop without
+ # having a frame open.
+ app.SetExitOnFrameDelete(False)
+ app.MainLoop()
+
+
+# Get the major wx version number to figure out what input hook we should use.
+major_version = 3
+
+try:
+ major_version = int(wx.__version__[0])
+except Exception:
+ pass
+
+# Use the phoenix hook on all platforms for wxpython >= 4
+if major_version >= 4:
+ inputhook = inputhook_wxphoenix
+# 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.
+elif sys.platform == 'darwin':
+ inputhook = inputhook_wx2
+else:
+ inputhook = inputhook_wx3
diff --git a/contrib/python/ipython/py3/IPython/terminal/ptshell.py b/contrib/python/ipython/py3/IPython/terminal/ptshell.py
index aad111b041..666d3c5b51 100644
--- a/contrib/python/ipython/py3/IPython/terminal/ptshell.py
+++ b/contrib/python/ipython/py3/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/py3/IPython/terminal/ptutils.py b/contrib/python/ipython/py3/IPython/terminal/ptutils.py
index 380087dc29..3e5d3c5c77 100644
--- a/contrib/python/ipython/py3/IPython/terminal/ptutils.py
+++ b/contrib/python/ipython/py3/IPython/terminal/ptutils.py
@@ -1,197 +1,197 @@
-"""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
-import sys
-import traceback
-
-from IPython.core.completer import (
- provisionalcompleter, cursor_to_position,
- _deduplicate_completions)
-from prompt_toolkit.completion import Completer, Completion
-from prompt_toolkit.lexers import Lexer
-from prompt_toolkit.lexers import PygmentsLexer
-from prompt_toolkit.patch_stdout import patch_stdout
-
-import pygments.lexers as pygments_lexers
-import os
-
-_completion_sentinel = object()
-
-def _elide_point(string:str, *, min_elide=30)->str:
- """
- If a string is long enough, and has at least 3 dots,
- replace the middle part with ellipses.
-
- If a string naming a file is long enough, and has at least 3 slashes,
- replace the middle part with ellipses.
-
- If three consecutive dots, or two consecutive dots are encountered these are
- replaced by the equivalents HORIZONTAL ELLIPSIS or TWO DOT LEADER unicode
- equivalents
- """
- string = string.replace('...','\N{HORIZONTAL ELLIPSIS}')
- string = string.replace('..','\N{TWO DOT LEADER}')
- if len(string) < min_elide:
- return string
-
- object_parts = string.split('.')
- file_parts = string.split(os.sep)
- if file_parts[-1] == '':
- file_parts.pop()
-
- if len(object_parts) > 3:
- return '{}.{}\N{HORIZONTAL ELLIPSIS}{}.{}'.format(object_parts[0], object_parts[1][0], object_parts[-2][-1], object_parts[-1])
-
- elif len(file_parts) > 3:
- return ('{}' + os.sep + '{}\N{HORIZONTAL ELLIPSIS}{}' + os.sep + '{}').format(file_parts[0], file_parts[1][0], file_parts[-2][-1], file_parts[-1])
-
- return string
-
-def _elide_typed(string:str, typed:str, *, min_elide:int=30)->str:
- """
- Elide the middle of a long string if the beginning has already been typed.
- """
-
- if len(string) < min_elide:
- return string
- cut_how_much = len(typed)-3
- if cut_how_much < 7:
- return string
- if string.startswith(typed) and len(string)> len(typed):
- return f"{string[:3]}\N{HORIZONTAL ELLIPSIS}{string[cut_how_much:]}"
- return string
-
-def _elide(string:str, typed:str, min_elide=30)->str:
- return _elide_typed(
- _elide_point(string, min_elide=min_elide),
- typed, min_elide=min_elide)
-
-
-
-def _adjust_completion_text_based_on_context(text, body, offset):
- if text.endswith('=') and len(body) > offset and body[offset] == '=':
- return text[:-1]
- else:
- return text
-
-
-class IPythonPTCompleter(Completer):
- """Adaptor to provide IPython completions to prompt_toolkit"""
- def __init__(self, ipy_completer=None, shell=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
-
- @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.
-
- with patch_stdout(), provisionalcompleter():
- body = document.text
- cursor_row = document.cursor_position_row
- cursor_col = document.cursor_position_col
- cursor_position = document.cursor_position
- offset = cursor_to_position(body, cursor_row, cursor_col)
- try:
- yield from self._get_completions(body, offset, cursor_position, self.ipy_completer)
- except Exception as e:
- try:
- exc_type, exc_value, exc_tb = sys.exc_info()
- traceback.print_exception(exc_type, exc_value, exc_tb)
- except AttributeError:
- print('Unrecoverable Error in completions')
-
- @staticmethod
- def _get_completions(body, offset, cursor_position, ipyc):
- """
- Private equivalent of get_completions() use only for unit_testing.
- """
- debug = getattr(ipyc, 'debug', False)
- completions = _deduplicate_completions(
- body, ipyc.completions(body, offset))
- for c in completions:
- if not c.text:
- # Guard against completion machinery giving us an empty string.
- continue
- text = unicodedata.normalize('NFC', c.text)
- # 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(text[0]) == 0:
- if cursor_position + c.start > 0:
- char_before = body[c.start - 1]
- fixed_text = unicodedata.normalize(
- 'NFC', char_before + text)
-
- # Yield the modified completion instead, if this worked.
- if wcwidth(text[0:1]) == 1:
- yield Completion(fixed_text, start_position=c.start - offset - 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)
- display_text = c.text
-
- adjusted_text = _adjust_completion_text_based_on_context(c.text, body, offset)
- if c.type == 'function':
- yield Completion(adjusted_text, start_position=c.start - offset, display=_elide(display_text+'()', body[c.start:c.end]), display_meta=c.type+c.signature)
- else:
- yield Completion(adjusted_text, start_position=c.start - offset, display=_elide(display_text, body[c.start:c.end]), display_meta=c.type)
-
-class IPythonPTLexer(Lexer):
- """
- Wrapper around PythonLexer and BashLexer.
- """
- def __init__(self):
- l = pygments_lexers
- self.python_lexer = PygmentsLexer(l.Python3Lexer)
- 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, 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(document)
+"""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
+import sys
+import traceback
+
+from IPython.core.completer import (
+ provisionalcompleter, cursor_to_position,
+ _deduplicate_completions)
+from prompt_toolkit.completion import Completer, Completion
+from prompt_toolkit.lexers import Lexer
+from prompt_toolkit.lexers import PygmentsLexer
+from prompt_toolkit.patch_stdout import patch_stdout
+
+import pygments.lexers as pygments_lexers
+import os
+
+_completion_sentinel = object()
+
+def _elide_point(string:str, *, min_elide=30)->str:
+ """
+ If a string is long enough, and has at least 3 dots,
+ replace the middle part with ellipses.
+
+ If a string naming a file is long enough, and has at least 3 slashes,
+ replace the middle part with ellipses.
+
+ If three consecutive dots, or two consecutive dots are encountered these are
+ replaced by the equivalents HORIZONTAL ELLIPSIS or TWO DOT LEADER unicode
+ equivalents
+ """
+ string = string.replace('...','\N{HORIZONTAL ELLIPSIS}')
+ string = string.replace('..','\N{TWO DOT LEADER}')
+ if len(string) < min_elide:
+ return string
+
+ object_parts = string.split('.')
+ file_parts = string.split(os.sep)
+ if file_parts[-1] == '':
+ file_parts.pop()
+
+ if len(object_parts) > 3:
+ return '{}.{}\N{HORIZONTAL ELLIPSIS}{}.{}'.format(object_parts[0], object_parts[1][0], object_parts[-2][-1], object_parts[-1])
+
+ elif len(file_parts) > 3:
+ return ('{}' + os.sep + '{}\N{HORIZONTAL ELLIPSIS}{}' + os.sep + '{}').format(file_parts[0], file_parts[1][0], file_parts[-2][-1], file_parts[-1])
+
+ return string
+
+def _elide_typed(string:str, typed:str, *, min_elide:int=30)->str:
+ """
+ Elide the middle of a long string if the beginning has already been typed.
+ """
+
+ if len(string) < min_elide:
+ return string
+ cut_how_much = len(typed)-3
+ if cut_how_much < 7:
+ return string
+ if string.startswith(typed) and len(string)> len(typed):
+ return f"{string[:3]}\N{HORIZONTAL ELLIPSIS}{string[cut_how_much:]}"
+ return string
+
+def _elide(string:str, typed:str, min_elide=30)->str:
+ return _elide_typed(
+ _elide_point(string, min_elide=min_elide),
+ typed, min_elide=min_elide)
+
+
+
+def _adjust_completion_text_based_on_context(text, body, offset):
+ if text.endswith('=') and len(body) > offset and body[offset] == '=':
+ return text[:-1]
+ else:
+ return text
+
+
+class IPythonPTCompleter(Completer):
+ """Adaptor to provide IPython completions to prompt_toolkit"""
+ def __init__(self, ipy_completer=None, shell=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
+
+ @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.
+
+ with patch_stdout(), provisionalcompleter():
+ body = document.text
+ cursor_row = document.cursor_position_row
+ cursor_col = document.cursor_position_col
+ cursor_position = document.cursor_position
+ offset = cursor_to_position(body, cursor_row, cursor_col)
+ try:
+ yield from self._get_completions(body, offset, cursor_position, self.ipy_completer)
+ except Exception as e:
+ try:
+ exc_type, exc_value, exc_tb = sys.exc_info()
+ traceback.print_exception(exc_type, exc_value, exc_tb)
+ except AttributeError:
+ print('Unrecoverable Error in completions')
+
+ @staticmethod
+ def _get_completions(body, offset, cursor_position, ipyc):
+ """
+ Private equivalent of get_completions() use only for unit_testing.
+ """
+ debug = getattr(ipyc, 'debug', False)
+ completions = _deduplicate_completions(
+ body, ipyc.completions(body, offset))
+ for c in completions:
+ if not c.text:
+ # Guard against completion machinery giving us an empty string.
+ continue
+ text = unicodedata.normalize('NFC', c.text)
+ # 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(text[0]) == 0:
+ if cursor_position + c.start > 0:
+ char_before = body[c.start - 1]
+ fixed_text = unicodedata.normalize(
+ 'NFC', char_before + text)
+
+ # Yield the modified completion instead, if this worked.
+ if wcwidth(text[0:1]) == 1:
+ yield Completion(fixed_text, start_position=c.start - offset - 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)
+ display_text = c.text
+
+ adjusted_text = _adjust_completion_text_based_on_context(c.text, body, offset)
+ if c.type == 'function':
+ yield Completion(adjusted_text, start_position=c.start - offset, display=_elide(display_text+'()', body[c.start:c.end]), display_meta=c.type+c.signature)
+ else:
+ yield Completion(adjusted_text, start_position=c.start - offset, display=_elide(display_text, body[c.start:c.end]), display_meta=c.type)
+
+class IPythonPTLexer(Lexer):
+ """
+ Wrapper around PythonLexer and BashLexer.
+ """
+ def __init__(self):
+ l = pygments_lexers
+ self.python_lexer = PygmentsLexer(l.Python3Lexer)
+ 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, 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(document)
diff --git a/contrib/python/ipython/py3/IPython/terminal/shortcuts.py b/contrib/python/ipython/py3/IPython/terminal/shortcuts.py
index 6f4468b3a5..a23fa091a0 100644
--- a/contrib/python/ipython/py3/IPython/terminal/shortcuts.py
+++ b/contrib/python/ipython/py3/IPython/terminal/shortcuts.py
@@ -1,276 +1,276 @@
-"""
-Module to define and register Terminal IPython shortcuts with
-:mod:`prompt_toolkit`
-"""
-
-# Copyright (c) IPython Development Team.
-# Distributed under the terms of the Modified BSD License.
-
-import warnings
-import signal
-import sys
-from typing import Callable
-
-
-from prompt_toolkit.application.current import get_app
-from prompt_toolkit.enums import DEFAULT_BUFFER, SEARCH_BUFFER
-from prompt_toolkit.filters import (has_focus, has_selection, Condition,
- vi_insert_mode, emacs_insert_mode, has_completions, vi_mode)
-from prompt_toolkit.key_binding.bindings.completion import display_completions_like_readline
-from prompt_toolkit.key_binding import KeyBindings
-
-from IPython.utils.decorators import undoc
-
-@undoc
-@Condition
-def cursor_in_leading_ws():
- before = get_app().current_buffer.document.current_line_before_cursor
- return (not before) or before.isspace()
-
-
-def create_ipython_shortcuts(shell):
- """Set up the prompt_toolkit keyboard shortcuts for IPython"""
-
- kb = KeyBindings()
- insert_mode = vi_insert_mode | emacs_insert_mode
-
- if getattr(shell, 'handle_return', None):
- return_handler = shell.handle_return(shell)
- else:
- return_handler = newline_or_execute_outer(shell)
-
- kb.add('enter', filter=(has_focus(DEFAULT_BUFFER)
- & ~has_selection
- & insert_mode
- ))(return_handler)
-
- def reformat_and_execute(event):
- reformat_text_before_cursor(event.current_buffer, event.current_buffer.document, shell)
- event.current_buffer.validate_and_handle()
-
- kb.add('escape', 'enter', filter=(has_focus(DEFAULT_BUFFER)
- & ~has_selection
- & insert_mode
- ))(reformat_and_execute)
-
- kb.add('c-\\')(force_exit)
-
- kb.add('c-p', filter=(vi_insert_mode & has_focus(DEFAULT_BUFFER))
- )(previous_history_or_previous_completion)
-
- kb.add('c-n', filter=(vi_insert_mode & has_focus(DEFAULT_BUFFER))
- )(next_history_or_next_completion)
-
- kb.add('c-g', filter=(has_focus(DEFAULT_BUFFER) & has_completions)
- )(dismiss_completion)
-
- kb.add('c-c', filter=has_focus(DEFAULT_BUFFER))(reset_buffer)
-
- kb.add('c-c', filter=has_focus(SEARCH_BUFFER))(reset_search_buffer)
-
- supports_suspend = Condition(lambda: hasattr(signal, 'SIGTSTP'))
- kb.add('c-z', filter=supports_suspend)(suspend_to_bg)
-
- # Ctrl+I == Tab
- kb.add('tab', filter=(has_focus(DEFAULT_BUFFER)
- & ~has_selection
- & insert_mode
- & cursor_in_leading_ws
- ))(indent_buffer)
- kb.add('c-o', filter=(has_focus(DEFAULT_BUFFER) & emacs_insert_mode)
- )(newline_autoindent_outer(shell.input_transformer_manager))
-
- kb.add('f2', filter=has_focus(DEFAULT_BUFFER))(open_input_in_editor)
-
- if shell.display_completions == 'readlinelike':
- kb.add('c-i', filter=(has_focus(DEFAULT_BUFFER)
- & ~has_selection
- & insert_mode
- & ~cursor_in_leading_ws
- ))(display_completions_like_readline)
-
- if sys.platform == 'win32':
- kb.add('c-v', filter=(has_focus(DEFAULT_BUFFER) & ~vi_mode))(win_paste)
-
- return kb
-
-
-def reformat_text_before_cursor(buffer, document, shell):
- text = buffer.delete_before_cursor(len(document.text[:document.cursor_position]))
- try:
- formatted_text = shell.reformat_handler(text)
- buffer.insert_text(formatted_text)
- except Exception as e:
- buffer.insert_text(text)
-
-
-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:
- check_text = d.text
- else:
- check_text = d.text[:d.cursor_position]
- status, indent = shell.check_complete(check_text)
-
- # if all we have after the cursor is whitespace: reformat current text
- # before cursor
- after_cursor = d.text[d.cursor_position:]
- reformatted = False
- if not after_cursor.strip():
- reformat_text_before_cursor(b, d, shell)
- reformatted = True
- if not (d.on_last_line or
- d.cursor_position_row >= d.line_count - d.empty_line_count_at_the_end()
- ):
- if shell.autoindent:
- b.insert_text('\n' + indent)
- else:
- b.insert_text('\n')
- return
-
- if (status != 'incomplete') and b.accept_handler:
- if not reformatted:
- reformat_text_before_cursor(b, d, shell)
- b.validate_and_handle()
- else:
- if shell.autoindent:
- b.insert_text('\n' + indent)
- else:
- b.insert_text('\n')
- 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.app.layout.focus(DEFAULT_BUFFER)
-
-def suspend_to_bg(event):
- event.app.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)
-
-@undoc
-def newline_with_copy_margin(event):
- """
- DEPRECATED since IPython 6.0
-
- See :any:`newline_autoindent_outer` for a replacement.
-
- Preserve margin and cursor position when using
- Control-O to insert a newline in EMACS mode
- """
- warnings.warn("`newline_with_copy_margin(event)` is deprecated since IPython 6.0. "
- "see `newline_autoindent_outer(shell)(event)` for a replacement.",
- DeprecationWarning, stacklevel=2)
-
- 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 newline_autoindent_outer(inputsplitter) -> Callable[..., None]:
- """
- Return a function suitable for inserting a indented newline after the cursor.
-
- Fancier version of deprecated ``newline_with_copy_margin`` which should
- compute the correct indentation of the inserted line. That is to say, indent
- by 4 extra space after a function definition, class definition, context
- manager... And dedent by 4 space after ``pass``, ``return``, ``raise ...``.
- """
-
- def newline_autoindent(event):
- """insert a newline after the cursor indented appropriately."""
- b = event.current_buffer
- d = b.document
-
- if b.complete_state:
- b.cancel_completion()
- text = d.text[:d.cursor_position] + '\n'
- _, indent = inputsplitter.check_complete(text)
- b.insert_text('\n' + (' ' * (indent or 0)), move_cursor=False)
-
- return newline_autoindent
-
-
-def open_input_in_editor(event):
- event.app.current_buffer.open_in_editor()
-
-
-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))
+"""
+Module to define and register Terminal IPython shortcuts with
+:mod:`prompt_toolkit`
+"""
+
+# Copyright (c) IPython Development Team.
+# Distributed under the terms of the Modified BSD License.
+
+import warnings
+import signal
+import sys
+from typing import Callable
+
+
+from prompt_toolkit.application.current import get_app
+from prompt_toolkit.enums import DEFAULT_BUFFER, SEARCH_BUFFER
+from prompt_toolkit.filters import (has_focus, has_selection, Condition,
+ vi_insert_mode, emacs_insert_mode, has_completions, vi_mode)
+from prompt_toolkit.key_binding.bindings.completion import display_completions_like_readline
+from prompt_toolkit.key_binding import KeyBindings
+
+from IPython.utils.decorators import undoc
+
+@undoc
+@Condition
+def cursor_in_leading_ws():
+ before = get_app().current_buffer.document.current_line_before_cursor
+ return (not before) or before.isspace()
+
+
+def create_ipython_shortcuts(shell):
+ """Set up the prompt_toolkit keyboard shortcuts for IPython"""
+
+ kb = KeyBindings()
+ insert_mode = vi_insert_mode | emacs_insert_mode
+
+ if getattr(shell, 'handle_return', None):
+ return_handler = shell.handle_return(shell)
+ else:
+ return_handler = newline_or_execute_outer(shell)
+
+ kb.add('enter', filter=(has_focus(DEFAULT_BUFFER)
+ & ~has_selection
+ & insert_mode
+ ))(return_handler)
+
+ def reformat_and_execute(event):
+ reformat_text_before_cursor(event.current_buffer, event.current_buffer.document, shell)
+ event.current_buffer.validate_and_handle()
+
+ kb.add('escape', 'enter', filter=(has_focus(DEFAULT_BUFFER)
+ & ~has_selection
+ & insert_mode
+ ))(reformat_and_execute)
+
+ kb.add('c-\\')(force_exit)
+
+ kb.add('c-p', filter=(vi_insert_mode & has_focus(DEFAULT_BUFFER))
+ )(previous_history_or_previous_completion)
+
+ kb.add('c-n', filter=(vi_insert_mode & has_focus(DEFAULT_BUFFER))
+ )(next_history_or_next_completion)
+
+ kb.add('c-g', filter=(has_focus(DEFAULT_BUFFER) & has_completions)
+ )(dismiss_completion)
+
+ kb.add('c-c', filter=has_focus(DEFAULT_BUFFER))(reset_buffer)
+
+ kb.add('c-c', filter=has_focus(SEARCH_BUFFER))(reset_search_buffer)
+
+ supports_suspend = Condition(lambda: hasattr(signal, 'SIGTSTP'))
+ kb.add('c-z', filter=supports_suspend)(suspend_to_bg)
+
+ # Ctrl+I == Tab
+ kb.add('tab', filter=(has_focus(DEFAULT_BUFFER)
+ & ~has_selection
+ & insert_mode
+ & cursor_in_leading_ws
+ ))(indent_buffer)
+ kb.add('c-o', filter=(has_focus(DEFAULT_BUFFER) & emacs_insert_mode)
+ )(newline_autoindent_outer(shell.input_transformer_manager))
+
+ kb.add('f2', filter=has_focus(DEFAULT_BUFFER))(open_input_in_editor)
+
+ if shell.display_completions == 'readlinelike':
+ kb.add('c-i', filter=(has_focus(DEFAULT_BUFFER)
+ & ~has_selection
+ & insert_mode
+ & ~cursor_in_leading_ws
+ ))(display_completions_like_readline)
+
+ if sys.platform == 'win32':
+ kb.add('c-v', filter=(has_focus(DEFAULT_BUFFER) & ~vi_mode))(win_paste)
+
+ return kb
+
+
+def reformat_text_before_cursor(buffer, document, shell):
+ text = buffer.delete_before_cursor(len(document.text[:document.cursor_position]))
+ try:
+ formatted_text = shell.reformat_handler(text)
+ buffer.insert_text(formatted_text)
+ except Exception as e:
+ buffer.insert_text(text)
+
+
+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:
+ check_text = d.text
+ else:
+ check_text = d.text[:d.cursor_position]
+ status, indent = shell.check_complete(check_text)
+
+ # if all we have after the cursor is whitespace: reformat current text
+ # before cursor
+ after_cursor = d.text[d.cursor_position:]
+ reformatted = False
+ if not after_cursor.strip():
+ reformat_text_before_cursor(b, d, shell)
+ reformatted = True
+ if not (d.on_last_line or
+ d.cursor_position_row >= d.line_count - d.empty_line_count_at_the_end()
+ ):
+ if shell.autoindent:
+ b.insert_text('\n' + indent)
+ else:
+ b.insert_text('\n')
+ return
+
+ if (status != 'incomplete') and b.accept_handler:
+ if not reformatted:
+ reformat_text_before_cursor(b, d, shell)
+ b.validate_and_handle()
+ else:
+ if shell.autoindent:
+ b.insert_text('\n' + indent)
+ else:
+ b.insert_text('\n')
+ 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.app.layout.focus(DEFAULT_BUFFER)
+
+def suspend_to_bg(event):
+ event.app.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)
+
+@undoc
+def newline_with_copy_margin(event):
+ """
+ DEPRECATED since IPython 6.0
+
+ See :any:`newline_autoindent_outer` for a replacement.
+
+ Preserve margin and cursor position when using
+ Control-O to insert a newline in EMACS mode
+ """
+ warnings.warn("`newline_with_copy_margin(event)` is deprecated since IPython 6.0. "
+ "see `newline_autoindent_outer(shell)(event)` for a replacement.",
+ DeprecationWarning, stacklevel=2)
+
+ 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 newline_autoindent_outer(inputsplitter) -> Callable[..., None]:
+ """
+ Return a function suitable for inserting a indented newline after the cursor.
+
+ Fancier version of deprecated ``newline_with_copy_margin`` which should
+ compute the correct indentation of the inserted line. That is to say, indent
+ by 4 extra space after a function definition, class definition, context
+ manager... And dedent by 4 space after ``pass``, ``return``, ``raise ...``.
+ """
+
+ def newline_autoindent(event):
+ """insert a newline after the cursor indented appropriately."""
+ b = event.current_buffer
+ d = b.document
+
+ if b.complete_state:
+ b.cancel_completion()
+ text = d.text[:d.cursor_position] + '\n'
+ _, indent = inputsplitter.check_complete(text)
+ b.insert_text('\n' + (' ' * (indent or 0)), move_cursor=False)
+
+ return newline_autoindent
+
+
+def open_input_in_editor(event):
+ event.app.current_buffer.open_in_editor()
+
+
+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))