diff options
author | Nikita Slyusarev <nslus@yandex-team.com> | 2022-02-10 16:46:52 +0300 |
---|---|---|
committer | Daniil Cherednik <dcherednik@yandex-team.ru> | 2022-02-10 16:46:52 +0300 |
commit | cd77cecfc03a3eaf87816af28a33067c4f0cdb59 (patch) | |
tree | 1308e0bae862d52e0020d881fe758080437fe389 /contrib/python | |
parent | cdae02d225fb5b3afbb28990e79a7ac6c9125327 (diff) | |
download | ydb-cd77cecfc03a3eaf87816af28a33067c4f0cdb59.tar.gz |
Restoring authorship annotation for Nikita Slyusarev <nslus@yandex-team.com>. Commit 1 of 2.
Diffstat (limited to 'contrib/python')
190 files changed, 13740 insertions, 13740 deletions
diff --git a/contrib/python/PyYAML/py2/ya.make b/contrib/python/PyYAML/py2/ya.make index 1ec5c0c301..372005867d 100644 --- a/contrib/python/PyYAML/py2/ya.make +++ b/contrib/python/PyYAML/py2/ya.make @@ -3,7 +3,7 @@ PY2_LIBRARY() LICENSE(MIT) VERSION(5.4.1) - + OWNER(g:python-contrib borman g:testenv) PEERDIR( diff --git a/contrib/python/PyYAML/py3/ya.make b/contrib/python/PyYAML/py3/ya.make index 0401c04651..ff032997c8 100644 --- a/contrib/python/PyYAML/py3/ya.make +++ b/contrib/python/PyYAML/py3/ya.make @@ -3,7 +3,7 @@ PY3_LIBRARY() LICENSE(MIT) VERSION(5.4.1) - + OWNER(g:python-contrib borman g:testenv) PEERDIR( diff --git a/contrib/python/PyYAML/ya.make b/contrib/python/PyYAML/ya.make index a604fce51f..80a68a1512 100644 --- a/contrib/python/PyYAML/ya.make +++ b/contrib/python/PyYAML/ya.make @@ -1,9 +1,9 @@ -PY23_LIBRARY() +PY23_LIBRARY() LICENSE(MIT) OWNER(g:python-contrib) - + IF (PYTHON2) PEERDIR( contrib/python/PyYAML/py2 diff --git a/contrib/python/cryptography/.dist-info/METADATA b/contrib/python/cryptography/.dist-info/METADATA index 7abd5f9465..6984988c85 100644 --- a/contrib/python/cryptography/.dist-info/METADATA +++ b/contrib/python/cryptography/.dist-info/METADATA @@ -1,131 +1,131 @@ -Metadata-Version: 2.1 -Name: cryptography +Metadata-Version: 2.1 +Name: cryptography Version: 3.3.2 -Summary: cryptography is a package which provides cryptographic recipes and primitives to Python developers. -Home-page: https://github.com/pyca/cryptography -Author: The cryptography developers -Author-email: cryptography-dev@python.org -License: BSD or Apache License, Version 2.0 -Platform: UNKNOWN -Classifier: Development Status :: 5 - Production/Stable -Classifier: Intended Audience :: Developers -Classifier: License :: OSI Approved :: Apache Software License -Classifier: License :: OSI Approved :: BSD License -Classifier: Natural Language :: English -Classifier: Operating System :: MacOS :: MacOS X -Classifier: Operating System :: POSIX -Classifier: Operating System :: POSIX :: BSD -Classifier: Operating System :: POSIX :: Linux -Classifier: Operating System :: Microsoft :: Windows -Classifier: Programming Language :: Python -Classifier: Programming Language :: Python :: 2 -Classifier: Programming Language :: Python :: 2.7 -Classifier: Programming Language :: Python :: 3 -Classifier: Programming Language :: Python :: 3.6 -Classifier: Programming Language :: Python :: 3.7 +Summary: cryptography is a package which provides cryptographic recipes and primitives to Python developers. +Home-page: https://github.com/pyca/cryptography +Author: The cryptography developers +Author-email: cryptography-dev@python.org +License: BSD or Apache License, Version 2.0 +Platform: UNKNOWN +Classifier: Development Status :: 5 - Production/Stable +Classifier: Intended Audience :: Developers +Classifier: License :: OSI Approved :: Apache Software License +Classifier: License :: OSI Approved :: BSD License +Classifier: Natural Language :: English +Classifier: Operating System :: MacOS :: MacOS X +Classifier: Operating System :: POSIX +Classifier: Operating System :: POSIX :: BSD +Classifier: Operating System :: POSIX :: Linux +Classifier: Operating System :: Microsoft :: Windows +Classifier: Programming Language :: Python +Classifier: Programming Language :: Python :: 2 +Classifier: Programming Language :: Python :: 2.7 +Classifier: Programming Language :: Python :: 3 +Classifier: Programming Language :: Python :: 3.6 +Classifier: Programming Language :: Python :: 3.7 Classifier: Programming Language :: Python :: 3.8 Classifier: Programming Language :: Python :: 3.9 -Classifier: Programming Language :: Python :: Implementation :: CPython -Classifier: Programming Language :: Python :: Implementation :: PyPy -Classifier: Topic :: Security :: Cryptography +Classifier: Programming Language :: Python :: Implementation :: CPython +Classifier: Programming Language :: Python :: Implementation :: PyPy +Classifier: Topic :: Security :: Cryptography Requires-Python: >=2.7,!=3.0.*,!=3.1.*,!=3.2.*,!=3.3.*,!=3.4.*,!=3.5.* Description-Content-Type: text/x-rst -Requires-Dist: six (>=1.4.1) +Requires-Dist: six (>=1.4.1) Requires-Dist: cffi (>=1.12) Requires-Dist: enum34 ; python_version < '3' Requires-Dist: ipaddress ; python_version < '3' -Provides-Extra: docs +Provides-Extra: docs Requires-Dist: sphinx (!=1.8.0,!=3.1.0,!=3.1.1,>=1.6.5) ; extra == 'docs' Requires-Dist: sphinx-rtd-theme ; extra == 'docs' -Provides-Extra: docstest +Provides-Extra: docstest Requires-Dist: doc8 ; extra == 'docstest' Requires-Dist: pyenchant (>=1.6.11) ; extra == 'docstest' Requires-Dist: twine (>=1.12.0) ; extra == 'docstest' Requires-Dist: sphinxcontrib-spelling (>=4.0.1) ; extra == 'docstest' -Provides-Extra: pep8test +Provides-Extra: pep8test Requires-Dist: black ; extra == 'pep8test' Requires-Dist: flake8 ; extra == 'pep8test' Requires-Dist: flake8-import-order ; extra == 'pep8test' Requires-Dist: pep8-naming ; extra == 'pep8test' Provides-Extra: ssh Requires-Dist: bcrypt (>=3.1.5) ; extra == 'ssh' -Provides-Extra: test +Provides-Extra: test Requires-Dist: pytest (!=3.9.0,!=3.9.1,!=3.9.2,>=3.6.0) ; extra == 'test' Requires-Dist: pretend ; extra == 'test' Requires-Dist: iso8601 ; extra == 'test' Requires-Dist: pytz ; extra == 'test' Requires-Dist: hypothesis (!=3.79.2,>=1.11.4) ; extra == 'test' - -pyca/cryptography -================= - -.. image:: https://img.shields.io/pypi/v/cryptography.svg - :target: https://pypi.org/project/cryptography/ - :alt: Latest Version - -.. image:: https://readthedocs.org/projects/cryptography/badge/?version=latest - :target: https://cryptography.io - :alt: Latest Docs - + +pyca/cryptography +================= + +.. image:: https://img.shields.io/pypi/v/cryptography.svg + :target: https://pypi.org/project/cryptography/ + :alt: Latest Version + +.. image:: https://readthedocs.org/projects/cryptography/badge/?version=latest + :target: https://cryptography.io + :alt: Latest Docs + .. image:: https://github.com/pyca/cryptography/workflows/CI/badge.svg?branch=master :target: https://github.com/pyca/cryptography/actions?query=workflow%3ACI+branch%3Amaster - -.. image:: https://codecov.io/github/pyca/cryptography/coverage.svg?branch=master - :target: https://codecov.io/github/pyca/cryptography?branch=master - - -``cryptography`` is a package which provides cryptographic recipes and -primitives to Python developers. Our goal is for it to be your "cryptographic + +.. image:: https://codecov.io/github/pyca/cryptography/coverage.svg?branch=master + :target: https://codecov.io/github/pyca/cryptography?branch=master + + +``cryptography`` is a package which provides cryptographic recipes and +primitives to Python developers. Our goal is for it to be your "cryptographic standard library". It supports Python 2.7, Python 3.6+, and PyPy 5.4+. - -``cryptography`` includes both high level recipes and low level interfaces to -common cryptographic algorithms such as symmetric ciphers, message digests, and -key derivation functions. For example, to encrypt something with -``cryptography``'s high level symmetric encryption recipe: - -.. code-block:: pycon - - >>> from cryptography.fernet import Fernet - >>> # Put this somewhere safe! - >>> key = Fernet.generate_key() - >>> f = Fernet(key) - >>> token = f.encrypt(b"A really secret message. Not for prying eyes.") - >>> token - '...' - >>> f.decrypt(token) - 'A really secret message. Not for prying eyes.' - -You can find more information in the `documentation`_. - -You can install ``cryptography`` with: - -.. code-block:: console - - $ pip install cryptography - -For full details see `the installation documentation`_. - -Discussion -~~~~~~~~~~ - -If you run into bugs, you can file them in our `issue tracker`_. - -We maintain a `cryptography-dev`_ mailing list for development discussion. - -You can also join ``#cryptography-dev`` on Freenode to ask questions or get -involved. - -Security -~~~~~~~~ - -Need to report a security issue? Please consult our `security reporting`_ -documentation. - - -.. _`documentation`: https://cryptography.io/ + +``cryptography`` includes both high level recipes and low level interfaces to +common cryptographic algorithms such as symmetric ciphers, message digests, and +key derivation functions. For example, to encrypt something with +``cryptography``'s high level symmetric encryption recipe: + +.. code-block:: pycon + + >>> from cryptography.fernet import Fernet + >>> # Put this somewhere safe! + >>> key = Fernet.generate_key() + >>> f = Fernet(key) + >>> token = f.encrypt(b"A really secret message. Not for prying eyes.") + >>> token + '...' + >>> f.decrypt(token) + 'A really secret message. Not for prying eyes.' + +You can find more information in the `documentation`_. + +You can install ``cryptography`` with: + +.. code-block:: console + + $ pip install cryptography + +For full details see `the installation documentation`_. + +Discussion +~~~~~~~~~~ + +If you run into bugs, you can file them in our `issue tracker`_. + +We maintain a `cryptography-dev`_ mailing list for development discussion. + +You can also join ``#cryptography-dev`` on Freenode to ask questions or get +involved. + +Security +~~~~~~~~ + +Need to report a security issue? Please consult our `security reporting`_ +documentation. + + +.. _`documentation`: https://cryptography.io/ .. _`the installation documentation`: https://cryptography.io/en/latest/installation.html -.. _`issue tracker`: https://github.com/pyca/cryptography/issues -.. _`cryptography-dev`: https://mail.python.org/mailman/listinfo/cryptography-dev +.. _`issue tracker`: https://github.com/pyca/cryptography/issues +.. _`cryptography-dev`: https://mail.python.org/mailman/listinfo/cryptography-dev .. _`security reporting`: https://cryptography.io/en/latest/security.html - - + + diff --git a/contrib/python/cryptography/.dist-info/top_level.txt b/contrib/python/cryptography/.dist-info/top_level.txt index 52ccfc6e37..cb0afcc11d 100644 --- a/contrib/python/cryptography/.dist-info/top_level.txt +++ b/contrib/python/cryptography/.dist-info/top_level.txt @@ -1,3 +1,3 @@ _openssl _padding -cryptography +cryptography diff --git a/contrib/python/cryptography/ya.make b/contrib/python/cryptography/ya.make index d63bb62f6a..7d6b5ba94c 100644 --- a/contrib/python/cryptography/ya.make +++ b/contrib/python/cryptography/ya.make @@ -25,12 +25,12 @@ PEERDIR( NO_COMPILER_WARNINGS() NO_LINT() -RESOURCE_FILES( - PREFIX contrib/python/cryptography/ - .dist-info/METADATA - .dist-info/top_level.txt -) - +RESOURCE_FILES( + PREFIX contrib/python/cryptography/ + .dist-info/METADATA + .dist-info/top_level.txt +) + SRCS( build/temp.linux-x86_64-2.7/_openssl.c build/temp.linux-x86_64-2.7/_padding.c diff --git a/contrib/python/ipython/py2/IPython/core/alias.py b/contrib/python/ipython/py2/IPython/core/alias.py index 28a9ccb00d..be4e7eebed 100644 --- a/contrib/python/ipython/py2/IPython/core/alias.py +++ b/contrib/python/ipython/py2/IPython/core/alias.py @@ -29,7 +29,7 @@ from IPython.core.error import UsageError from IPython.utils.py3compat import string_types from traitlets import List, Instance -from logging import error +from logging import error #----------------------------------------------------------------------------- # Utilities @@ -192,8 +192,8 @@ class Alias(object): class AliasManager(Configurable): - default_aliases = List(default_aliases()).tag(config=True) - user_aliases = List(default_value=[]).tag(config=True) + default_aliases = List(default_aliases()).tag(config=True) + user_aliases = List(default_value=[]).tag(config=True) shell = Instance('IPython.core.interactiveshell.InteractiveShellABC', allow_none=True) def __init__(self, shell=None, **kwargs): diff --git a/contrib/python/ipython/py2/IPython/core/application.py b/contrib/python/ipython/py2/IPython/core/application.py index af28133945..32983540e7 100644 --- a/contrib/python/ipython/py2/IPython/core/application.py +++ b/contrib/python/ipython/py2/IPython/core/application.py @@ -13,7 +13,7 @@ object and then create the configurable objects, passing the config to them. # Distributed under the terms of the Modified BSD License. import atexit -from copy import deepcopy +from copy import deepcopy import glob import logging import os @@ -27,10 +27,10 @@ from IPython.core.profiledir import ProfileDir, ProfileDirError from IPython.paths import get_ipython_dir, get_ipython_package_dir from IPython.utils.path import ensure_dir_exists from IPython.utils import py3compat -from traitlets import ( - List, Unicode, Type, Bool, Dict, Set, Instance, Undefined, - default, observe, -) +from traitlets import ( + List, Unicode, Type, Bool, Dict, Set, Instance, Undefined, + default, observe, +) if os.name == 'nt': programdata = os.environ.get('PROGRAMDATA', None) @@ -52,16 +52,16 @@ if _env_config_dir not in SYSTEM_CONFIG_DIRS: ENV_CONFIG_DIRS.append(_env_config_dir) -_envvar = os.environ.get('IPYTHON_SUPPRESS_CONFIG_ERRORS') -if _envvar in {None, ''}: - IPYTHON_SUPPRESS_CONFIG_ERRORS = None -else: - if _envvar.lower() in {'1','true'}: - IPYTHON_SUPPRESS_CONFIG_ERRORS = True - elif _envvar.lower() in {'0','false'} : - IPYTHON_SUPPRESS_CONFIG_ERRORS = False - else: - sys.exit("Unsupported value for environment variable: 'IPYTHON_SUPPRESS_CONFIG_ERRORS' is set to '%s' which is none of {'0', '1', 'false', 'true', ''}."% _envvar ) +_envvar = os.environ.get('IPYTHON_SUPPRESS_CONFIG_ERRORS') +if _envvar in {None, ''}: + IPYTHON_SUPPRESS_CONFIG_ERRORS = None +else: + if _envvar.lower() in {'1','true'}: + IPYTHON_SUPPRESS_CONFIG_ERRORS = True + elif _envvar.lower() in {'0','false'} : + IPYTHON_SUPPRESS_CONFIG_ERRORS = False + else: + sys.exit("Unsupported value for environment variable: 'IPYTHON_SUPPRESS_CONFIG_ERRORS' is set to '%s' which is none of {'0', '1', 'false', 'true', ''}."% _envvar ) # aliases and flags @@ -118,13 +118,13 @@ class BaseIPythonApplication(Application): config_file_specified = Set() config_file_name = Unicode() - @default('config_file_name') + @default('config_file_name') def _config_file_name_default(self): return self.name.replace('-','_') + u'_config.py' - @observe('config_file_name') - def _config_file_name_changed(self, change): - if change['new'] != change['old']: - self.config_file_specified.add(change['new']) + @observe('config_file_name') + def _config_file_name_changed(self, change): + if change['new'] != change['old']: + self.config_file_specified.add(change['new']) # The directory that contains IPython's builtin profiles. builtin_profile_dir = Unicode( @@ -132,19 +132,19 @@ class BaseIPythonApplication(Application): ) config_file_paths = List(Unicode()) - @default('config_file_paths') + @default('config_file_paths') def _config_file_paths_default(self): return [py3compat.getcwd()] - extra_config_file = Unicode( + extra_config_file = Unicode( help="""Path to an extra config file to load. If specified, load this config file in addition to any other IPython config. - """).tag(config=True) - @observe('extra_config_file') - def _extra_config_file_changed(self, change): - old = change['old'] - new = change['new'] + """).tag(config=True) + @observe('extra_config_file') + def _extra_config_file_changed(self, change): + old = change['old'] + new = change['new'] try: self.config_files.remove(old) except ValueError: @@ -152,37 +152,37 @@ class BaseIPythonApplication(Application): self.config_file_specified.add(new) self.config_files.append(new) - profile = Unicode(u'default', + profile = Unicode(u'default', help="""The IPython profile to use.""" - ).tag(config=True) - - @observe('profile') - def _profile_changed(self, change): + ).tag(config=True) + + @observe('profile') + def _profile_changed(self, change): self.builtin_profile_dir = os.path.join( - get_ipython_package_dir(), u'config', u'profile', change['new'] + get_ipython_package_dir(), u'config', u'profile', change['new'] ) - ipython_dir = Unicode( + ipython_dir = Unicode( help=""" The name of the IPython directory. This directory is used for logging configuration (through profiles), history storage, etc. The default is usually $HOME/.ipython. This option can also be specified through the environment variable IPYTHONDIR. """ - ).tag(config=True) - @default('ipython_dir') + ).tag(config=True) + @default('ipython_dir') def _ipython_dir_default(self): d = get_ipython_dir() - self._ipython_dir_changed({ - 'name': 'ipython_dir', - 'old': d, - 'new': d, - }) + self._ipython_dir_changed({ + 'name': 'ipython_dir', + 'old': d, + 'new': d, + }) return d _in_init_profile_dir = False profile_dir = Instance(ProfileDir, allow_none=True) - @default('profile_dir') + @default('profile_dir') def _profile_dir_default(self): # avoid recursion if self._in_init_profile_dir: @@ -191,29 +191,29 @@ class BaseIPythonApplication(Application): self.init_profile_dir() return self.profile_dir - overwrite = Bool(False, - help="""Whether to overwrite existing config files when copying""" - ).tag(config=True) - auto_create = Bool(False, - help="""Whether to create profile dir if it doesn't exist""" - ).tag(config=True) + overwrite = Bool(False, + help="""Whether to overwrite existing config files when copying""" + ).tag(config=True) + auto_create = Bool(False, + help="""Whether to create profile dir if it doesn't exist""" + ).tag(config=True) config_files = List(Unicode()) - @default('config_files') + @default('config_files') def _config_files_default(self): return [self.config_file_name] - copy_config_files = Bool(False, + copy_config_files = Bool(False, help="""Whether to install the default config files into the profile dir. If a new profile is being created, and IPython contains config files for that profile, then they will be staged into the new directory. Otherwise, default config files will be automatically generated. - """).tag(config=True) + """).tag(config=True) - verbose_crash = Bool(False, + verbose_crash = Bool(False, help="""Create a massive crash report when IPython encounters what may be an internal error. The default is to append a short message to the - usual traceback""").tag(config=True) + usual traceback""").tag(config=True) # The class to use as the crash handler. crash_handler_class = Type(crashhandler.CrashHandler) @@ -239,8 +239,8 @@ class BaseIPythonApplication(Application): if subc in self.deprecated_subcommands: self.log.warning("Subcommand `ipython {sub}` is deprecated and will be removed " "in future versions.".format(sub=subc)) - self.log.warning("You likely want to use `jupyter {sub}` in the " - "future".format(sub=subc)) + self.log.warning("You likely want to use `jupyter {sub}` in the " + "future".format(sub=subc)) return super(BaseIPythonApplication, self).initialize_subcommand(subc, argv) def init_crash_handler(self): @@ -262,11 +262,11 @@ class BaseIPythonApplication(Application): return self.crash_handler(etype, evalue, tb) else: return crashhandler.crash_handler_lite(etype, evalue, tb) - - @observe('ipython_dir') - def _ipython_dir_changed(self, change): - old = change['old'] - new = change['new'] + + @observe('ipython_dir') + def _ipython_dir_changed(self, change): + old = change['old'] + new = change['new'] if old is not Undefined: str_old = py3compat.cast_bytes_py2(os.path.abspath(old), sys.getfilesystemencoding() @@ -291,33 +291,33 @@ class BaseIPythonApplication(Application): self.log.error("couldn't create path %s: %s", path, e) self.log.debug("IPYTHONDIR set to: %s" % new) - def load_config_file(self, suppress_errors=IPYTHON_SUPPRESS_CONFIG_ERRORS): + def load_config_file(self, suppress_errors=IPYTHON_SUPPRESS_CONFIG_ERRORS): """Load the config file. By default, errors in loading config are handled, and a warning printed on screen. For testing, the suppress_errors option is set to False, so errors will make tests fail. - - `supress_errors` default value is to be `None` in which case the - behavior default to the one of `traitlets.Application`. - - The default value can be set : - - to `False` by setting 'IPYTHON_SUPPRESS_CONFIG_ERRORS' environment variable to '0', or 'false' (case insensitive). - - to `True` by setting 'IPYTHON_SUPPRESS_CONFIG_ERRORS' environment variable to '1' or 'true' (case insensitive). - - to `None` by setting 'IPYTHON_SUPPRESS_CONFIG_ERRORS' environment variable to '' (empty string) or leaving it unset. - - Any other value are invalid, and will make IPython exit with a non-zero return code. + + `supress_errors` default value is to be `None` in which case the + behavior default to the one of `traitlets.Application`. + + The default value can be set : + - to `False` by setting 'IPYTHON_SUPPRESS_CONFIG_ERRORS' environment variable to '0', or 'false' (case insensitive). + - to `True` by setting 'IPYTHON_SUPPRESS_CONFIG_ERRORS' environment variable to '1' or 'true' (case insensitive). + - to `None` by setting 'IPYTHON_SUPPRESS_CONFIG_ERRORS' environment variable to '' (empty string) or leaving it unset. + + Any other value are invalid, and will make IPython exit with a non-zero return code. """ - - + + self.log.debug("Searching path %s for config files", self.config_file_paths) base_config = 'ipython_config.py' self.log.debug("Attempting to load config file: %s" % base_config) try: - if suppress_errors is not None: - old_value = Application.raise_config_file_errors - Application.raise_config_file_errors = not suppress_errors; + if suppress_errors is not None: + old_value = Application.raise_config_file_errors + Application.raise_config_file_errors = not suppress_errors; Application.load_config_file( self, base_config, @@ -327,8 +327,8 @@ class BaseIPythonApplication(Application): # ignore errors loading parent self.log.debug("Config file %s not found", base_config) pass - if suppress_errors is not None: - Application.raise_config_file_errors = old_value + if suppress_errors is not None: + Application.raise_config_file_errors = old_value for config_file_name in self.config_files: if not config_file_name or config_file_name == base_config: @@ -457,9 +457,9 @@ class BaseIPythonApplication(Application): if self.subapp is not None: # stop here if subapp is taking over return - # save a copy of CLI config to re-load after config files - # so that it has highest priority - cl_config = deepcopy(self.config) + # save a copy of CLI config to re-load after config files + # so that it has highest priority + cl_config = deepcopy(self.config) self.init_profile_dir() self.init_config_files() self.load_config_file() diff --git a/contrib/python/ipython/py2/IPython/core/builtin_trap.py b/contrib/python/ipython/py2/IPython/core/builtin_trap.py index 909a555c73..ff857be949 100644 --- a/contrib/python/ipython/py2/IPython/core/builtin_trap.py +++ b/contrib/python/ipython/py2/IPython/core/builtin_trap.py @@ -57,7 +57,7 @@ class BuiltinTrap(Configurable): from IPython.lib import deepreload if self.shell.deep_reload: from warnings import warn - warn("Automatically replacing builtin `reload` by `deepreload.reload` is deprecated since IPython 4.0, please import `reload` explicitly from `IPython.lib.deepreload", DeprecationWarning) + warn("Automatically replacing builtin `reload` by `deepreload.reload` is deprecated since IPython 4.0, please import `reload` explicitly from `IPython.lib.deepreload", DeprecationWarning) self.auto_builtins['reload'] = deepreload._dreload else: self.auto_builtins['dreload']= deepreload._dreload diff --git a/contrib/python/ipython/py2/IPython/core/completer.py b/contrib/python/ipython/py2/IPython/core/completer.py index b386945e54..70bdee80ed 100644 --- a/contrib/python/ipython/py2/IPython/core/completer.py +++ b/contrib/python/ipython/py2/IPython/core/completer.py @@ -1,9 +1,9 @@ # encoding: utf-8 """Word completion for IPython. -This module started as fork of the rlcompleter module in the Python standard +This module started as fork of the rlcompleter module in the Python standard library. The original enhancements made to rlcompleter have been sent -upstream and were accepted as of Python 2.3, +upstream and were accepted as of Python 2.3, """ @@ -13,8 +13,8 @@ upstream and were accepted as of Python 2.3, # Some of this code originated from rlcompleter in the Python standard library # Copyright (C) 2001 Python Software Foundation, www.python.org -from __future__ import print_function - +from __future__ import print_function + import __main__ import glob import inspect @@ -27,18 +27,18 @@ import unicodedata import string import warnings -from traitlets.config.configurable import Configurable +from traitlets.config.configurable import Configurable from IPython.core.error import TryNext from IPython.core.inputsplitter import ESC_MAGIC from IPython.core.latex_symbols import latex_symbols, reverse_latex_symbol from IPython.utils import generics from IPython.utils.decorators import undoc -from IPython.utils.dir2 import dir2, get_real_method +from IPython.utils.dir2 import dir2, get_real_method from IPython.utils.process import arg_split -from IPython.utils.py3compat import builtin_mod, string_types, PY3, cast_unicode_py2 -from traitlets import Bool, Enum, observe - +from IPython.utils.py3compat import builtin_mod, string_types, PY3, cast_unicode_py2 +from traitlets import Bool, Enum, observe + # Public API __all__ = ['Completer','IPCompleter'] @@ -74,13 +74,13 @@ def has_open_quotes(s): def protect_filename(s): """Escape a string to protect certain characters.""" - if set(s) & set(PROTECTABLES): - if sys.platform == "win32": - return '"' + s + '"' - else: - return "".join(("\\" + c if c in PROTECTABLES else c) for c in s) - else: - return s + if set(s) & set(PROTECTABLES): + if sys.platform == "win32": + return '"' + s + '"' + else: + return "".join(("\\" + c if c in PROTECTABLES else c) for c in s) + else: + return s def expand_user(path): @@ -132,52 +132,52 @@ def compress_user(path, tilde_expand, tilde_val): return path -def completions_sorting_key(word): - """key for sorting completions +def completions_sorting_key(word): + """key for sorting completions - This does several things: + This does several things: - - Lowercase all completions, so they are sorted alphabetically with - upper and lower case words mingled - - Demote any completions starting with underscores to the end - - Insert any %magic and %%cellmagic completions in the alphabetical order - by their name - """ - # Case insensitive sort - word = word.lower() + - Lowercase all completions, so they are sorted alphabetically with + upper and lower case words mingled + - Demote any completions starting with underscores to the end + - Insert any %magic and %%cellmagic completions in the alphabetical order + by their name + """ + # Case insensitive sort + word = word.lower() - prio1, prio2 = 0, 0 + prio1, prio2 = 0, 0 - if word.startswith('__'): - prio1 = 2 - elif word.startswith('_'): - prio1 = 1 + if word.startswith('__'): + prio1 = 2 + elif word.startswith('_'): + prio1 = 1 - if word.endswith('='): - prio1 = -1 + if word.endswith('='): + prio1 = -1 - if word.startswith('%%'): - # If there's another % in there, this is something else, so leave it alone + if word.startswith('%%'): + # If there's another % in there, this is something else, so leave it alone if not "%" in word[2:]: - word = word[2:] - prio2 = 2 - elif word.startswith('%'): + word = word[2:] + prio2 = 2 + elif word.startswith('%'): if not "%" in word[1:]: - word = word[1:] - prio2 = 1 - - return prio1, word, prio2 + word = word[1:] + prio2 = 1 + return prio1, word, prio2 + @undoc class Bunch(object): pass -if sys.platform == 'win32': - DELIMS = ' \t\n`!@#$^&*()=+[{]}|;\'",<>?' -else: - DELIMS = ' \t\n`!@#$^&*()=+[{]}\\|;:\'",<>?' - +if sys.platform == 'win32': + DELIMS = ' \t\n`!@#$^&*()=+[{]}|;\'",<>?' +else: + DELIMS = ' \t\n`!@#$^&*()=+[{]}\\|;:\'",<>?' + GREEDY_DELIMS = ' =\r\n' @@ -234,14 +234,14 @@ class CompletionSplitter(object): class Completer(Configurable): - greedy = Bool(False, + greedy = Bool(False, help="""Activate greedy completion - PENDING DEPRECTION. this is now mostly taken care of with Jedi. + PENDING DEPRECTION. this is now mostly taken care of with Jedi. This will enable completion on elements of lists, results of function calls, etc., but can be unsafe because the code is actually evaluated on TAB. """ - ).tag(config=True) + ).tag(config=True) backslash_combining_completions = Bool(True, help="Enable unicode completions, e.g. \\alpha<tab> . " @@ -251,7 +251,7 @@ class Completer(Configurable): def __init__(self, namespace=None, global_namespace=None, **kwargs): """Create a new completer for the command line. - Completer(namespace=ns, global_namespace=ns2) -> completer instance. + Completer(namespace=ns, global_namespace=ns2) -> completer instance. If unspecified, the default namespace where completions are performed is __main__ (technically, __main__.__dict__). Namespaces should be @@ -321,7 +321,7 @@ class Completer(Configurable): for word in lst: if word[:n] == text and word != "__builtins__": match_append(word) - return [cast_unicode_py2(m) for m in matches] + return [cast_unicode_py2(m) for m in matches] def attr_matches(self, text): """Compute matches when text contains a dot. @@ -373,7 +373,7 @@ class Completer(Configurable): pass # Build match list to return n = len(attr) - return [u"%s.%s" % (expr, w) for w in words if w[:n] == attr ] + return [u"%s.%s" % (expr, w) for w in words if w[:n] == attr ] def get__all__entries(obj): @@ -383,7 +383,7 @@ def get__all__entries(obj): except: return [] - return [cast_unicode_py2(w) for w in words if isinstance(w, string_types)] + return [cast_unicode_py2(w) for w in words if isinstance(w, string_types)] def match_dict_keys(keys, prefix, delims): @@ -470,7 +470,7 @@ def back_unicode_name_matches(text): try : unic = unicodedata.name(char) return '\\'+char,['\\'+unic] - except KeyError: + except KeyError: pass return u'', () @@ -497,18 +497,18 @@ def back_latex_name_matches(text): latex = reverse_latex_symbol[char] # '\\' replace the \ as well return '\\'+char,[latex] - except KeyError: + except KeyError: pass return u'', () class IPCompleter(Completer): """Extension of the completer class with IPython-specific features""" - - @observe('greedy') - def _greedy_changed(self, change): + + @observe('greedy') + def _greedy_changed(self, change): """update the splitter and readline delims when greedy is changed""" - if change['new']: + if change['new']: self.splitter.delims = GREEDY_DELIMS else: self.splitter.delims = DELIMS @@ -516,14 +516,14 @@ class IPCompleter(Completer): if self.readline: self.readline.set_completer_delims(self.splitter.delims) - merge_completions = Bool(True, + merge_completions = Bool(True, help="""Whether to merge completion results into a single list If False, only the completion results from the first non-empty completer will be returned. """ - ).tag(config=True) - omit__names = Enum((0,1,2), default_value=2, + ).tag(config=True) + omit__names = Enum((0,1,2), default_value=2, help="""Instruct the completer to omit private method names Specifically, when completing on ``object.<tab>``. @@ -534,20 +534,20 @@ class IPCompleter(Completer): When 0: nothing will be excluded. """ - ).tag(config=True) - limit_to__all__ = Bool(False, - help=""" - DEPRECATED as of version 5.0. - - Instruct the completer to use __all__ for the completion + ).tag(config=True) + limit_to__all__ = Bool(False, + help=""" + DEPRECATED as of version 5.0. + Instruct the completer to use __all__ for the completion + Specifically, when completing on ``object.<tab>``. When True: only those names in obj.__all__ will be included. When False [default]: the __all__ attribute is ignored - """, - ).tag(config=True) + """, + ).tag(config=True) @observe('limit_to__all__') def _limit_to_all_changed(self, change): @@ -621,24 +621,24 @@ class IPCompleter(Completer): #= re.compile(r'[\s|\[]*(\w+)(?:\s*=?\s*.*)') # All active matcher routines for completion - self.matchers = [ - self.python_matches, + self.matchers = [ + self.python_matches, self.file_matches, self.magic_matches, self.python_func_kw_matches, self.dict_key_matches, ] - # This is set externally by InteractiveShell - self.custom_completers = None - + # This is set externally by InteractiveShell + self.custom_completers = None + def all_completions(self, text): """ - Wrapper around the complete method for the benefit of emacs. + Wrapper around the complete method for the benefit of emacs. """ return self.complete(text)[1] - def _clean_glob(self, text): + def _clean_glob(self, text): return self.glob("%s*" % text) def _clean_glob_win32(self,text): @@ -665,9 +665,9 @@ class IPCompleter(Completer): # when escaped with backslash if text.startswith('!'): text = text[1:] - text_prefix = u'!' + text_prefix = u'!' else: - text_prefix = u'' + text_prefix = u'' text_until_cursor = self.text_until_cursor # track strings with open quotes @@ -698,13 +698,13 @@ class IPCompleter(Completer): text = os.path.expanduser(text) if text == "": - return [text_prefix + cast_unicode_py2(protect_filename(f)) for f in self.glob("*")] + return [text_prefix + cast_unicode_py2(protect_filename(f)) for f in self.glob("*")] # Compute the matches from the filesystem - if sys.platform == 'win32': - m0 = self.clean_glob(text) - else: - m0 = self.clean_glob(text.replace('\\', '')) + if sys.platform == 'win32': + m0 = self.clean_glob(text) + else: + m0 = self.clean_glob(text.replace('\\', '')) if has_protectables: # If we had protectables, we need to revert our changes to the @@ -724,7 +724,7 @@ class IPCompleter(Completer): protect_filename(f) for f in m0] # Mark directories in input list by appending '/' to their names. - return [cast_unicode_py2(x+'/') if os.path.isdir(x) else x for x in matches] + return [cast_unicode_py2(x+'/') if os.path.isdir(x) else x for x in matches] def magic_matches(self, text): """Match magics""" @@ -745,10 +745,10 @@ class IPCompleter(Completer): comp = [ pre2+m for m in cell_magics if m.startswith(bare_text)] if not text.startswith(pre2): comp += [ pre+m for m in line_magics if m.startswith(bare_text)] - return [cast_unicode_py2(c) for c in comp] - + return [cast_unicode_py2(c) for c in comp] - def python_matches(self, text): + + def python_matches(self, text): """Match attributes or global python names""" if "." in text: try: @@ -896,19 +896,19 @@ class IPCompleter(Completer): for namedArg in namedArgs: if namedArg.startswith(text): - argMatches.append(u"%s=" %namedArg) + argMatches.append(u"%s=" %namedArg) return argMatches def dict_key_matches(self, text): "Match string keys in a dictionary, after e.g. 'foo[' " def get_keys(obj): - # Objects can define their own completions by defining an - # _ipy_key_completions_() method. - method = get_real_method(obj, '_ipython_key_completions_') - if method is not None: - return method() - - # Special case some common in-memory dict-like types + # Objects can define their own completions by defining an + # _ipy_key_completions_() method. + method = get_real_method(obj, '_ipython_key_completions_') + if method is not None: + return method() + + # Special case some common in-memory dict-like types if isinstance(obj, dict) or\ _safe_isinstance(obj, 'pandas', 'DataFrame'): try: @@ -1026,7 +1026,7 @@ class IPCompleter(Completer): # allow combining chars if ('a'+unic).isidentifier(): return '\\'+s,[unic] - except KeyError: + except KeyError: pass return u'', [] @@ -1055,9 +1055,9 @@ class IPCompleter(Completer): return u'', [] def dispatch_custom_completer(self, text): - if not self.custom_completers: - return - + if not self.custom_completers: + return + line = self.line_buffer if not line.strip(): return None @@ -1085,12 +1085,12 @@ class IPCompleter(Completer): res = c(event) if res: # first, try case sensitive match - withcase = [cast_unicode_py2(r) for r in res if r.startswith(text)] + withcase = [cast_unicode_py2(r) for r in res if r.startswith(text)] if withcase: return withcase # if none, then case insensitive ones are ok too text_low = text.lower() - return [cast_unicode_py2(r) for r in res if r.lower().startswith(text_low)] + return [cast_unicode_py2(r) for r in res if r.lower().startswith(text_low)] except TryNext: pass except KeyboardInterrupt: diff --git a/contrib/python/ipython/py2/IPython/core/completerlib.py b/contrib/python/ipython/py2/IPython/core/completerlib.py index e736ca73d1..5d51991725 100644 --- a/contrib/python/ipython/py2/IPython/core/completerlib.py +++ b/contrib/python/ipython/py2/IPython/core/completerlib.py @@ -227,8 +227,8 @@ def try_import(mod, only_modules=False): completions.extend(getattr(m, '__all__', [])) if m_is_init: completions.extend(arcadia_module_list(mod)) - completions = {c for c in completions if isinstance(c, string_types)} - completions.discard('__init__') + completions = {c for c in completions if isinstance(c, string_types)} + completions.discard('__init__') return sorted(completions) diff --git a/contrib/python/ipython/py2/IPython/core/debugger.py b/contrib/python/ipython/py2/IPython/core/debugger.py index f08cfb1a78..4980c3551b 100644 --- a/contrib/python/ipython/py2/IPython/core/debugger.py +++ b/contrib/python/ipython/py2/IPython/core/debugger.py @@ -31,40 +31,40 @@ import bdb import functools import inspect import sys -import warnings +import warnings from IPython import get_ipython from IPython.utils import PyColorize, ulinecache -from IPython.utils import coloransi, py3compat +from IPython.utils import coloransi, py3compat from IPython.core.excolors import exception_colors from IPython.testing.skipdoctest import skip_doctest - + prompt = 'ipdb> ' - + #We have to check this directly from sys.argv, config struct not yet available -from pdb import Pdb as OldPdb +from pdb import Pdb as OldPdb # Allow the set_trace code to operate outside of an ipython instance, even if # it does so with some limitations. The rest of this support is implemented in # the Tracer constructor. - -def make_arrow(pad): - """generate the leading arrow in front of traceback or debugger""" - if pad >= 2: - return '-'*(pad-2) + '> ' - elif pad == 1: - return '>' - return '' - - + +def make_arrow(pad): + """generate the leading arrow in front of traceback or debugger""" + if pad >= 2: + return '-'*(pad-2) + '> ' + elif pad == 1: + return '>' + return '' + + def BdbQuit_excepthook(et, ev, tb, excepthook=None): """Exception hook which handles `BdbQuit` exceptions. All other exceptions are processed using the `excepthook` parameter. """ - warnings.warn("`BdbQuit_excepthook` is deprecated since version 5.1", + warnings.warn("`BdbQuit_excepthook` is deprecated since version 5.1", DeprecationWarning, stacklevel=2) if et==bdb.BdbQuit: print('Exiting Debugger.') @@ -74,20 +74,20 @@ def BdbQuit_excepthook(et, ev, tb, excepthook=None): # Backwards compatibility. Raise deprecation warning? BdbQuit_excepthook.excepthook_ori(et,ev,tb) - + def BdbQuit_IPython_excepthook(self,et,ev,tb,tb_offset=None): - warnings.warn( - "`BdbQuit_IPython_excepthook` is deprecated since version 5.1", + warnings.warn( + "`BdbQuit_IPython_excepthook` is deprecated since version 5.1", DeprecationWarning, stacklevel=2) print('Exiting Debugger.') class Tracer(object): - """ - DEPRECATED - - Class for local debugging, similar to pdb.set_trace. + """ + DEPRECATED + Class for local debugging, similar to pdb.set_trace. + Instances of this class, when called, behave like pdb.set_trace, but providing IPython's enhanced capabilities. @@ -100,11 +100,11 @@ class Tracer(object): @skip_doctest def __init__(self, colors=None): - """ - DEPRECATED - - Create a local debugger instance. + """ + DEPRECATED + Create a local debugger instance. + Parameters ---------- @@ -128,8 +128,8 @@ class Tracer(object): step through code, set breakpoints, etc. See the pdb documentation from the Python standard library for usage details. """ - warnings.warn("`Tracer` is deprecated since version 5.1, directly use " - "`IPython.core.debugger.Pdb.set_trace()`", + warnings.warn("`Tracer` is deprecated since version 5.1, directly use " + "`IPython.core.debugger.Pdb.set_trace()`", DeprecationWarning, stacklevel=2) ip = get_ipython() @@ -204,25 +204,25 @@ def _file_lines(fname): class Pdb(OldPdb): - """Modified Pdb class, does not load readline. - - for a standalone version that uses prompt_toolkit, see - `IPython.terminal.debugger.TerminalPdb` and - `IPython.terminal.debugger.set_trace()` - """ - - def __init__(self, color_scheme=None, completekey=None, + """Modified Pdb class, does not load readline. + + for a standalone version that uses prompt_toolkit, see + `IPython.terminal.debugger.TerminalPdb` and + `IPython.terminal.debugger.set_trace()` + """ + + def __init__(self, color_scheme=None, completekey=None, stdin=None, stdout=None, context=5): # Parent constructor: try: - self.context = int(context) + self.context = int(context) if self.context <= 0: raise ValueError("Context must be a positive integer") except (TypeError, ValueError): raise ValueError("Context must be a positive integer") - OldPdb.__init__(self, completekey, stdin, stdout) + OldPdb.__init__(self, completekey, stdin, stdout) # IPython changes... self.shell = get_ipython() @@ -237,12 +237,12 @@ class Pdb(OldPdb): # the debugger was entered. See also #9941. sys.modules['__main__'] = save_main - if color_scheme is not None: - warnings.warn( - "The `color_scheme` argument is deprecated since version 5.1", - DeprecationWarning) - else: - color_scheme = self.shell.colors + if color_scheme is not None: + warnings.warn( + "The `color_scheme` argument is deprecated since version 5.1", + DeprecationWarning) + else: + color_scheme = self.shell.colors self.aliases = {} @@ -266,28 +266,28 @@ class Pdb(OldPdb): cst['LightBG'].colors.breakpoint_enabled = C.LightRed cst['LightBG'].colors.breakpoint_disabled = C.Red - cst['Neutral'].colors.prompt = C.Blue - cst['Neutral'].colors.breakpoint_enabled = C.LightRed - cst['Neutral'].colors.breakpoint_disabled = C.Red - + cst['Neutral'].colors.prompt = C.Blue + cst['Neutral'].colors.breakpoint_enabled = C.LightRed + cst['Neutral'].colors.breakpoint_disabled = C.Red + self.set_colors(color_scheme) # Add a python parser so we can syntax highlight source while # debugging. self.parser = PyColorize.Parser() - # Set the prompt - the default prompt is '(Pdb)' - self.prompt = prompt + # Set the prompt - the default prompt is '(Pdb)' + self.prompt = prompt def set_colors(self, scheme): """Shorthand access to the color table scheme selector method.""" self.color_scheme_table.set_active_scheme(scheme) def interaction(self, frame, traceback): - try: - OldPdb.interaction(self, frame, traceback) - except KeyboardInterrupt: - sys.stdout.write('\n' + self.shell.get_exception_only()) + try: + OldPdb.interaction(self, frame, traceback) + except KeyboardInterrupt: + sys.stdout.write('\n' + self.shell.get_exception_only()) def new_do_up(self, arg): OldPdb.do_up(self, arg) @@ -331,7 +331,7 @@ class Pdb(OldPdb): except KeyboardInterrupt: pass - def print_stack_entry(self,frame_lineno, prompt_prefix='\n-> ', + def print_stack_entry(self,frame_lineno, prompt_prefix='\n-> ', context=None): if context is None: context = self.context @@ -341,7 +341,7 @@ class Pdb(OldPdb): raise ValueError("Context must be a positive integer") except (TypeError, ValueError): raise ValueError("Context must be a positive integer") - print(self.format_stack_entry(frame_lineno, '', context)) + print(self.format_stack_entry(frame_lineno, '', context)) # vds: >> frame, lineno = frame_lineno @@ -447,11 +447,11 @@ class Pdb(OldPdb): if arrow: # This is the line with the error pad = numbers_width - len(str(lineno)) - len(bp_mark) - num = '%s%s' % (make_arrow(pad), str(lineno)) + num = '%s%s' % (make_arrow(pad), str(lineno)) else: num = '%*s' % (numbers_width - len(bp_mark), str(lineno)) - return tpl_line % (bp_mark_color + bp_mark, num, line) + return tpl_line % (bp_mark_color + bp_mark, num, line) def print_list_lines(self, filename, first, last): @@ -479,7 +479,7 @@ class Pdb(OldPdb): src.append(line) self.lineno = lineno - print(''.join(src)) + print(''.join(src)) except KeyboardInterrupt: pass diff --git a/contrib/python/ipython/py2/IPython/core/display.py b/contrib/python/ipython/py2/IPython/core/display.py index 5c82a57b31..a099031953 100644 --- a/contrib/python/ipython/py2/IPython/core/display.py +++ b/contrib/python/ipython/py2/IPython/core/display.py @@ -6,17 +6,17 @@ from __future__ import print_function -try: - from base64 import encodebytes as base64_encode -except ImportError: - from base64 import encodestring as base64_encode - +try: + from base64 import encodebytes as base64_encode +except ImportError: + from base64 import encodestring as base64_encode + from binascii import b2a_hex, hexlify import json import mimetypes import os import struct -import sys +import sys import warnings from IPython.utils.py3compat import (string_types, cast_bytes_py2, cast_unicode, @@ -964,9 +964,9 @@ class Image(DisplayObject): Note that QtConsole is not able to display images if `embed` is set to `False` width : int - Width in pixels to which to constrain the image in html + Width in pixels to which to constrain the image in html height : int - Height in pixels to which to constrain the image in html + Height in pixels to which to constrain the image in html retina : bool Automatically set the width and height to half of the measured width and height. @@ -1111,7 +1111,7 @@ class Image(DisplayObject): class Video(DisplayObject): - def __init__(self, data=None, url=None, filename=None, embed=False, mimetype=None): + def __init__(self, data=None, url=None, filename=None, embed=False, mimetype=None): """Create a video object given raw data or an URL. When this object is returned by an input cell or passed to the @@ -1121,54 +1121,54 @@ class Video(DisplayObject): Parameters ---------- data : unicode, str or bytes - The raw video data or a URL or filename to load the data from. - Raw data will require passing `embed=True`. + The raw video data or a URL or filename to load the data from. + Raw data will require passing `embed=True`. url : unicode - A URL for the video. If you specify `url=`, - the image data will not be embedded. + A URL for the video. If you specify `url=`, + the image data will not be embedded. filename : unicode - Path to a local file containing the video. - Will be interpreted as a local URL unless `embed=True`. + Path to a local file containing the video. + Will be interpreted as a local URL unless `embed=True`. embed : bool - Should the video be embedded using a data URI (True) or be - loaded using a <video> tag (False). - - Since videos are large, embedding them should be avoided, if possible. - You must confirm embedding as your intention by passing `embed=True`. - - Local files can be displayed with URLs without embedding the content, via:: + Should the video be embedded using a data URI (True) or be + loaded using a <video> tag (False). - Video('./video.mp4') + Since videos are large, embedding them should be avoided, if possible. + You must confirm embedding as your intention by passing `embed=True`. + Local files can be displayed with URLs without embedding the content, via:: + + Video('./video.mp4') + mimetype: unicode - Specify the mimetype for embedded videos. - Default will be guessed from file extension, if available. - + Specify the mimetype for embedded videos. + Default will be guessed from file extension, if available. + Examples -------- - + Video('https://archive.org/download/Sita_Sings_the_Blues/Sita_Sings_the_Blues_small.mp4') Video('path/to/video.mp4') - Video('path/to/video.mp4', embed=True) - Video(b'raw-videodata', embed=True) + Video('path/to/video.mp4', embed=True) + Video(b'raw-videodata', embed=True) """ - if url is None and isinstance(data, string_types) and data.startswith(('http:', 'https:')): + if url is None and isinstance(data, string_types) and data.startswith(('http:', 'https:')): url = data data = None elif os.path.exists(data): filename = data data = None - - if data and not embed: - msg = ''.join([ - "To embed videos, you must pass embed=True ", - "(this may make your notebook files huge)\n", - "Consider passing Video(url='...')", - ]) - raise ValueError(msg) + + if data and not embed: + msg = ''.join([ + "To embed videos, you must pass embed=True ", + "(this may make your notebook files huge)\n", + "Consider passing Video(url='...')", + ]) + raise ValueError(msg) self.mimetype = mimetype - self.embed = embed + self.embed = embed super(Video, self).__init__(data=data, url=url, filename=filename) def _repr_html_(self): @@ -1180,27 +1180,27 @@ class Video(DisplayObject): Your browser does not support the <code>video</code> element. </video>""".format(url) return output - - # Embedded videos are base64-encoded. - mimetype = self.mimetype + + # Embedded videos are base64-encoded. + mimetype = self.mimetype if self.filename is not None: - if not mimetype: - mimetype, _ = mimetypes.guess_type(self.filename) - - with open(self.filename, 'rb') as f: - video = f.read() + if not mimetype: + mimetype, _ = mimetypes.guess_type(self.filename) + + with open(self.filename, 'rb') as f: + video = f.read() else: - video = self.data - if isinstance(video, unicode_type): - # unicode input is already b64-encoded - b64_video = video - else: - b64_video = base64_encode(video).decode('ascii').rstrip() - + video = self.data + if isinstance(video, unicode_type): + # unicode input is already b64-encoded + b64_video = video + else: + b64_video = base64_encode(video).decode('ascii').rstrip() + output = """<video controls> <source src="data:{0};base64,{1}" type="{0}"> Your browser does not support the video tag. - </video>""".format(mimetype, b64_video) + </video>""".format(mimetype, b64_video) return output def reload(self): @@ -1225,10 +1225,10 @@ def clear_output(wait=False): if InteractiveShell.initialized(): InteractiveShell.instance().display_pub.clear_output(wait) else: - print('\033[2K\r', end='') - sys.stdout.flush() - print('\033[2K\r', end='') - sys.stderr.flush() + print('\033[2K\r', end='') + sys.stdout.flush() + print('\033[2K\r', end='') + sys.stderr.flush() @skip_doctest diff --git a/contrib/python/ipython/py2/IPython/core/displayhook.py b/contrib/python/ipython/py2/IPython/core/displayhook.py index cce7c83d16..e07b577680 100644 --- a/contrib/python/ipython/py2/IPython/core/displayhook.py +++ b/contrib/python/ipython/py2/IPython/core/displayhook.py @@ -16,7 +16,7 @@ import tokenize from traitlets.config.configurable import Configurable from IPython.utils.py3compat import builtin_mod, cast_unicode_py2 from traitlets import Instance, Float -from warnings import warn +from warnings import warn # TODO: Move the various attributes (cache_size, [others now moved]). Some # of these are also attributes of InteractiveShell. They should be on ONE object @@ -94,7 +94,7 @@ class DisplayHook(Configurable): tokens = list(tokenize.generate_tokens(sio.readline)) for token in reversed(tokens): - if token[0] in (tokenize.ENDMARKER, tokenize.NL, tokenize.NEWLINE, tokenize.COMMENT): + if token[0] in (tokenize.ENDMARKER, tokenize.NL, tokenize.NEWLINE, tokenize.COMMENT): continue if (token[0] == tokenize.OP) and (token[1] == ';'): return True @@ -109,13 +109,13 @@ class DisplayHook(Configurable): """Write the output prompt. The default implementation simply writes the prompt to - ``sys.stdout``. + ``sys.stdout``. """ # Use write, not print which adds an extra space. - sys.stdout.write(self.shell.separate_out) - outprompt = 'Out[{}]: '.format(self.shell.execution_count) + sys.stdout.write(self.shell.separate_out) + outprompt = 'Out[{}]: '.format(self.shell.execution_count) if self.do_full_cache: - sys.stdout.write(outprompt) + sys.stdout.write(outprompt) def compute_format_data(self, result): """Compute format data of the object to be displayed. @@ -149,14 +149,14 @@ class DisplayHook(Configurable): """ return self.shell.display_formatter.format(result) - # This can be set to True by the write_output_prompt method in a subclass - prompt_end_newline = False - + # This can be set to True by the write_output_prompt method in a subclass + prompt_end_newline = False + def write_format_data(self, format_dict, md_dict=None): """Write the format data dict to the frontend. This default version of this method simply writes the plain text - representation of the object to ``sys.stdout``. Subclasses should + representation of the object to ``sys.stdout``. Subclasses should override this method to send the entire `format_dict` to the frontends. @@ -182,11 +182,11 @@ class DisplayHook(Configurable): # because the expansion may add ANSI escapes that will interfere # with our ability to determine whether or not we should add # a newline. - if not self.prompt_end_newline: + if not self.prompt_end_newline: # But avoid extraneous empty lines. result_repr = '\n' + result_repr - print(result_repr) + print(result_repr) def update_user_ns(self, result): """Update user_ns with various things like _, __, _1, etc.""" @@ -230,8 +230,8 @@ class DisplayHook(Configurable): def finish_displayhook(self): """Finish up all displayhook activities.""" - sys.stdout.write(self.shell.separate_out2) - sys.stdout.flush() + sys.stdout.write(self.shell.separate_out2) + sys.stdout.flush() def __call__(self, result=None): """Printing with history cache management. diff --git a/contrib/python/ipython/py2/IPython/core/displaypub.py b/contrib/python/ipython/py2/IPython/core/displaypub.py index 82a859ae15..cd7be5797e 100644 --- a/contrib/python/ipython/py2/IPython/core/displaypub.py +++ b/contrib/python/ipython/py2/IPython/core/displaypub.py @@ -17,8 +17,8 @@ spec. from __future__ import print_function -import sys - +import sys + from traitlets.config.configurable import Configurable from traitlets import List @@ -105,16 +105,16 @@ class DisplayPublisher(Configurable): transient = kwargs.pop('transient', None) update = kwargs.pop('update', False) - # The default is to simply write the plain text data using sys.stdout. + # The default is to simply write the plain text data using sys.stdout. if 'text/plain' in data: - print(data['text/plain']) + print(data['text/plain']) def clear_output(self, wait=False): """Clear the output of the cell receiving output.""" - print('\033[2K\r', end='') - sys.stdout.flush() - print('\033[2K\r', end='') - sys.stderr.flush() + print('\033[2K\r', end='') + sys.stdout.flush() + print('\033[2K\r', end='') + sys.stderr.flush() class CapturingDisplayPublisher(DisplayPublisher): diff --git a/contrib/python/ipython/py2/IPython/core/events.py b/contrib/python/ipython/py2/IPython/core/events.py index bfd09fec6a..776fa191da 100644 --- a/contrib/python/ipython/py2/IPython/core/events.py +++ b/contrib/python/ipython/py2/IPython/core/events.py @@ -69,7 +69,7 @@ class EventManager(object): Any additional arguments are passed to all callbacks registered for this event. Exceptions raised by callbacks are caught, and a message printed. """ - for func in self.callbacks[event][:]: + for func in self.callbacks[event][:]: try: func(*args, **kwargs) except Exception: diff --git a/contrib/python/ipython/py2/IPython/core/excolors.py b/contrib/python/ipython/py2/IPython/core/excolors.py index 487bde18c8..de46ac13a5 100644 --- a/contrib/python/ipython/py2/IPython/core/excolors.py +++ b/contrib/python/ipython/py2/IPython/core/excolors.py @@ -19,7 +19,7 @@ def exception_colors(): """Return a color table with fields for exception reporting. The table is an instance of ColorSchemeTable with schemes added for - 'Neutral', 'Linux', 'LightBG' and 'NoColor' and fields for exception handling filled + 'Neutral', 'Linux', 'LightBG' and 'NoColor' and fields for exception handling filled in. Examples: @@ -128,41 +128,41 @@ def exception_colors(): Normal = C.Normal, )) - ex_colors.add_scheme(ColorScheme( - 'Neutral', - # The color to be used for the top line - topline = C.Red, - - # The colors to be used in the traceback - filename = C.LightGreen, - lineno = C.LightGreen, - name = C.LightPurple, - vName = C.Cyan, - val = C.LightGreen, - em = C.Cyan, - - # Emphasized colors for the last frame of the traceback - normalEm = C.Cyan, - filenameEm = C.Green, - linenoEm = C.Green, - nameEm = C.Purple, - valEm = C.Blue, - - # Colors for printing the exception - excName = C.Red, - #line = C.Brown, # brown often is displayed as yellow - line = C.Red, - caret = C.Normal, - Normal = C.Normal, - )) - + ex_colors.add_scheme(ColorScheme( + 'Neutral', + # The color to be used for the top line + topline = C.Red, + + # The colors to be used in the traceback + filename = C.LightGreen, + lineno = C.LightGreen, + name = C.LightPurple, + vName = C.Cyan, + val = C.LightGreen, + em = C.Cyan, + + # Emphasized colors for the last frame of the traceback + normalEm = C.Cyan, + filenameEm = C.Green, + linenoEm = C.Green, + nameEm = C.Purple, + valEm = C.Blue, + + # Colors for printing the exception + excName = C.Red, + #line = C.Brown, # brown often is displayed as yellow + line = C.Red, + caret = C.Normal, + Normal = C.Normal, + )) + # Hack: the 'neutral' colours are not very visible on a dark background on # Windows. Since Windows command prompts have a dark background by default, and # relatively few users are likely to alter that, we will use the 'Linux' colours, # designed for a dark background, as the default on Windows. if os.name == "nt": ex_colors.add_scheme(ex_colors['Linux'].copy('Neutral')) - + return ex_colors class Deprec(object): diff --git a/contrib/python/ipython/py2/IPython/core/extensions.py b/contrib/python/ipython/py2/IPython/core/extensions.py index 58855466f1..81c5de462d 100644 --- a/contrib/python/ipython/py2/IPython/core/extensions.py +++ b/contrib/python/ipython/py2/IPython/core/extensions.py @@ -36,7 +36,7 @@ class ExtensionManager(Configurable): the only argument. You can do anything you want with IPython at that point, including defining new magic and aliases, adding new components, etc. - + You can also optionally define an :func:`unload_ipython_extension(ipython)` function, which will be called if the user unloads or reloads the extension. The extension manager will only call :func:`load_ipython_extension` again @@ -49,12 +49,12 @@ class ExtensionManager(Configurable): is added to ``sys.path`` automatically. """ - shell = Instance('IPython.core.interactiveshell.InteractiveShellABC', allow_none=True) + shell = Instance('IPython.core.interactiveshell.InteractiveShellABC', allow_none=True) def __init__(self, shell=None, **kwargs): super(ExtensionManager, self).__init__(shell=shell, **kwargs) - self.shell.observe( - self._on_ipython_dir_changed, names=('ipython_dir',) + self.shell.observe( + self._on_ipython_dir_changed, names=('ipython_dir',) ) self.loaded = set() @@ -62,7 +62,7 @@ class ExtensionManager(Configurable): def ipython_extension_dir(self): return os.path.join(self.shell.ipython_dir, u'extensions') - def _on_ipython_dir_changed(self, change): + def _on_ipython_dir_changed(self, change): ensure_dir_exists(self.ipython_extension_dir) def load_extension(self, module_str): @@ -74,7 +74,7 @@ class ExtensionManager(Configurable): """ if module_str in self.loaded: return "already loaded" - + with self.shell.builtin_trap: if module_str not in sys.modules: try: @@ -92,14 +92,14 @@ class ExtensionManager(Configurable): This function looks up the extension's name in ``sys.modules`` and simply calls ``mod.unload_ipython_extension(self)``. - + Returns the string "no unload function" if the extension doesn't define a function to unload itself, "not loaded" if the extension isn't loaded, otherwise None. """ if module_str not in self.loaded: return "not loaded" - + if module_str in sys.modules: mod = sys.modules[module_str] if self._call_unload_ipython_extension(mod): @@ -138,7 +138,7 @@ class ExtensionManager(Configurable): return True def install_extension(self, url, filename=None): - """Download and install an IPython extension. + """Download and install an IPython extension. If filename is given, the file will be so named (inside the extension directory). Otherwise, the name from the URL will be used. The file must diff --git a/contrib/python/ipython/py2/IPython/core/formatters.py b/contrib/python/ipython/py2/IPython/core/formatters.py index d990619f27..06af83c1a9 100644 --- a/contrib/python/ipython/py2/IPython/core/formatters.py +++ b/contrib/python/ipython/py2/IPython/core/formatters.py @@ -21,12 +21,12 @@ from decorator import decorator from traitlets.config.configurable import Configurable from IPython.core.getipython import get_ipython from IPython.utils.sentinel import Sentinel -from IPython.utils.dir2 import get_real_method +from IPython.utils.dir2 import get_real_method from IPython.lib import pretty from traitlets import ( Bool, Dict, Integer, Unicode, CUnicode, ObjectName, List, ForwardDeclaredInstance, - default, observe, + default, observe, ) from IPython.utils.py3compat import ( with_metaclass, string_types, unicode_type, @@ -35,28 +35,28 @@ from IPython.utils.py3compat import ( class DisplayFormatter(Configurable): - active_types = List(Unicode(), + active_types = List(Unicode(), help="""List of currently active mime-types to display. You can use this to set a white-list for formats to display. Most users will not need to change this value. - """).tag(config=True) - - @default('active_types') + """).tag(config=True) + + @default('active_types') def _active_types_default(self): return self.format_types - - @observe('active_types') - def _active_types_changed(self, change): + + @observe('active_types') + def _active_types_changed(self, change): for key, formatter in self.formatters.items(): - if key in change['new']: + if key in change['new']: formatter.enabled = True else: formatter.enabled = False ipython_display_formatter = ForwardDeclaredInstance('FormatterABC') - @default('ipython_display_formatter') - def _default_formatter(self): + @default('ipython_display_formatter') + def _default_formatter(self): return IPythonDisplayFormatter(parent=self) mimebundle_formatter = ForwardDeclaredInstance('FormatterABC') @@ -67,7 +67,7 @@ class DisplayFormatter(Configurable): # A dict of formatter whose keys are format types (MIME types) and whose # values are subclasses of BaseFormatter. formatters = Dict() - @default('formatters') + @default('formatters') def _formatters_default(self): """Activate the default formatters.""" formatter_classes = [ @@ -305,21 +305,21 @@ class BaseFormatter(Configurable): format_type = Unicode('text/plain') _return_type = string_types - enabled = Bool(True).tag(config=True) + enabled = Bool(True).tag(config=True) print_method = ObjectName('__repr__') # The singleton printers. # Maps the IDs of the builtin singleton objects to the format functions. - singleton_printers = Dict().tag(config=True) + singleton_printers = Dict().tag(config=True) # The type-specific printers. # Map type objects to the format functions. - type_printers = Dict().tag(config=True) + type_printers = Dict().tag(config=True) # The deferred-import type-specific printers. # Map (modulename, classname) pairs to the format functions. - deferred_printers = Dict().tag(config=True) + deferred_printers = Dict().tag(config=True) @catch_format_error def __call__(self, obj): @@ -333,7 +333,7 @@ class BaseFormatter(Configurable): else: return printer(obj) # Finally look for special method names - method = get_real_method(obj, self.print_method) + method = get_real_method(obj, self.print_method) if method is not None: return method() return None @@ -586,37 +586,37 @@ class PlainTextFormatter(BaseFormatter): # This subclass ignores this attribute as it always need to return # something. - enabled = Bool(True).tag(config=False) + enabled = Bool(True).tag(config=False) - max_seq_length = Integer(pretty.MAX_SEQ_LENGTH, + max_seq_length = Integer(pretty.MAX_SEQ_LENGTH, help="""Truncate large collections (lists, dicts, tuples, sets) to this size. Set to 0 to disable truncation. """ - ).tag(config=True) + ).tag(config=True) # Look for a _repr_pretty_ methods to use for pretty printing. print_method = ObjectName('_repr_pretty_') # Whether to pretty-print or not. - pprint = Bool(True).tag(config=True) + pprint = Bool(True).tag(config=True) # Whether to be verbose or not. - verbose = Bool(False).tag(config=True) + verbose = Bool(False).tag(config=True) # The maximum width. - max_width = Integer(79).tag(config=True) + max_width = Integer(79).tag(config=True) # The newline character. - newline = Unicode('\n').tag(config=True) + newline = Unicode('\n').tag(config=True) # format-string for pprinting floats float_format = Unicode('%r') # setter for float precision, either int or direct format-string - float_precision = CUnicode('').tag(config=True) + float_precision = CUnicode('').tag(config=True) - @observe('float_precision') - def _float_precision_changed(self, change): + @observe('float_precision') + def _float_precision_changed(self, change): """float_precision changed, set float_format accordingly. float_precision can be set by int or str. @@ -630,7 +630,7 @@ class PlainTextFormatter(BaseFormatter): This parameter can be set via the '%precision' magic. """ - new = change['new'] + new = change['new'] if '%' in new: # got explicit format string fmt = new @@ -663,17 +663,17 @@ class PlainTextFormatter(BaseFormatter): self.float_format = fmt # Use the default pretty printers from IPython.lib.pretty. - @default('singleton_printers') + @default('singleton_printers') def _singleton_printers_default(self): return pretty._singleton_pprinters.copy() - @default('type_printers') + @default('type_printers') def _type_printers_default(self): d = pretty._type_pprinters.copy() d[float] = lambda obj,p,cycle: p.text(self.float_format%obj) return d - @default('deferred_printers') + @default('deferred_printers') def _deferred_printers_default(self): return pretty._deferred_type_pprinters.copy() @@ -910,7 +910,7 @@ class IPythonDisplayFormatter(BaseFormatter): printer(obj) return True # Finally look for special method names - method = get_real_method(obj, self.print_method) + method = get_real_method(obj, self.print_method) if method is not None: method() return True @@ -1030,7 +1030,7 @@ def format_display_data(obj, include=None, exclude=None): """ from IPython.core.interactiveshell import InteractiveShell - return InteractiveShell.instance().display_formatter.format( + return InteractiveShell.instance().display_formatter.format( obj, include, exclude diff --git a/contrib/python/ipython/py2/IPython/core/history.py b/contrib/python/ipython/py2/IPython/core/history.py index 2e7fdbc845..1e8e227a50 100644 --- a/contrib/python/ipython/py2/IPython/core/history.py +++ b/contrib/python/ipython/py2/IPython/core/history.py @@ -1,8 +1,8 @@ """ History related magics and functionality """ -# Copyright (c) IPython Development Team. -# Distributed under the terms of the Modified BSD License. - +# Copyright (c) IPython Development Team. +# Distributed under the terms of the Modified BSD License. + from __future__ import print_function import atexit @@ -18,16 +18,16 @@ except ImportError: sqlite3 = None import threading -from traitlets.config.configurable import LoggingConfigurable +from traitlets.config.configurable import LoggingConfigurable from decorator import decorator from IPython.utils.decorators import undoc from IPython.paths import locate_profile from IPython.utils import py3compat from traitlets import ( Any, Bool, Dict, Instance, Integer, List, Unicode, TraitError, - default, observe, + default, observe, ) -from warnings import warn +from warnings import warn #----------------------------------------------------------------------------- # Classes and functions @@ -72,55 +72,55 @@ else: class OperationalError(Exception): "Dummy exception when sqlite could not be imported. Should never occur." -# use 16kB as threshold for whether a corrupt history db should be saved -# that should be at least 100 entries or so -_SAVE_DB_SIZE = 16384 - +# use 16kB as threshold for whether a corrupt history db should be saved +# that should be at least 100 entries or so +_SAVE_DB_SIZE = 16384 + @decorator def catch_corrupt_db(f, self, *a, **kw): """A decorator which wraps HistoryAccessor method calls to catch errors from a corrupt SQLite database, move the old database out of the way, and create a new one. - - We avoid clobbering larger databases because this may be triggered due to filesystem issues, - not just a corrupt file. + + We avoid clobbering larger databases because this may be triggered due to filesystem issues, + not just a corrupt file. """ try: return f(self, *a, **kw) - except (DatabaseError, OperationalError) as e: - self._corrupt_db_counter += 1 - self.log.error("Failed to open SQLite history %s (%s).", self.hist_file, e) - if self.hist_file != ':memory:': - if self._corrupt_db_counter > self._corrupt_db_limit: - self.hist_file = ':memory:' - self.log.error("Failed to load history too many times, history will not be saved.") - elif os.path.isfile(self.hist_file): - # move the file out of the way - base, ext = os.path.splitext(self.hist_file) - size = os.stat(self.hist_file).st_size - if size >= _SAVE_DB_SIZE: - # if there's significant content, avoid clobbering - now = datetime.datetime.now().isoformat().replace(':', '.') - newpath = base + '-corrupt-' + now + ext - # don't clobber previous corrupt backups - for i in range(100): - if not os.path.isfile(newpath): - break - else: - newpath = base + '-corrupt-' + now + (u'-%i' % i) + ext - else: - # not much content, possibly empty; don't worry about clobbering - # maybe we should just delete it? - newpath = base + '-corrupt' + ext - os.rename(self.hist_file, newpath) - self.log.error("History file was moved to %s and a new file created.", newpath) + except (DatabaseError, OperationalError) as e: + self._corrupt_db_counter += 1 + self.log.error("Failed to open SQLite history %s (%s).", self.hist_file, e) + if self.hist_file != ':memory:': + if self._corrupt_db_counter > self._corrupt_db_limit: + self.hist_file = ':memory:' + self.log.error("Failed to load history too many times, history will not be saved.") + elif os.path.isfile(self.hist_file): + # move the file out of the way + base, ext = os.path.splitext(self.hist_file) + size = os.stat(self.hist_file).st_size + if size >= _SAVE_DB_SIZE: + # if there's significant content, avoid clobbering + now = datetime.datetime.now().isoformat().replace(':', '.') + newpath = base + '-corrupt-' + now + ext + # don't clobber previous corrupt backups + for i in range(100): + if not os.path.isfile(newpath): + break + else: + newpath = base + '-corrupt-' + now + (u'-%i' % i) + ext + else: + # not much content, possibly empty; don't worry about clobbering + # maybe we should just delete it? + newpath = base + '-corrupt' + ext + os.rename(self.hist_file, newpath) + self.log.error("History file was moved to %s and a new file created.", newpath) self.init_db() return [] else: - # Failed with :memory:, something serious is wrong + # Failed with :memory:, something serious is wrong raise -class HistoryAccessorBase(LoggingConfigurable): +class HistoryAccessorBase(LoggingConfigurable): """An abstract class for History Accessors """ def get_tail(self, n=10, raw=True, output=False, include_latest=False): @@ -143,13 +143,13 @@ class HistoryAccessor(HistoryAccessorBase): This is intended for use by standalone history tools. IPython shells use HistoryManager, below, which is a subclass of this.""" - # counter for init_db retries, so we don't keep trying over and over - _corrupt_db_counter = 0 - # after two failures, fallback on :memory: - _corrupt_db_limit = 2 - + # counter for init_db retries, so we don't keep trying over and over + _corrupt_db_counter = 0 + # after two failures, fallback on :memory: + _corrupt_db_limit = 2 + # String holding the path to the history file - hist_file = Unicode( + hist_file = Unicode( help="""Path to file to use for SQLite history database. By default, IPython will put the history database in the IPython @@ -161,13 +161,13 @@ class HistoryAccessor(HistoryAccessorBase): local disk, e.g:: ipython --HistoryManager.hist_file=/tmp/ipython_hist.sqlite - - you can also use the specific value `:memory:` (including the colon - at both end but not the back ticks), to avoid creating an history file. + + you can also use the specific value `:memory:` (including the colon + at both end but not the back ticks), to avoid creating an history file. - """).tag(config=True) + """).tag(config=True) - enabled = Bool(True, + enabled = Bool(True, help="""enable the SQLite history set enabled=False to disable the SQLite history, @@ -175,22 +175,22 @@ class HistoryAccessor(HistoryAccessorBase): and no background saving thread. This may be necessary in some threaded environments where IPython is embedded. """ - ).tag(config=True) + ).tag(config=True) - connection_options = Dict( + connection_options = Dict( help="""Options for configuring the SQLite connection These options are passed as keyword args to sqlite3.connect when establishing database conenctions. """ - ).tag(config=True) + ).tag(config=True) # The SQLite database db = Any() - @observe('db') - def _db_changed(self, change): + @observe('db') + def _db_changed(self, change): """validate the db, since it can be an Instance of two different types""" - new = change['new'] + new = change['new'] connection_types = (DummyDB,) if sqlite3 is not None: connection_types = (DummyDB, sqlite3.Connection) @@ -266,8 +266,8 @@ class HistoryAccessor(HistoryAccessorBase): (session integer, line integer, output text, PRIMARY KEY (session, line))""") self.db.commit() - # success! reset corrupt db count - self._corrupt_db_counter = 0 + # success! reset corrupt db count + self._corrupt_db_counter = 0 def writeout_cache(self): """Overridden by HistoryManager to dump the cache before certain @@ -486,7 +486,7 @@ class HistoryManager(HistoryAccessor): input_hist_raw = List([""]) # A list of directories visited during session dir_hist = List() - @default('dir_hist') + @default('dir_hist') def _dir_hist_default(self): try: return [py3compat.getcwd()] @@ -502,13 +502,13 @@ class HistoryManager(HistoryAccessor): # The number of the current session in the history database session_number = Integer() - db_log_output = Bool(False, + db_log_output = Bool(False, help="Should the history database include output? (default: no)" - ).tag(config=True) - db_cache_size = Integer(0, + ).tag(config=True) + db_cache_size = Integer(0, help="Write to database every x commands (higher values save disk access & power).\n" "Values of 1 or less effectively disable caching." - ).tag(config=True) + ).tag(config=True) # The input and output caches db_input_cache = List() db_output_cache = List() diff --git a/contrib/python/ipython/py2/IPython/core/historyapp.py b/contrib/python/ipython/py2/IPython/core/historyapp.py index d51426d2ca..d083a78822 100644 --- a/contrib/python/ipython/py2/IPython/core/historyapp.py +++ b/contrib/python/ipython/py2/IPython/core/historyapp.py @@ -34,17 +34,17 @@ This is an handy alias to `ipython history trim --keep=0` class HistoryTrim(BaseIPythonApplication): description = trim_hist_help - backup = Bool(False, - help="Keep the old history file as history.sqlite.<N>" - ).tag(config=True) + backup = Bool(False, + help="Keep the old history file as history.sqlite.<N>" + ).tag(config=True) - keep = Int(1000, - help="Number of recent lines to keep in the database." - ).tag(config=True) + keep = Int(1000, + help="Number of recent lines to keep in the database." + ).tag(config=True) flags = Dict(dict( backup = ({'HistoryTrim' : {'backup' : True}}, - backup.help + backup.help ) )) @@ -120,18 +120,18 @@ class HistoryTrim(BaseIPythonApplication): class HistoryClear(HistoryTrim): description = clear_hist_help - keep = Int(0, + keep = Int(0, help="Number of recent lines to keep in the database.") - force = Bool(False, - help="Don't prompt user for confirmation" - ).tag(config=True) + force = Bool(False, + help="Don't prompt user for confirmation" + ).tag(config=True) flags = Dict(dict( force = ({'HistoryClear' : {'force' : True}}, - force.help), + force.help), f = ({'HistoryTrim' : {'force' : True}}, - force.help + force.help ) )) aliases = Dict() diff --git a/contrib/python/ipython/py2/IPython/core/hooks.py b/contrib/python/ipython/py2/IPython/core/hooks.py index e6fc84087f..a93bc31627 100644 --- a/contrib/python/ipython/py2/IPython/core/hooks.py +++ b/contrib/python/ipython/py2/IPython/core/hooks.py @@ -37,7 +37,7 @@ example, you could use a startup file like this:: import os import subprocess -import warnings +import warnings import sys from IPython.core.error import TryNext @@ -84,24 +84,24 @@ def editor(self, filename, linenum=None, wait=True): import tempfile def fix_error_editor(self,filename,linenum,column,msg): - """DEPRECATED - - Open the editor at the given filename, linenumber, column and + """DEPRECATED + + Open the editor at the given filename, linenumber, column and show an error message. This is used for correcting syntax errors. The current implementation only has special support for the VIM editor, and falls back on the 'editor' hook if VIM is not used. - Call ip.set_hook('fix_error_editor',yourfunc) to use your own function, + Call ip.set_hook('fix_error_editor',yourfunc) to use your own function, """ - - warnings.warn(""" -`fix_error_editor` is pending deprecation as of IPython 5.0 and will be removed -in future versions. It appears to be used only for automatically fixing syntax -error that has been broken for a few years and has thus been removed. If you -happend to use this function and still need it please make your voice heard on + + warnings.warn(""" +`fix_error_editor` is pending deprecation as of IPython 5.0 and will be removed +in future versions. It appears to be used only for automatically fixing syntax +error that has been broken for a few years and has thus been removed. If you +happend to use this function and still need it please make your voice heard on the mailing list ipython-dev@python.org , or on the GitHub Issue tracker: -https://github.com/ipython/ipython/issues/9649 """, UserWarning) - +https://github.com/ipython/ipython/issues/9649 """, UserWarning) + def vim_quickfix_file(): t = tempfile.NamedTemporaryFile() t.write('%s:%d:%d:%s\n' % (filename,linenum,column,msg)) diff --git a/contrib/python/ipython/py2/IPython/core/interactiveshell.py b/contrib/python/ipython/py2/IPython/core/interactiveshell.py index ad8824b606..67b84a6e5f 100644 --- a/contrib/python/ipython/py2/IPython/core/interactiveshell.py +++ b/contrib/python/ipython/py2/IPython/core/interactiveshell.py @@ -31,7 +31,7 @@ from io import open as io_open from pickleshare import PickleShareDB from traitlets.config.configurable import SingletonConfigurable -from IPython.core import oinspect +from IPython.core import oinspect from IPython.core import magic from IPython.core import page from IPython.core import prefilter @@ -42,7 +42,7 @@ from IPython.core.autocall import ExitAutocall from IPython.core.builtin_trap import BuiltinTrap from IPython.core.events import EventManager, available_events from IPython.core.compilerop import CachingCompiler, check_linecache_ipython -from IPython.core.debugger import Pdb +from IPython.core.debugger import Pdb from IPython.core.display_trap import DisplayTrap from IPython.core.displayhook import DisplayHook from IPython.core.displaypub import DisplayPublisher @@ -50,14 +50,14 @@ from IPython.core.error import InputRejected, UsageError from IPython.core.extensions import ExtensionManager from IPython.core.formatters import DisplayFormatter from IPython.core.history import HistoryManager -from IPython.core.inputsplitter import ESC_MAGIC, ESC_MAGIC2 +from IPython.core.inputsplitter import ESC_MAGIC, ESC_MAGIC2 from IPython.core.logger import Logger from IPython.core.macro import Macro from IPython.core.payload import PayloadManager from IPython.core.prefilter import PrefilterManager from IPython.core.profiledir import ProfileDir from IPython.core.usage import default_banner -from IPython.testing.skipdoctest import skip_doctest_py2, skip_doctest +from IPython.testing.skipdoctest import skip_doctest_py2, skip_doctest from IPython.display import display from IPython.utils import PyColorize from IPython.utils import io @@ -67,45 +67,45 @@ from IPython.utils.decorators import undoc from IPython.utils.io import ask_yes_no from IPython.utils.ipstruct import Struct from IPython.paths import get_ipython_dir -from IPython.utils.path import get_home_dir, get_py_filename, ensure_dir_exists +from IPython.utils.path import get_home_dir, get_py_filename, ensure_dir_exists from IPython.utils.process import system, getoutput from IPython.utils.py3compat import (builtin_mod, unicode_type, string_types, with_metaclass, iteritems) from IPython.utils.strdispatch import StrDispatch from IPython.utils.syspathcontext import prepended_to_syspath -from IPython.utils.text import format_screen, LSString, SList, DollarFormatter -from IPython.utils.tempdir import TemporaryDirectory -from traitlets import ( - Integer, Bool, CaselessStrEnum, Enum, List, Dict, Unicode, Instance, Type, - observe, default, -) -from warnings import warn -from logging import error +from IPython.utils.text import format_screen, LSString, SList, DollarFormatter +from IPython.utils.tempdir import TemporaryDirectory +from traitlets import ( + Integer, Bool, CaselessStrEnum, Enum, List, Dict, Unicode, Instance, Type, + observe, default, +) +from warnings import warn +from logging import error import IPython.core.hooks -# NoOpContext is deprecated, but ipykernel imports it from here. -# See https://github.com/ipython/ipykernel/issues/157 -from IPython.utils.contexts import NoOpContext - -try: - import docrepr.sphinxify as sphx - - def sphinxify(doc): - with TemporaryDirectory() as dirname: - return { - 'text/html': sphx.sphinxify(doc, dirname), - 'text/plain': doc - } -except ImportError: - sphinxify = None - - -class ProvisionalWarning(DeprecationWarning): - """ - Warning class for unstable features - """ - pass - +# NoOpContext is deprecated, but ipykernel imports it from here. +# See https://github.com/ipython/ipykernel/issues/157 +from IPython.utils.contexts import NoOpContext + +try: + import docrepr.sphinxify as sphx + + def sphinxify(doc): + with TemporaryDirectory() as dirname: + return { + 'text/html': sphx.sphinxify(doc, dirname), + 'text/plain': doc + } +except ImportError: + sphinxify = None + + +class ProvisionalWarning(DeprecationWarning): + """ + Warning class for unstable features + """ + pass + #----------------------------------------------------------------------------- # Globals #----------------------------------------------------------------------------- @@ -141,10 +141,10 @@ class SpaceInInput(Exception): pass def get_default_colors(): - "DEPRECATED" - warn('get_default_color is Deprecated, and is `Neutral` on all platforms.', - DeprecationWarning, stacklevel=2) - return 'Neutral' + "DEPRECATED" + warn('get_default_color is Deprecated, and is `Neutral` on all platforms.', + DeprecationWarning, stacklevel=2) + return 'Neutral' class SeparateUnicode(Unicode): @@ -187,28 +187,28 @@ class ExecutionResult(object): if self.error_in_exec is not None: raise self.error_in_exec - def __repr__(self): - if sys.version_info > (3,): - name = self.__class__.__qualname__ - else: - name = self.__class__.__name__ - return '<%s object at %x, execution_count=%s error_before_exec=%s error_in_exec=%s result=%s>' %\ - (name, id(self), self.execution_count, self.error_before_exec, self.error_in_exec, repr(self.result)) - + def __repr__(self): + if sys.version_info > (3,): + name = self.__class__.__qualname__ + else: + name = self.__class__.__name__ + return '<%s object at %x, execution_count=%s error_before_exec=%s error_in_exec=%s result=%s>' %\ + (name, id(self), self.execution_count, self.error_before_exec, self.error_in_exec, repr(self.result)) + class InteractiveShell(SingletonConfigurable): """An enhanced, interactive shell for Python.""" _instance = None - - ast_transformers = List([], help= + + ast_transformers = List([], help= """ A list of ast.NodeTransformer subclass instances, which will be applied to user input before code is run. """ - ).tag(config=True) + ).tag(config=True) - autocall = Enum((0,1,2), default_value=0, help= + autocall = Enum((0,1,2), default_value=0, help= """ Make IPython automatically call any callable object even if you didn't type explicit parentheses. For example, 'str 43' becomes 'str(43)' @@ -217,29 +217,29 @@ class InteractiveShell(SingletonConfigurable): arguments on the line, and '2' for 'full' autocall, where all callable objects are automatically called (even if no arguments are present). """ - ).tag(config=True) + ).tag(config=True) # TODO: remove all autoindent logic and put into frontends. # We can't do this yet because even runlines uses the autoindent. - autoindent = Bool(True, help= + autoindent = Bool(True, help= """ Autoindent IPython code entered interactively. """ - ).tag(config=True) - - automagic = Bool(True, help= + ).tag(config=True) + + automagic = Bool(True, help= """ Enable magic commands to be called without the leading %. """ - ).tag(config=True) - - banner1 = Unicode(default_banner, + ).tag(config=True) + + banner1 = Unicode(default_banner, help="""The part of the banner to be printed before the profile""" - ).tag(config=True) - banner2 = Unicode('', + ).tag(config=True) + banner2 = Unicode('', help="""The part of the banner to be printed after the profile""" - ).tag(config=True) + ).tag(config=True) - cache_size = Integer(1000, help= + cache_size = Integer(1000, help= """ Set the size of the output cache. The default is 1000, you can change it permanently in your config file. Setting it to 0 completely @@ -248,20 +248,20 @@ class InteractiveShell(SingletonConfigurable): issued). This limit is defined because otherwise you'll spend more time re-flushing a too small cache than working """ - ).tag(config=True) - color_info = Bool(True, help= + ).tag(config=True) + color_info = Bool(True, help= """ Use colors for displaying information about objects. Because this information is passed through a pager (like 'less'), and some pagers get confused with color codes, this capability can be turned off. """ - ).tag(config=True) - colors = CaselessStrEnum(('Neutral', 'NoColor','LightBG','Linux'), - default_value='Neutral', - help="Set the color scheme (NoColor, Neutral, Linux, or LightBG)." - ).tag(config=True) - debug = Bool(False).tag(config=True) - deep_reload = Bool(False, help= + ).tag(config=True) + colors = CaselessStrEnum(('Neutral', 'NoColor','LightBG','Linux'), + default_value='Neutral', + help="Set the color scheme (NoColor, Neutral, Linux, or LightBG)." + ).tag(config=True) + debug = Bool(False).tag(config=True) + deep_reload = Bool(False, help= """ **Deprecated** @@ -275,47 +275,47 @@ class InteractiveShell(SingletonConfigurable): deep_reload is off, IPython will use the normal reload(), but deep_reload will still be available as dreload(). """ - ).tag(config=True) - disable_failing_post_execute = Bool(False, + ).tag(config=True) + disable_failing_post_execute = Bool(False, help="Don't call post-execute functions that have failed in the past." - ).tag(config=True) + ).tag(config=True) display_formatter = Instance(DisplayFormatter, allow_none=True) displayhook_class = Type(DisplayHook) display_pub_class = Type(DisplayPublisher) - - sphinxify_docstring = Bool(False, help= - """ - Enables rich html representation of docstrings. (This requires the - docrepr module). - """).tag(config=True) - - @observe("sphinxify_docstring") - def _sphinxify_docstring_changed(self, change): - if change['new']: - warn("`sphinxify_docstring` is provisional since IPython 5.0 and might change in future versions." , ProvisionalWarning) - - enable_html_pager = Bool(False, help= - """ - (Provisional API) enables html representation in mime bundles sent - to pagers. - """).tag(config=True) - - @observe("enable_html_pager") - def _enable_html_pager_changed(self, change): - if change['new']: - warn("`enable_html_pager` is provisional since IPython 5.0 and might change in future versions.", ProvisionalWarning) - + + sphinxify_docstring = Bool(False, help= + """ + Enables rich html representation of docstrings. (This requires the + docrepr module). + """).tag(config=True) + + @observe("sphinxify_docstring") + def _sphinxify_docstring_changed(self, change): + if change['new']: + warn("`sphinxify_docstring` is provisional since IPython 5.0 and might change in future versions." , ProvisionalWarning) + + enable_html_pager = Bool(False, help= + """ + (Provisional API) enables html representation in mime bundles sent + to pagers. + """).tag(config=True) + + @observe("enable_html_pager") + def _enable_html_pager_changed(self, change): + if change['new']: + warn("`enable_html_pager` is provisional since IPython 5.0 and might change in future versions.", ProvisionalWarning) + data_pub_class = None - exit_now = Bool(False) + exit_now = Bool(False) exiter = Instance(ExitAutocall) - @default('exiter') + @default('exiter') def _exiter_default(self): return ExitAutocall(self) # Monotonically increasing execution counter execution_count = Integer(1) filename = Unicode("<ipython console>") - ipython_dir= Unicode('').tag(config=True) # Set to get_ipython_dir() in __init__ + ipython_dir= Unicode('').tag(config=True) # Set to get_ipython_dir() in __init__ # Input splitter, to transform input line by line and detect when a block # is ready to be executed. @@ -327,90 +327,90 @@ class InteractiveShell(SingletonConfigurable): input_transformer_manager = Instance('IPython.core.inputsplitter.IPythonInputSplitter', (), {'line_input_checker': False}) - logstart = Bool(False, help= + logstart = Bool(False, help= """ Start logging to the default log file in overwrite mode. Use `logappend` to specify a log file to **append** logs to. """ - ).tag(config=True) - logfile = Unicode('', help= + ).tag(config=True) + logfile = Unicode('', help= """ The name of the logfile to use. """ - ).tag(config=True) - logappend = Unicode('', help= + ).tag(config=True) + logappend = Unicode('', help= """ Start logging to the given file in append mode. Use `logfile` to specify a log file to **overwrite** logs to. """ - ).tag(config=True) + ).tag(config=True) object_info_string_level = Enum((0,1,2), default_value=0, - ).tag(config=True) - pdb = Bool(False, help= + ).tag(config=True) + pdb = Bool(False, help= """ Automatically call the pdb debugger after every exception. """ - ).tag(config=True) - display_page = Bool(False, + ).tag(config=True) + display_page = Bool(False, help="""If True, anything that would be passed to the pager will be displayed as regular output instead.""" - ).tag(config=True) + ).tag(config=True) # deprecated prompt traits: - - prompt_in1 = Unicode('In [\\#]: ', - help="Deprecated since IPython 4.0 and ignored since 5.0, set TerminalInteractiveShell.prompts object directly." - ).tag(config=True) - prompt_in2 = Unicode(' .\\D.: ', - help="Deprecated since IPython 4.0 and ignored since 5.0, set TerminalInteractiveShell.prompts object directly." - ).tag(config=True) - prompt_out = Unicode('Out[\\#]: ', - help="Deprecated since IPython 4.0 and ignored since 5.0, set TerminalInteractiveShell.prompts object directly." - ).tag(config=True) - prompts_pad_left = Bool(True, - help="Deprecated since IPython 4.0 and ignored since 5.0, set TerminalInteractiveShell.prompts object directly." - ).tag(config=True) - - @observe('prompt_in1', 'prompt_in2', 'prompt_out', 'prompt_pad_left') - def _prompt_trait_changed(self, change): - name = change['name'] - warn("InteractiveShell.{name} is deprecated since IPython 4.0 and ignored since 5.0, set TerminalInteractiveShell.prompts object directly.".format( - name=name) + + prompt_in1 = Unicode('In [\\#]: ', + help="Deprecated since IPython 4.0 and ignored since 5.0, set TerminalInteractiveShell.prompts object directly." + ).tag(config=True) + prompt_in2 = Unicode(' .\\D.: ', + help="Deprecated since IPython 4.0 and ignored since 5.0, set TerminalInteractiveShell.prompts object directly." + ).tag(config=True) + prompt_out = Unicode('Out[\\#]: ', + help="Deprecated since IPython 4.0 and ignored since 5.0, set TerminalInteractiveShell.prompts object directly." + ).tag(config=True) + prompts_pad_left = Bool(True, + help="Deprecated since IPython 4.0 and ignored since 5.0, set TerminalInteractiveShell.prompts object directly." + ).tag(config=True) + + @observe('prompt_in1', 'prompt_in2', 'prompt_out', 'prompt_pad_left') + def _prompt_trait_changed(self, change): + name = change['name'] + warn("InteractiveShell.{name} is deprecated since IPython 4.0 and ignored since 5.0, set TerminalInteractiveShell.prompts object directly.".format( + name=name) ) # protect against weird cases where self.config may not exist: - show_rewritten_input = Bool(True, + show_rewritten_input = Bool(True, help="Show rewritten input, e.g. for autocall." - ).tag(config=True) + ).tag(config=True) - quiet = Bool(False).tag(config=True) + quiet = Bool(False).tag(config=True) - history_length = Integer(10000, - help='Total length of command history' - ).tag(config=True) + history_length = Integer(10000, + help='Total length of command history' + ).tag(config=True) - history_load_length = Integer(1000, help= + history_load_length = Integer(1000, help= """ The number of saved history entries to be loaded - into the history buffer at startup. + into the history buffer at startup. """ - ).tag(config=True) + ).tag(config=True) ast_node_interactivity = Enum(['all', 'last', 'last_expr', 'none'], - default_value='last_expr', + default_value='last_expr', help=""" 'all', 'last', 'last_expr' or 'none', specifying which nodes should be - run interactively (displaying output from expressions).""" - ).tag(config=True) + run interactively (displaying output from expressions).""" + ).tag(config=True) # TODO: this part of prompt management should be moved to the frontends. # Use custom TraitTypes that convert '0'->'' and '\\n'->'\n' - separate_in = SeparateUnicode('\n').tag(config=True) - separate_out = SeparateUnicode('').tag(config=True) - separate_out2 = SeparateUnicode('').tag(config=True) - wildcards_case_sensitive = Bool(True).tag(config=True) + separate_in = SeparateUnicode('\n').tag(config=True) + separate_out = SeparateUnicode('').tag(config=True) + separate_out2 = SeparateUnicode('').tag(config=True) + wildcards_case_sensitive = Bool(True).tag(config=True) xmode = CaselessStrEnum(('Context','Plain', 'Verbose'), - default_value='Context').tag(config=True) + default_value='Context').tag(config=True) # Subcomponents of InteractiveShell alias_manager = Instance('IPython.core.alias.AliasManager', allow_none=True) @@ -436,8 +436,8 @@ class InteractiveShell(SingletonConfigurable): # Tracks any GUI loop loaded for pylab pylab_gui_select = None - last_execution_succeeded = Bool(True, help='Did last executed command succeeded') - + last_execution_succeeded = Bool(True, help='Did last executed command succeeded') + def __init__(self, ipython_dir=None, profile_dir=None, user_module=None, user_ns=None, custom_exceptions=((), None), **kwargs): @@ -445,9 +445,9 @@ class InteractiveShell(SingletonConfigurable): # This is where traits with a config_key argument are updated # from the values on config. super(InteractiveShell, self).__init__(**kwargs) - if 'PromptManager' in self.config: - warn('As of IPython 5.0 `PromptManager` config will have no effect' - ' and has been replaced by TerminalInteractiveShell.prompts_class') + if 'PromptManager' in self.config: + warn('As of IPython 5.0 `PromptManager` config will have no effect' + ' and has been replaced by TerminalInteractiveShell.prompts_class') self.configurables = [self] # These are relatively independent and stateless @@ -455,7 +455,7 @@ class InteractiveShell(SingletonConfigurable): self.init_profile_dir(profile_dir) self.init_instance_attrs() self.init_environment() - + # Check if we're in a virtualenv, and set up sys.path. self.init_virtualenv() @@ -522,12 +522,12 @@ class InteractiveShell(SingletonConfigurable): #------------------------------------------------------------------------- # Trait changed handlers #------------------------------------------------------------------------- - @observe('ipython_dir') - def _ipython_dir_changed(self, change): - ensure_dir_exists(change['new']) + @observe('ipython_dir') + def _ipython_dir_changed(self, change): + ensure_dir_exists(change['new']) def set_autoindent(self,value=None): - """Set the autoindent flag. + """Set the autoindent flag. If called with no arguments, it acts as a toggle.""" if value is None: @@ -598,10 +598,10 @@ class InteractiveShell(SingletonConfigurable): pyformat = PyColorize.Parser().format self.pycolorize = lambda src: pyformat(src,'str',self.colors) - def refresh_style(self): - # No-op here, used in subclass - pass - + def refresh_style(self): + # No-op here, used in subclass + pass + def init_pushd_popd_magic(self): # for pushd/popd management self.home_dir = get_home_dir() @@ -653,10 +653,10 @@ class InteractiveShell(SingletonConfigurable): # override sys.stdout and sys.stderr themselves, you need to do that # *before* instantiating this class, because io holds onto # references to the underlying streams. - # 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.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) @@ -700,15 +700,15 @@ class InteractiveShell(SingletonConfigurable): virtualenv was built, and it ignores the --no-site-packages option. A warning will appear suggesting the user installs IPython in the virtualenv, but for many cases, it probably works well enough. - + Adapted from code snippets online. - + http://blog.ufsoft.org/2009/1/29/ipython-and-virtualenv """ if 'VIRTUAL_ENV' not in os.environ: # Not in a virtualenv return - + # venv detection: # stdlib venv may symlink sys.executable, so we can't use realpath. # but others can symlink *to* the venv Python, so we can't just use sys.executable. @@ -722,15 +722,15 @@ class InteractiveShell(SingletonConfigurable): if any(p.startswith(p_venv) for p in paths): # Running properly in the virtualenv, don't need to do anything return - + warn("Attempting to work in a virtualenv. If you encounter problems, please " "install IPython inside the virtualenv.") if sys.platform == "win32": - virtual_env = os.path.join(os.environ['VIRTUAL_ENV'], 'Lib', 'site-packages') + virtual_env = os.path.join(os.environ['VIRTUAL_ENV'], 'Lib', 'site-packages') else: virtual_env = os.path.join(os.environ['VIRTUAL_ENV'], 'lib', 'python%d.%d' % sys.version_info[:2], 'site-packages') - + import site sys.path.insert(0, virtual_env) site.addsitedir(virtual_env) @@ -765,7 +765,7 @@ class InteractiveShell(SingletonConfigurable): #------------------------------------------------------------------------- # Things related to the banner #------------------------------------------------------------------------- - + @property def banner(self): banner = self.banner1 @@ -778,8 +778,8 @@ class InteractiveShell(SingletonConfigurable): def show_banner(self, banner=None): if banner is None: banner = self.banner - sys.stdout.write(banner) - + sys.stdout.write(banner) + #------------------------------------------------------------------------- # Things related to hooks #------------------------------------------------------------------------- @@ -796,10 +796,10 @@ class InteractiveShell(SingletonConfigurable): # default hooks have priority 100, i.e. low; user hooks should have # 0-100 priority self.set_hook(hook_name,getattr(hooks,hook_name), 100, _warn_deprecated=False) - + if self.display_page: self.set_hook('show_in_pager', page.as_hook(page.display_page), 90) - + def set_hook(self,name,hook, priority=50, str_key=None, re_key=None, _warn_deprecated=True): """set_hook(name,hook) -> sets an internal IPython hook. @@ -857,13 +857,13 @@ class InteractiveShell(SingletonConfigurable): def register_post_execute(self, func): """DEPRECATED: Use ip.events.register('post_run_cell', func) - + Register a function for calling after code execution. """ warn("ip.register_post_execute is deprecated, use " "ip.events.register('post_run_cell', func) instead.") self.events.register('post_run_cell', func) - + def _clear_warning_registry(self): # clear the warning registry, so that different code blocks with # overlapping line number ranges don't cause spurious suppression of @@ -877,14 +877,14 @@ class InteractiveShell(SingletonConfigurable): def new_main_mod(self, filename, modname): """Return a new 'main' module object for user code execution. - + ``filename`` should be the path of the script which will be run in the module. Requests with the same filename will get the same module, with its namespace cleared. - + ``modname`` should be the module name - normally either '__main__' or the basename of the file without the extension. - + When scripts are executed via %run, we must keep a reference to their __main__ module around so that Python doesn't clear it, rendering references to module globals useless. @@ -905,12 +905,12 @@ class InteractiveShell(SingletonConfigurable): else: main_mod.__dict__.clear() main_mod.__name__ = modname - + main_mod.__file__ = filename # It seems pydoc (and perhaps others) needs any module instance to # implement a __nonzero__ method main_mod.__nonzero__ = lambda : True - + return main_mod def clear_main_mod_cache(self): @@ -962,7 +962,7 @@ class InteractiveShell(SingletonConfigurable): 'Control auto-activation of pdb at exceptions') def debugger(self,force=False): - """Call the pdb debugger. + """Call the pdb debugger. Keywords: @@ -979,7 +979,7 @@ class InteractiveShell(SingletonConfigurable): error('No traceback has been produced, nothing to debug.') return - self.InteractiveTB.debugger(force=True) + self.InteractiveTB.debugger(force=True) #------------------------------------------------------------------------- # Things related to IPython's various namespaces @@ -1063,17 +1063,17 @@ class InteractiveShell(SingletonConfigurable): 'user_local':self.user_ns, 'builtin':builtin_mod.__dict__ } - + @property def user_global_ns(self): return self.user_module.__dict__ def prepare_user_module(self, user_module=None, user_ns=None): """Prepare the module and namespace in which user code will be run. - + When IPython is started normally, both parameters are None: a new module is created automatically, and its __dict__ used as the namespace. - + If only user_module is provided, its __dict__ is used as the namespace. If only user_ns is provided, a dummy module is created, and user_ns becomes the global namespace. If both are provided (as they may be @@ -1096,17 +1096,17 @@ class InteractiveShell(SingletonConfigurable): user_ns.setdefault("__name__", "__main__") user_module = DummyMod() user_module.__dict__ = user_ns - + if user_module is None: user_module = types.ModuleType("__main__", doc="Automatically created module for IPython interactive environment") - + # We must ensure that __builtin__ (without the final 's') is always # available and pointing to the __builtin__ *module*. For more details: # http://mail.python.org/pipermail/python-dev/2001-April/014068.html user_module.__dict__.setdefault('__builtin__', builtin_mod) user_module.__dict__.setdefault('__builtins__', builtin_mod) - + if user_ns is None: user_ns = user_module.__dict__ @@ -1162,7 +1162,7 @@ class InteractiveShell(SingletonConfigurable): # For more details: # http://mail.python.org/pipermail/python-dev/2001-April/014068.html ns = dict() - + # make global variables for user access to the histories ns['_ih'] = self.history_manager.input_hist_parsed ns['_oh'] = self.history_manager.output_hist @@ -1177,7 +1177,7 @@ class InteractiveShell(SingletonConfigurable): # Store myself as the public api!!! ns['get_ipython'] = self.get_ipython - + ns['exit'] = self.exiter ns['quit'] = self.exiter @@ -1191,12 +1191,12 @@ class InteractiveShell(SingletonConfigurable): # Finally, update the real user's namespace self.user_ns.update(ns) - + @property def all_ns_refs(self): """Get a list of references to all the namespace dictionaries in which IPython might store a user-created object. - + Note that this does not include the displayhook, which also caches objects from the output.""" return [self.user_ns, self.user_global_ns, self.user_ns_hidden] + \ @@ -1230,9 +1230,9 @@ class InteractiveShell(SingletonConfigurable): drop_keys.discard('__name__') for k in drop_keys: del ns[k] - + self.user_ns_hidden.clear() - + # Restore the user namespaces to minimal usability self.init_user_ns() @@ -1261,7 +1261,7 @@ class InteractiveShell(SingletonConfigurable): raise ValueError("Refusing to delete %s" % varname) ns_refs = self.all_ns_refs - + if by_name: # Delete by name for ns in ns_refs: try: @@ -1358,11 +1358,11 @@ class InteractiveShell(SingletonConfigurable): def drop_by_id(self, variables): """Remove a dict of variables from the user namespace, if they are the same as the values in the dictionary. - + This is intended for use by extensions: variables that they've added can be taken back out if they are unloaded, without removing any that the user has overwritten. - + Parameters ---------- variables : dict @@ -1520,20 +1520,20 @@ class InteractiveShell(SingletonConfigurable): def _inspect(self, meth, oname, namespaces=None, **kw): """Generic interface to the inspector system. - This function is meant to be called by pdef, pdoc & friends. - """ + This function is meant to be called by pdef, pdoc & friends. + """ info = self._object_find(oname, namespaces) - docformat = sphinxify if self.sphinxify_docstring else None + docformat = sphinxify if self.sphinxify_docstring else None if info.found: pmethod = getattr(self.inspector, meth) - # TODO: only apply format_screen to the plain/text repr of the mime - # bundle. - formatter = format_screen if info.ismagic else docformat + # TODO: only apply format_screen to the plain/text repr of the mime + # bundle. + formatter = format_screen if info.ismagic else docformat if meth == 'pdoc': pmethod(info.obj, oname, formatter) elif meth == 'pinfo': - pmethod(info.obj, oname, formatter, info, - enable_html_pager=self.enable_html_pager, **kw) + pmethod(info.obj, oname, formatter, info, + enable_html_pager=self.enable_html_pager, **kw) else: pmethod(info.obj, oname) else: @@ -1553,18 +1553,18 @@ class InteractiveShell(SingletonConfigurable): def object_inspect_text(self, oname, detail_level=0): """Get object info as formatted text""" - return self.object_inspect_mime(oname, detail_level)['text/plain'] - - def object_inspect_mime(self, oname, detail_level=0): - """Get object info as a mimebundle of formatted representations. - - A mimebundle is a dictionary, keyed by mime-type. - It must always have the key `'text/plain'`. - """ + return self.object_inspect_mime(oname, detail_level)['text/plain'] + + def object_inspect_mime(self, oname, detail_level=0): + """Get object info as a mimebundle of formatted representations. + + A mimebundle is a dictionary, keyed by mime-type. + It must always have the key `'text/plain'`. + """ with self.builtin_trap: info = self._object_find(oname) if info.found: - return self.inspector._get_info(info.obj, oname, info=info, + return self.inspector._get_info(info.obj, oname, info=info, detail_level=detail_level ) else: @@ -1583,8 +1583,8 @@ class InteractiveShell(SingletonConfigurable): # Things related to exception handling and tracebacks (not debugging) #------------------------------------------------------------------------- - debugger_cls = Pdb - + debugger_cls = Pdb + def init_traceback_handlers(self, custom_exceptions): # Syntax error handler. self.SyntaxTB = ultratb.SyntaxTB(color_scheme='NoColor') @@ -1595,8 +1595,8 @@ class InteractiveShell(SingletonConfigurable): self.InteractiveTB = ultratb.AutoFormattedTB(mode = 'Plain', color_scheme='NoColor', tb_offset = 1, - check_cache=check_linecache_ipython, - debugger_cls=self.debugger_cls) + check_cache=check_linecache_ipython, + debugger_cls=self.debugger_cls) # The instance will store a pointer to the system-wide exception hook, # so that runtime code (such as magics) can access it. This is because @@ -1610,7 +1610,7 @@ class InteractiveShell(SingletonConfigurable): self.InteractiveTB.set_mode(mode=self.xmode) def set_custom_exc(self, exc_tuple, handler): - """set_custom_exc(exc_tuple, handler) + """set_custom_exc(exc_tuple, handler) Set a custom exception handler, which will be called if any of the exceptions in exc_tuple occur in the mainloop (specifically, in the @@ -1653,19 +1653,19 @@ class InteractiveShell(SingletonConfigurable): assert type(exc_tuple)==type(()) , \ "The custom exceptions must be given AS A TUPLE." - def dummy_handler(self, etype, value, tb, tb_offset=None): + def dummy_handler(self, etype, value, tb, tb_offset=None): print('*** Simple custom exception handler ***') print('Exception type :',etype) print('Exception value:',value) print('Traceback :',tb) #print 'Source code :','\n'.join(self.buffer) - + def validate_stb(stb): """validate structured traceback return type - + return type of CustomTB *should* be a list of strings, but allow single strings or None, which are harmless. - + This function will *always* return a list of strings, and will raise a TypeError if stb is inappropriate. """ @@ -1688,7 +1688,7 @@ class InteractiveShell(SingletonConfigurable): else: def wrapped(self,etype,value,tb,tb_offset=None): """wrap CustomTB handler, to protect IPython from user code - + This makes it harder (but not impossible) for custom exception handlers to crash IPython. """ @@ -1698,11 +1698,11 @@ class InteractiveShell(SingletonConfigurable): except: # clear custom handler immediately self.set_custom_exc((), None) - print("Custom TB Handler failed, unregistering", file=sys.stderr) + print("Custom TB Handler failed, unregistering", file=sys.stderr) # show the exception in handler first stb = self.InteractiveTB.structured_traceback(*sys.exc_info()) - print(self.InteractiveTB.stb2text(stb)) - print("The original exception:") + print(self.InteractiveTB.stb2text(stb)) + print("The original exception:") stb = self.InteractiveTB.structured_traceback( (etype,value,tb), tb_offset=tb_offset ) @@ -1737,10 +1737,10 @@ class InteractiveShell(SingletonConfigurable): def _get_exc_info(self, exc_tuple=None): """get exc_info from a given tuple, sys.exc_info() or sys.last_type etc. - + Ensures sys.last_type,value,traceback hold the exc_info we found, from whichever source. - + raises ValueError if none of these contain any information """ if exc_tuple is None: @@ -1752,10 +1752,10 @@ class InteractiveShell(SingletonConfigurable): if hasattr(sys, 'last_type'): etype, value, tb = sys.last_type, sys.last_value, \ sys.last_traceback - + if etype is None: raise ValueError("No exception to find") - + # Now store the exception info in sys.last_type etc. # WARNING: these variables are somewhat deprecated and not # necessarily safe to use in a threaded environment, but tools @@ -1764,16 +1764,16 @@ class InteractiveShell(SingletonConfigurable): sys.last_type = etype sys.last_value = value sys.last_traceback = tb - + return etype, value, tb - + def show_usage_error(self, exc): """Show a short message for UsageErrors - + These are special exceptions that shouldn't show a traceback. """ - print("UsageError: %s" % exc, file=sys.stderr) - + print("UsageError: %s" % exc, file=sys.stderr) + def get_exception_only(self, exc_tuple=None): """ Return as a string (ending with a newline) the exception that @@ -1800,9 +1800,9 @@ class InteractiveShell(SingletonConfigurable): try: etype, value, tb = self._get_exc_info(exc_tuple) except ValueError: - print('No traceback available to show.', file=sys.stderr) + print('No traceback available to show.', file=sys.stderr) return - + if issubclass(etype, SyntaxError): # Though this won't be called by syntax errors in the input # line, there may be SyntaxError cases with imported code. @@ -1835,7 +1835,7 @@ class InteractiveShell(SingletonConfigurable): self._showtraceback(etype, value, stb) except KeyboardInterrupt: - print('\n' + self.get_exception_only(), file=sys.stderr) + print('\n' + self.get_exception_only(), file=sys.stderr) def _showtraceback(self, etype, evalue, stb): """Actually show a traceback. @@ -1843,7 +1843,7 @@ class InteractiveShell(SingletonConfigurable): Subclasses may override this method to put the traceback on a different place, like a side channel. """ - print(self.InteractiveTB.stb2text(stb)) + print(self.InteractiveTB.stb2text(stb)) def showsyntaxerror(self, filename=None): """Display the syntax error that just occurred. @@ -1862,7 +1862,7 @@ class InteractiveShell(SingletonConfigurable): except: # Not the format we expect; leave it alone pass - + stb = self.SyntaxTB.structured_traceback(etype, value, []) self._showtraceback(etype, value, stb) @@ -1881,12 +1881,12 @@ class InteractiveShell(SingletonConfigurable): #------------------------------------------------------------------------- def init_readline(self): - """DEPRECATED - - Moved to terminal subclass, here only to simplify the init logic.""" + """DEPRECATED + + Moved to terminal subclass, here only to simplify the init logic.""" # Set a number of methods that depend on readline to be no-op - warnings.warn('`init_readline` is no-op since IPython 5.0 and is Deprecated', - DeprecationWarning, stacklevel=2) + warnings.warn('`init_readline` is no-op since IPython 5.0 and is Deprecated', + DeprecationWarning, stacklevel=2) self.set_custom_completer = no_op @skip_doctest @@ -1923,7 +1923,7 @@ class InteractiveShell(SingletonConfigurable): self.Completer = IPCompleter(shell=self, namespace=self.user_ns, global_namespace=self.user_global_ns, - use_readline=False, + use_readline=False, parent=self, ) self.configurables.append(self.Completer) @@ -1941,7 +1941,7 @@ class InteractiveShell(SingletonConfigurable): self.set_hook('complete_command', reset_completer, str_key = '%reset') - @skip_doctest_py2 + @skip_doctest_py2 def complete(self, text, line=None, cursor_pos=None): """Return the completed text and a list of completions. @@ -2020,7 +2020,7 @@ class InteractiveShell(SingletonConfigurable): self.register_magics = self.magics_manager.register self.register_magics(m.AutoMagics, m.BasicMagics, m.CodeMagics, - m.ConfigMagics, m.DisplayMagics, m.ExecutionMagics, + m.ConfigMagics, m.DisplayMagics, m.ExecutionMagics, m.ExtensionMagics, m.HistoryMagics, m.LoggingMagics, m.NamespaceMagics, m.OSMagics, m.PylabMagics, m.ScriptMagics, ) @@ -2040,11 +2040,11 @@ class InteractiveShell(SingletonConfigurable): # should be split into a prompt manager and displayhook. We probably # even need a centralize colors management object. self.magic('colors %s' % self.colors) - + # Defined here so that it's included in the documentation @functools.wraps(magic.MagicsManager.register_function) def register_magic_function(self, func, magic_kind='line', magic_name=None): - self.magics_manager.register_function(func, + self.magics_manager.register_function(func, magic_kind=magic_kind, magic_name=magic_name) def run_line_magic(self, magic_name, line): @@ -2083,7 +2083,7 @@ class InteractiveShell(SingletonConfigurable): def run_cell_magic(self, magic_name, line, cell): """Execute the given cell magic. - + Parameters ---------- magic_name : str @@ -2230,7 +2230,7 @@ class InteractiveShell(SingletonConfigurable): try: ec = os.system(cmd) except KeyboardInterrupt: - print('\n' + self.get_exception_only(), file=sys.stderr) + print('\n' + self.get_exception_only(), file=sys.stderr) ec = -2 else: cmd = py3compat.unicode_to_str(cmd) @@ -2249,11 +2249,11 @@ class InteractiveShell(SingletonConfigurable): ec = subprocess.call(cmd, shell=True, executable=executable) except KeyboardInterrupt: # intercept control-C; a long traceback is not useful here - print('\n' + self.get_exception_only(), file=sys.stderr) + print('\n' + self.get_exception_only(), file=sys.stderr) ec = 130 if ec > 128: ec = -(ec - 128) - + # We explicitly do NOT return the subprocess status code, because # a non-None value would trigger :func:`sys.displayhook` calls. # Instead, we store the exit_code in user_ns. Note the semantics @@ -2316,7 +2316,7 @@ class InteractiveShell(SingletonConfigurable): def init_payload(self): self.payload_manager = PayloadManager(parent=self) self.configurables.append(self.payload_manager) - + #------------------------------------------------------------------------- # Things related to the prefilter #------------------------------------------------------------------------- @@ -2347,8 +2347,8 @@ class InteractiveShell(SingletonConfigurable): if not self.show_rewritten_input: return - # This is overridden in TerminalInteractiveShell to use fancy prompts - print("------> " + cmd) + # This is overridden in TerminalInteractiveShell to use fancy prompts + print("------> " + cmd) #------------------------------------------------------------------------- # Things related to extracting values/expressions from kernel and user_ns @@ -2356,13 +2356,13 @@ class InteractiveShell(SingletonConfigurable): def _user_obj_error(self): """return simple exception dict - + for use in user_expressions """ - + etype, evalue, tb = self._get_exc_info() stb = self.InteractiveTB.get_exception_only(etype, evalue) - + exc_info = { u'status' : 'error', u'traceback' : stb, @@ -2371,13 +2371,13 @@ class InteractiveShell(SingletonConfigurable): } return exc_info - + def _format_user_obj(self, obj): """format a user object to display dict - + for use in user_expressions """ - + data, md = self.display_formatter.format(obj) value = { 'status' : 'ok', @@ -2385,7 +2385,7 @@ class InteractiveShell(SingletonConfigurable): 'metadata' : md, } return value - + def user_expressions(self, expressions): """Evaluate a dict of expressions in the user's namespace. @@ -2404,7 +2404,7 @@ class InteractiveShell(SingletonConfigurable): out = {} user_ns = self.user_ns global_ns = self.user_global_ns - + for key, expr in iteritems(expressions): try: value = self._format_user_obj(eval(expr, global_ns, user_ns)) @@ -2475,7 +2475,7 @@ class InteractiveShell(SingletonConfigurable): # Python inserts the script's directory into sys.path dname = os.path.dirname(fname) - with prepended_to_syspath(dname), self.builtin_trap: + with prepended_to_syspath(dname), self.builtin_trap: try: glob, loc = (where + (None, ))[:2] py3compat.execfile( @@ -2532,7 +2532,7 @@ class InteractiveShell(SingletonConfigurable): # behavior of running a script from the system command line, where # Python inserts the script's directory into sys.path dname = os.path.dirname(fname) - + def get_cells(): """generator for sequence of code blocks to run""" if fname.endswith('.ipynb'): @@ -2616,9 +2616,9 @@ class InteractiveShell(SingletonConfigurable): result = ExecutionResult() if (not raw_cell) or raw_cell.isspace(): - self.last_execution_succeeded = True + self.last_execution_succeeded = True return result - + if silent: store_history = False @@ -2629,7 +2629,7 @@ class InteractiveShell(SingletonConfigurable): if store_history: self.execution_count += 1 result.error_before_exec = value - self.last_execution_succeeded = False + self.last_execution_succeeded = False return result self.events.trigger('pre_execute') @@ -2685,10 +2685,10 @@ class InteractiveShell(SingletonConfigurable): # Compile to bytecode try: code_ast = compiler.ast_parse(cell, filename=cell_name) - except self.custom_exceptions as e: - etype, value, tb = sys.exc_info() - self.CustomTB(etype, value, tb) - return error_before_exec(e) + except self.custom_exceptions as e: + etype, value, tb = sys.exc_info() + self.CustomTB(etype, value, tb) + return error_before_exec(e) except IndentationError as e: self.showindentationerror() return error_before_exec(e) @@ -2710,10 +2710,10 @@ class InteractiveShell(SingletonConfigurable): # Execute the user code interactivity = "none" if silent else self.ast_node_interactivity - has_raised = self.run_ast_nodes(code_ast.body, cell_name, + has_raised = self.run_ast_nodes(code_ast.body, cell_name, interactivity=interactivity, compiler=compiler, result=result) - - self.last_execution_succeeded = not has_raised + + self.last_execution_succeeded = not has_raised # Reset this so later displayed values do not modify the # ExecutionResult @@ -2731,16 +2731,16 @@ class InteractiveShell(SingletonConfigurable): self.execution_count += 1 return result - + def transform_ast(self, node): """Apply the AST transformations from self.ast_transformers - + Parameters ---------- node : ast.Node The root node to be transformed. Typically called with the ast.Module produced by parsing user input. - + Returns ------- An ast.Node corresponding to the node it was called with. Note that it @@ -2758,11 +2758,11 @@ class InteractiveShell(SingletonConfigurable): except Exception: warn("AST transformer %r threw an error. It will be unregistered." % transformer) self.ast_transformers.remove(transformer) - + if self.ast_transformers: ast.fix_missing_locations(node) return node - + def run_ast_nodes(self, nodelist, cell_name, interactivity='last_expr', compiler=compile, result=None): @@ -2883,7 +2883,7 @@ class InteractiveShell(SingletonConfigurable): if result is not None: result.error_in_exec = e self.showtraceback(exception_only=True) - warn("To exit: use 'exit', 'quit', or Ctrl-D.", stacklevel=1) + warn("To exit: use 'exit', 'quit', or Ctrl-D.", stacklevel=1) except self.custom_exceptions: etype, value, tb = sys.exc_info() if result is not None: @@ -2928,17 +2928,17 @@ class InteractiveShell(SingletonConfigurable): def enable_gui(self, gui=None): raise NotImplementedError('Implement enable_gui in a subclass') - + def enable_matplotlib(self, gui=None): """Enable interactive matplotlib and inline figure support. - + This takes the following steps: - + 1. select the appropriate eventloop and matplotlib backend 2. set up matplotlib for interactive use with that backend 3. configure formatters for inline figure display 4. enable the selected gui eventloop - + Parameters ---------- gui : optional, string @@ -2952,7 +2952,7 @@ class InteractiveShell(SingletonConfigurable): """ from IPython.core import pylabtools as pt gui, backend = pt.find_gui_and_backend(gui, self.pylab_gui_select) - + if gui != 'inline': # If we have our first gui selection, store it if self.pylab_gui_select is None: @@ -2962,16 +2962,16 @@ class InteractiveShell(SingletonConfigurable): print ('Warning: Cannot change to a different GUI toolkit: %s.' ' Using %s instead.' % (gui, self.pylab_gui_select)) gui, backend = pt.find_gui_and_backend(self.pylab_gui_select) - + pt.activate_matplotlib(backend) pt.configure_inline_support(self, backend) - + # Now we must activate the gui pylab wants to use, and fix %run to take # plot updates into account self.enable_gui(gui) self.magics_manager.registry['ExecutionMagics'].default_runner = \ pt.mpl_runner(self.safe_execfile) - + return gui, backend def enable_pylab(self, gui=None, import_all=True, welcome_message=False): @@ -2981,7 +2981,7 @@ class InteractiveShell(SingletonConfigurable): namespace all of numpy and pylab, and configures IPython to correctly interact with the GUI event loop. The GUI backend to be used can be optionally selected with the optional ``gui`` argument. - + This method only adds preloading the namespace to InteractiveShell.enable_matplotlib. Parameters @@ -3001,9 +3001,9 @@ class InteractiveShell(SingletonConfigurable): This argument is ignored, no welcome message will be displayed. """ from IPython.core.pylabtools import import_pylab - + gui, backend = self.enable_matplotlib(gui) - + # We want to prevent the loading of pylab to pollute the user's # namespace as shown by the %who* magics, so we execute the activation # code in an empty namespace, and we update *both* user_ns and @@ -3076,19 +3076,19 @@ class InteractiveShell(SingletonConfigurable): tmp_file.close() return filename - @undoc + @undoc def write(self,data): - """DEPRECATED: Write a string to the default output""" - warn('InteractiveShell.write() is deprecated, use sys.stdout instead', - DeprecationWarning, stacklevel=2) - sys.stdout.write(data) + """DEPRECATED: Write a string to the default output""" + warn('InteractiveShell.write() is deprecated, use sys.stdout instead', + DeprecationWarning, stacklevel=2) + sys.stdout.write(data) - @undoc + @undoc def write_err(self,data): - """DEPRECATED: Write a string to the default error output""" - warn('InteractiveShell.write_err() is deprecated, use sys.stderr instead', - DeprecationWarning, stacklevel=2) - sys.stderr.write(data) + """DEPRECATED: Write a string to the default error output""" + warn('InteractiveShell.write_err() is deprecated, use sys.stderr instead', + DeprecationWarning, stacklevel=2) + sys.stderr.write(data) def ask_yes_no(self, prompt, default=None, interrupt=None): if self.quiet: @@ -3160,8 +3160,8 @@ class InteractiveShell(SingletonConfigurable): if code: return code try: - if target.startswith(('http://', 'https://')): - return openpy.read_py_url(target, skip_encoding_cookie=skip_encoding_cookie) + if target.startswith(('http://', 'https://')): + return openpy.read_py_url(target, skip_encoding_cookie=skip_encoding_cookie) except UnicodeDecodeError: if not py_only : # Deferred import @@ -3171,7 +3171,7 @@ class InteractiveShell(SingletonConfigurable): from urllib import urlopen response = urlopen(target) return response.read().decode('latin1') - raise ValueError(("'%s' seem to be unreadable.") % target) + raise ValueError(("'%s' seem to be unreadable.") % target) potential_target = [target] try : @@ -3253,11 +3253,11 @@ class InteractiveShell(SingletonConfigurable): self.restore_sys_module_state() - # Overridden in terminal subclass to change prompts - def switch_doctest_mode(self, mode): - pass - - + # Overridden in terminal subclass to change prompts + def switch_doctest_mode(self, mode): + pass + + class InteractiveShellABC(with_metaclass(abc.ABCMeta, object)): """An abstract base class for InteractiveShell.""" diff --git a/contrib/python/ipython/py2/IPython/core/magic.py b/contrib/python/ipython/py2/IPython/core/magic.py index 61a929fd23..f3a0b5be33 100644 --- a/contrib/python/ipython/py2/IPython/core/magic.py +++ b/contrib/python/ipython/py2/IPython/core/magic.py @@ -27,8 +27,8 @@ from IPython.utils.ipstruct import Struct from IPython.utils.process import arg_split from IPython.utils.py3compat import string_types, iteritems from IPython.utils.text import dedent -from traitlets import Bool, Dict, Instance, observe -from logging import error +from traitlets import Bool, Dict, Instance, observe +from logging import error #----------------------------------------------------------------------------- # Globals @@ -298,12 +298,12 @@ class MagicsManager(Configurable): shell = Instance('IPython.core.interactiveshell.InteractiveShellABC', allow_none=True) - auto_magic = Bool(True, help= - "Automatically call line magics without requiring explicit % prefix" - ).tag(config=True) - @observe('auto_magic') - def _auto_magic_changed(self, change): - self.shell.automagic = change['new'] + auto_magic = Bool(True, help= + "Automatically call line magics without requiring explicit % prefix" + ).tag(config=True) + @observe('auto_magic') + def _auto_magic_changed(self, change): + self.shell.automagic = change['new'] _auto_status = [ 'Automagic is OFF, % prefix IS needed for line magics.', diff --git a/contrib/python/ipython/py2/IPython/core/magics/auto.py b/contrib/python/ipython/py2/IPython/core/magics/auto.py index f87bafdeb1..dc229d509b 100644 --- a/contrib/python/ipython/py2/IPython/core/magics/auto.py +++ b/contrib/python/ipython/py2/IPython/core/magics/auto.py @@ -1,7 +1,7 @@ """Implementation of magic functions that control various automatic behaviors. """ from __future__ import print_function -from __future__ import absolute_import +from __future__ import absolute_import #----------------------------------------------------------------------------- # Copyright (c) 2012 The IPython Development Team. # @@ -17,7 +17,7 @@ from __future__ import absolute_import # Our own packages from IPython.core.magic import Bunch, Magics, magics_class, line_magic from IPython.testing.skipdoctest import skip_doctest -from logging import error +from logging import error #----------------------------------------------------------------------------- # Magic implementation classes diff --git a/contrib/python/ipython/py2/IPython/core/magics/basic.py b/contrib/python/ipython/py2/IPython/core/magics/basic.py index ca69e2e698..529cdd2b65 100644 --- a/contrib/python/ipython/py2/IPython/core/magics/basic.py +++ b/contrib/python/ipython/py2/IPython/core/magics/basic.py @@ -1,7 +1,7 @@ """Implementation of basic magic functions.""" from __future__ import print_function -from __future__ import absolute_import +from __future__ import absolute_import import argparse import io @@ -15,8 +15,8 @@ from IPython.utils.text import format_screen, dedent, indent from IPython.testing.skipdoctest import skip_doctest from IPython.utils.ipstruct import Struct from IPython.utils.py3compat import unicode_type -from warnings import warn -from logging import error +from warnings import warn +from logging import error class MagicsDisplay(object): @@ -328,7 +328,7 @@ Currently the magic system has the following functions:""", """ def color_switch_err(name): warn('Error changing %s color schemes.\n%s' % - (name, sys.exc_info()[1]), stacklevel=2) + (name, sys.exc_info()[1]), stacklevel=2) new_scheme = parameter_s.strip() @@ -338,13 +338,13 @@ Currently the magic system has the following functions:""", # local shortcut shell = self.shell - # Set shell colour scheme + # Set shell colour scheme try: - shell.colors = new_scheme - shell.refresh_style() + shell.colors = new_scheme + shell.refresh_style() except: - color_switch_err('shell') - + color_switch_err('shell') + # Set exception colors try: shell.InteractiveTB.set_colors(scheme = new_scheme) @@ -458,12 +458,12 @@ Currently the magic system has the following functions:""", shell.magic('xmode ' + dstore.xmode) - # mode here is the state before we switch; switch_doctest_mode takes - # the mode we're switching to. - shell.switch_doctest_mode(not mode) - + # mode here is the state before we switch; switch_doctest_mode takes + # the mode we're switching to. + shell.switch_doctest_mode(not mode) + # Store new mode and inform - dstore.mode = bool(not mode) + dstore.mode = bool(not mode) mode_label = ['OFF','ON'][dstore.mode] print('Doctest mode is:', mode_label) diff --git a/contrib/python/ipython/py2/IPython/core/magics/code.py b/contrib/python/ipython/py2/IPython/core/magics/code.py index 4c1a40f197..c91d24c639 100644 --- a/contrib/python/ipython/py2/IPython/core/magics/code.py +++ b/contrib/python/ipython/py2/IPython/core/magics/code.py @@ -1,7 +1,7 @@ """Implementation of code management magic functions. """ from __future__ import print_function -from __future__ import absolute_import +from __future__ import absolute_import #----------------------------------------------------------------------------- # Copyright (c) 2012 The IPython Development Team. # @@ -32,9 +32,9 @@ from IPython.testing.skipdoctest import skip_doctest from IPython.utils import py3compat from IPython.utils.py3compat import string_types from IPython.utils.contexts import preserve_keys -from IPython.utils.path import get_py_filename -from warnings import warn -from logging import error +from IPython.utils.path import get_py_filename +from warnings import warn +from logging import error from IPython.utils.text import get_text_list #----------------------------------------------------------------------------- @@ -138,37 +138,37 @@ def extract_symbols(code, symbols): return blocks, not_found -def strip_initial_indent(lines): - """For %load, strip indent from lines until finding an unindented line. - - https://github.com/ipython/ipython/issues/9775 - """ - indent_re = re.compile(r'\s+') - - it = iter(lines) - first_line = next(it) - indent_match = indent_re.match(first_line) - - if indent_match: - # First line was indented - indent = indent_match.group() - yield first_line[len(indent):] - - for line in it: - if line.startswith(indent): - yield line[len(indent):] - else: - # Less indented than the first line - stop dedenting - yield line - break - else: - yield first_line - - # Pass the remaining lines through without dedenting - for line in it: - yield line - - +def strip_initial_indent(lines): + """For %load, strip indent from lines until finding an unindented line. + + https://github.com/ipython/ipython/issues/9775 + """ + indent_re = re.compile(r'\s+') + + it = iter(lines) + first_line = next(it) + indent_match = indent_re.match(first_line) + + if indent_match: + # First line was indented + indent = indent_match.group() + yield first_line[len(indent):] + + for line in it: + if line.startswith(indent): + yield line[len(indent):] + else: + # Less indented than the first line - stop dedenting + yield line + break + else: + yield first_line + + # Pass the remaining lines through without dedenting + for line in it: + yield line + + class InteractivelyDefined(Exception): """Exception for interactively defined variable in magic_edit""" def __init__(self, index): @@ -219,7 +219,7 @@ class CodeMagics(Magics): append = 'a' in opts mode = 'a' if append else 'w' ext = u'.ipy' if raw else u'.py' - fname, codefrom = args[0], " ".join(args[1:]) + fname, codefrom = args[0], " ".join(args[1:]) if not fname.endswith((u'.py',u'.ipy')): fname += ext file_exists = os.path.isfile(fname) @@ -371,7 +371,7 @@ class CodeMagics(Magics): lines = contents.split('\n') slices = extract_code_ranges(ranges) contents = [lines[slice(*slc)] for slc in slices] - contents = '\n'.join(strip_initial_indent(chain.from_iterable(contents))) + contents = '\n'.join(strip_initial_indent(chain.from_iterable(contents))) l = len(contents) diff --git a/contrib/python/ipython/py2/IPython/core/magics/config.py b/contrib/python/ipython/py2/IPython/core/magics/config.py index 9505697791..184388f064 100644 --- a/contrib/python/ipython/py2/IPython/core/magics/config.py +++ b/contrib/python/ipython/py2/IPython/core/magics/config.py @@ -1,7 +1,7 @@ """Implementation of configuration-related magic functions. """ from __future__ import print_function -from __future__ import absolute_import +from __future__ import absolute_import #----------------------------------------------------------------------------- # Copyright (c) 2012 The IPython Development Team. # @@ -20,7 +20,7 @@ import re # Our own packages from IPython.core.error import UsageError from IPython.core.magic import Magics, magics_class, line_magic -from logging import error +from logging import error #----------------------------------------------------------------------------- # Magic implementation classes diff --git a/contrib/python/ipython/py2/IPython/core/magics/display.py b/contrib/python/ipython/py2/IPython/core/magics/display.py index c4a8f44d9a..a0a74a62cc 100644 --- a/contrib/python/ipython/py2/IPython/core/magics/display.py +++ b/contrib/python/ipython/py2/IPython/core/magics/display.py @@ -25,32 +25,32 @@ from IPython.core.magic import ( @magics_class class DisplayMagics(Magics): """Magics for displaying various output types with literals - - Defines javascript/latex/svg/html cell magics for writing + + Defines javascript/latex/svg/html cell magics for writing blocks in those languages, to be rendered in the frontend. """ - - @cell_magic - def js(self, line, cell): - """Run the cell block of Javascript code - - Alias of `%%javascript` - """ - self.javascript(line, cell) - + @cell_magic + def js(self, line, cell): + """Run the cell block of Javascript code + + Alias of `%%javascript` + """ + self.javascript(line, cell) + + @cell_magic def javascript(self, line, cell): """Run the cell block of Javascript code""" display(Javascript(cell)) - - + + @cell_magic def latex(self, line, cell): """Render the cell as a block of latex - + The subset of latex which is support depends on the implementation in - the client. In the Jupyter Notebook, this magic only renders the subset - of latex defined by MathJax + the client. In the Jupyter Notebook, this magic only renders the subset + of latex defined by MathJax [here](https://docs.mathjax.org/en/v2.5-latest/tex.html).""" display(Latex(cell)) diff --git a/contrib/python/ipython/py2/IPython/core/magics/execution.py b/contrib/python/ipython/py2/IPython/core/magics/execution.py index 3734b0cdae..2597cab3fc 100644 --- a/contrib/python/ipython/py2/IPython/core/magics/execution.py +++ b/contrib/python/ipython/py2/IPython/core/magics/execution.py @@ -5,7 +5,7 @@ # Distributed under the terms of the Modified BSD License. from __future__ import print_function -from __future__ import absolute_import +from __future__ import absolute_import import ast import bdb @@ -28,7 +28,7 @@ except ImportError: except ImportError: profile = pstats = None -from IPython.core import oinspect +from IPython.core import oinspect from IPython.core import magic_arguments from IPython.core import page from IPython.core.error import UsageError @@ -42,10 +42,10 @@ from IPython.utils.contexts import preserve_keys from IPython.utils.capture import capture_output from IPython.utils.ipstruct import Struct from IPython.utils.module_paths import find_mod -from IPython.utils.path import get_py_filename, shellglob +from IPython.utils.path import get_py_filename, shellglob from IPython.utils.timing import clock, clock2 -from warnings import warn -from logging import error +from warnings import warn +from logging import error if PY3: from io import StringIO @@ -61,12 +61,12 @@ class TimeitResult(object): """ Object returned by the timeit magic with info about the run. - Contains the following attributes : + Contains the following attributes : - loops: (int) number of loops done per measurement - repeat: (int) number of times the measurement has been repeated - best: (float) best execution time / number - all_runs: (list of float) execution time of each run (in s) + loops: (int) number of loops done per measurement + repeat: (int) number of times the measurement has been repeated + best: (float) best execution time / number + all_runs: (list of float) execution time of each run (in s) compile_time: (float) time of statement compilation (s) """ @@ -705,54 +705,54 @@ python-profiler package from non-free.""") try: stats = None - if 'p' in opts: - stats = self._run_with_profiler(code, opts, code_ns) - else: - if 'd' in opts: - bp_file, bp_line = parse_breakpoint( - opts.get('b', ['1'])[0], filename) - self._run_with_debugger( - code, code_ns, filename, bp_line, bp_file) + if 'p' in opts: + stats = self._run_with_profiler(code, opts, code_ns) + else: + if 'd' in opts: + bp_file, bp_line = parse_breakpoint( + opts.get('b', ['1'])[0], filename) + self._run_with_debugger( + code, code_ns, filename, bp_line, bp_file) else: - if 'm' in opts: - def run(): - self.shell.safe_run_module(modulename, prog_ns) + if 'm' in opts: + def run(): + self.shell.safe_run_module(modulename, prog_ns) else: - if runner is None: - runner = self.default_runner - if runner is None: - runner = self.shell.safe_execfile - - def run(): - runner(filename, prog_ns, prog_ns, - exit_ignore=exit_ignore) - - if 't' in opts: - # timed execution - try: - nruns = int(opts['N'][0]) - if nruns < 1: - error('Number of runs must be >=1') - return - except (KeyError): - nruns = 1 - self._run_with_timing(run, nruns) - else: - # regular execution - run() - - if 'i' in opts: - self.shell.user_ns['__name__'] = __name__save - else: - # update IPython interactive namespace - - # Some forms of read errors on the file may mean the - # __name__ key was never set; using pop we don't have to - # worry about a possible KeyError. - prog_ns.pop('__name__', None) - - with preserve_keys(self.shell.user_ns, '__file__'): - self.shell.user_ns.update(prog_ns) + if runner is None: + runner = self.default_runner + if runner is None: + runner = self.shell.safe_execfile + + def run(): + runner(filename, prog_ns, prog_ns, + exit_ignore=exit_ignore) + + if 't' in opts: + # timed execution + try: + nruns = int(opts['N'][0]) + if nruns < 1: + error('Number of runs must be >=1') + return + except (KeyError): + nruns = 1 + self._run_with_timing(run, nruns) + else: + # regular execution + run() + + if 'i' in opts: + self.shell.user_ns['__name__'] = __name__save + else: + # update IPython interactive namespace + + # Some forms of read errors on the file may mean the + # __name__ key was never set; using pop we don't have to + # worry about a possible KeyError. + prog_ns.pop('__name__', None) + + with preserve_keys(self.shell.user_ns, '__file__'): + self.shell.user_ns.update(prog_ns) finally: # It's a bit of a mystery why, but __builtins__ can change from # being a module to becoming a dict missing some key data after @@ -801,11 +801,11 @@ python-profiler package from non-free.""") If the break point given by `bp_line` is not valid. """ - deb = self.shell.InteractiveTB.pdb - if not deb: - self.shell.InteractiveTB.pdb = self.shell.InteractiveTB.debugger_cls() - deb = self.shell.InteractiveTB.pdb - + deb = self.shell.InteractiveTB.pdb + if not deb: + self.shell.InteractiveTB.pdb = self.shell.InteractiveTB.debugger_cls() + deb = self.shell.InteractiveTB.pdb + # deb.checkline() fails if deb.curframe exists but is None; it can # handle it not existing. https://github.com/ipython/ipython/issues/10028 if hasattr(deb, 'curframe'): diff --git a/contrib/python/ipython/py2/IPython/core/magics/history.py b/contrib/python/ipython/py2/IPython/core/magics/history.py index 5967591394..d24bfd2a4e 100644 --- a/contrib/python/ipython/py2/IPython/core/magics/history.py +++ b/contrib/python/ipython/py2/IPython/core/magics/history.py @@ -15,7 +15,7 @@ from __future__ import print_function # Stdlib import os -import sys +import sys from io import open as io_open # Our own packages @@ -148,7 +148,7 @@ class HistoryMagics(Magics): # Check if output to specific file was requested. outfname = args.filename if not outfname: - outfile = sys.stdout # default + outfile = sys.stdout # default # We don't want to close stdout at the end! close_at_end = False else: diff --git a/contrib/python/ipython/py2/IPython/core/magics/logging.py b/contrib/python/ipython/py2/IPython/core/magics/logging.py index 90214ab54a..22500f8156 100644 --- a/contrib/python/ipython/py2/IPython/core/magics/logging.py +++ b/contrib/python/ipython/py2/IPython/core/magics/logging.py @@ -18,7 +18,7 @@ import sys # Our own packages from IPython.core.magic import Magics, magics_class, line_magic -from warnings import warn +from warnings import warn from IPython.utils.py3compat import str_to_unicode #----------------------------------------------------------------------------- diff --git a/contrib/python/ipython/py2/IPython/core/magics/osm.py b/contrib/python/ipython/py2/IPython/core/magics/osm.py index 352cf2d451..f48259ee02 100644 --- a/contrib/python/ipython/py2/IPython/core/magics/osm.py +++ b/contrib/python/ipython/py2/IPython/core/magics/osm.py @@ -323,7 +323,7 @@ class OSMagics(Magics): else: - opts, ps = self.parse_options(parameter_s, 'qb', mode='string') + opts, ps = self.parse_options(parameter_s, 'qb', mode='string') # jump to previous if ps == '-': try: @@ -437,7 +437,7 @@ class OSMagics(Magics): """ dir_s = self.shell.dir_stack - tgt = os.path.expanduser(parameter_s) + tgt = os.path.expanduser(parameter_s) cwd = py3compat.getcwd().replace(self.shell.home_dir,'~') if tgt: self.cd(parameter_s) @@ -775,8 +775,8 @@ class OSMagics(Magics): The file will be overwritten unless the -a (--append) flag is specified. """ args = magic_arguments.parse_argstring(self.writefile, line) - filename = os.path.expanduser(args.filename) - + filename = os.path.expanduser(args.filename) + if os.path.exists(filename): if args.append: print("Appending to %s" % filename) diff --git a/contrib/python/ipython/py2/IPython/core/magics/pylab.py b/contrib/python/ipython/py2/IPython/core/magics/pylab.py index 6c5cd68a59..62308d5e49 100644 --- a/contrib/python/ipython/py2/IPython/core/magics/pylab.py +++ b/contrib/python/ipython/py2/IPython/core/magics/pylab.py @@ -18,7 +18,7 @@ from traitlets.config.application import Application from IPython.core import magic_arguments from IPython.core.magic import Magics, magics_class, line_magic from IPython.testing.skipdoctest import skip_doctest -from warnings import warn +from warnings import warn from IPython.core.pylabtools import backends #----------------------------------------------------------------------------- diff --git a/contrib/python/ipython/py2/IPython/core/magics/script.py b/contrib/python/ipython/py2/IPython/core/magics/script.py index 3fbddc38a8..bfcad64919 100644 --- a/contrib/python/ipython/py2/IPython/core/magics/script.py +++ b/contrib/python/ipython/py2/IPython/core/magics/script.py @@ -1,8 +1,8 @@ """Magic functions for running cells in various scripts.""" from __future__ import print_function -# Copyright (c) IPython Development Team. -# Distributed under the terms of the Modified BSD License. +# Copyright (c) IPython Development Team. +# Distributed under the terms of the Modified BSD License. import errno import os @@ -19,7 +19,7 @@ from IPython.core.magic import ( from IPython.lib.backgroundjobs import BackgroundJobManager from IPython.utils import py3compat from IPython.utils.process import arg_split -from traitlets import List, Dict, default +from traitlets import List, Dict, default #----------------------------------------------------------------------------- # Magic implementation classes @@ -68,7 +68,7 @@ class ScriptMagics(Magics): with a program in a subprocess, and registers a few top-level magics that call %%script with common interpreters. """ - script_magics = List( + script_magics = List( help="""Extra script cell magics to define This generates simple wrappers of `%%script foo` as `%%foo`. @@ -76,8 +76,8 @@ class ScriptMagics(Magics): If you want to add script magics that aren't on your path, specify them in script_paths """, - ).tag(config=True) - @default('script_magics') + ).tag(config=True) + @default('script_magics') def _script_magics_default(self): """default to a common list of programs""" @@ -98,13 +98,13 @@ class ScriptMagics(Magics): return defaults - script_paths = Dict( + script_paths = Dict( help="""Dict mapping short 'ruby' names to full paths, such as '/opt/secret/bin/ruby' Only necessary for items in script_magics where the default path will not find the right interpreter. """ - ).tag(config=True) + ).tag(config=True) def __init__(self, shell=None): super(ScriptMagics, self).__init__(shell=shell) diff --git a/contrib/python/ipython/py2/IPython/core/oinspect.py b/contrib/python/ipython/py2/IPython/core/oinspect.py index 55a4efe8c0..b11e24e435 100644 --- a/contrib/python/ipython/py2/IPython/core/oinspect.py +++ b/contrib/python/ipython/py2/IPython/core/oinspect.py @@ -17,7 +17,7 @@ __all__ = ['Inspector','InspectColors'] # stdlib modules import inspect import linecache -import warnings +import warnings import os from textwrap import dedent import types @@ -42,19 +42,19 @@ from IPython.utils.wildcard import list_namespace from IPython.utils.coloransi import TermColors, ColorScheme, ColorSchemeTable from IPython.utils.py3compat import cast_unicode, string_types, PY3 from IPython.utils.signatures import signature -from IPython.utils.colorable import Colorable +from IPython.utils.colorable import Colorable -from pygments import highlight +from pygments import highlight try: # PythonLexer was renamed to Python2Lexer in pygments 2.5 from pygments.lexers import Python2Lexer except ImportError: from pygments.lexers import PythonLexer as Python2Lexer -from pygments.formatters import HtmlFormatter - -def pylight(code): +from pygments.formatters import HtmlFormatter + +def pylight(code): return highlight(code, Python2Lexer(), HtmlFormatter(noclasses=True)) - + # builtin docstrings to ignore _func_call_docstring = types.FunctionType.__call__.__doc__ _object_init_docstring = object.__init__.__doc__ @@ -124,8 +124,8 @@ def getdoc(obj): It also attempts to call a getdoc() method on the given object. This allows objects which provide their docstrings via non-standard mechanisms - (like Pyro proxies) to still be inspected by ipython's ? system. - """ + (like Pyro proxies) to still be inspected by ipython's ? system. + """ # Allow objects to offer customized documentation via a getdoc method: try: ds = obj.getdoc() @@ -141,7 +141,7 @@ def getdoc(obj): return py3compat.cast_unicode(docstr, encoding=encoding) except Exception: # Harden against an inspect failure, which can occur with - # extensions modules. + # extensions modules. raise return None @@ -376,16 +376,16 @@ def find_source_lines(obj): return lineno -class Inspector(Colorable): +class Inspector(Colorable): def __init__(self, color_table=InspectColors, code_color_table=PyColorize.ANSICodeColors, scheme='NoColor', - str_detail_level=0, - parent=None, config=None): - super(Inspector, self).__init__(parent=parent, config=config) + str_detail_level=0, + parent=None, config=None): + super(Inspector, self).__init__(parent=parent, config=config) self.color_table = color_table - self.parser = PyColorize.Parser(out='str', parent=self, style=scheme) + self.parser = PyColorize.Parser(out='str', parent=self, style=scheme) self.format = self.parser.format self.str_detail_level = str_detail_level self.set_active_scheme(scheme) @@ -438,11 +438,11 @@ class Inspector(Colorable): if output is None: self.noinfo('definition header',oname) else: - print(header,self.format(output), end=' ') + print(header,self.format(output), end=' ') # In Python 3, all classes are new-style, so they all have __init__. @skip_doctest_py3 - def pdoc(self, obj, oname='', formatter=None): + def pdoc(self, obj, oname='', formatter=None): """Print the docstring for any object. Optional: @@ -480,7 +480,7 @@ class Inspector(Colorable): lines = [] ds = getdoc(obj) if formatter: - ds = formatter(ds).get('plain/text', ds) + ds = formatter(ds).get('plain/text', ds) if ds: lines.append(head("Class docstring:")) lines.append(indent(ds)) @@ -517,7 +517,7 @@ class Inspector(Colorable): def pfile(self, obj, oname=''): """Show the whole file where an object was defined.""" - + lineno = find_source_lines(obj) if lineno is None: self.noinfo('file', oname) @@ -553,184 +553,184 @@ class Inspector(Colorable): title_width = max(len(title) + 2 for title, _ in fields) for title, content in fields: if len(content.splitlines()) > 1: - title = header(title + ':') + '\n' + title = header(title + ':') + '\n' else: - title = header((title + ':').ljust(title_width)) + title = header((title + ':').ljust(title_width)) out.append(cast_unicode(title) + cast_unicode(content)) return "\n".join(out) - def _mime_format(self, text, formatter=None): - """Return a mime bundle representation of the input text. - - - if `formatter` is None, the returned mime bundle has - a `text/plain` field, with the input text. - a `text/html` field with a `<pre>` tag containing the input text. - - - if `formatter` is not None, it must be a callable transforming the - input text into a mime bundle. Default values for `text/plain` and - `text/html` representations are the ones described above. - - Note: - - Formatters returning strings are supported but this behavior is deprecated. - - """ - text = cast_unicode(text) - defaults = { - 'text/plain': text, - 'text/html': '<pre>' + text + '</pre>' - } - - if formatter is None: - return defaults - else: - formatted = formatter(text) - - if not isinstance(formatted, dict): - # Handle the deprecated behavior of a formatter returning - # a string instead of a mime bundle. - return { - 'text/plain': formatted, - 'text/html': '<pre>' + formatted + '</pre>' - } - - else: - return dict(defaults, **formatted) - - - def format_mime(self, bundle): - - text_plain = bundle['text/plain'] - - text = '' - heads, bodies = list(zip(*text_plain)) - _len = max(len(h) for h in heads) - - for head, body in zip(heads, bodies): - body = body.strip('\n') - delim = '\n' if '\n' in body else ' ' - text += self.__head(head+':') + (_len - len(head))*' ' +delim + body +'\n' - - bundle['text/plain'] = text - return bundle - - def _get_info(self, obj, oname='', formatter=None, info=None, detail_level=0): - """Retrieve an info dict and format it.""" - - info = self._info(obj, oname=oname, info=info, detail_level=detail_level) - - _mime = { - 'text/plain': [], - 'text/html': '', - } - - def append_field(bundle, title, key, formatter=None): - field = info[key] - if field is not None: - formatted_field = self._mime_format(field, formatter) - bundle['text/plain'].append((title, formatted_field['text/plain'])) - bundle['text/html'] += '<h1>' + title + '</h1>\n' + formatted_field['text/html'] + '\n' - - def code_formatter(text): - return { - 'text/plain': self.format(text), - 'text/html': pylight(text) - } - + def _mime_format(self, text, formatter=None): + """Return a mime bundle representation of the input text. + + - if `formatter` is None, the returned mime bundle has + a `text/plain` field, with the input text. + a `text/html` field with a `<pre>` tag containing the input text. + + - if `formatter` is not None, it must be a callable transforming the + input text into a mime bundle. Default values for `text/plain` and + `text/html` representations are the ones described above. + + Note: + + Formatters returning strings are supported but this behavior is deprecated. + + """ + text = cast_unicode(text) + defaults = { + 'text/plain': text, + 'text/html': '<pre>' + text + '</pre>' + } + + if formatter is None: + return defaults + else: + formatted = formatter(text) + + if not isinstance(formatted, dict): + # Handle the deprecated behavior of a formatter returning + # a string instead of a mime bundle. + return { + 'text/plain': formatted, + 'text/html': '<pre>' + formatted + '</pre>' + } + + else: + return dict(defaults, **formatted) + + + def format_mime(self, bundle): + + text_plain = bundle['text/plain'] + + text = '' + heads, bodies = list(zip(*text_plain)) + _len = max(len(h) for h in heads) + + for head, body in zip(heads, bodies): + body = body.strip('\n') + delim = '\n' if '\n' in body else ' ' + text += self.__head(head+':') + (_len - len(head))*' ' +delim + body +'\n' + + bundle['text/plain'] = text + return bundle + + def _get_info(self, obj, oname='', formatter=None, info=None, detail_level=0): + """Retrieve an info dict and format it.""" + + info = self._info(obj, oname=oname, info=info, detail_level=detail_level) + + _mime = { + 'text/plain': [], + 'text/html': '', + } + + def append_field(bundle, title, key, formatter=None): + field = info[key] + if field is not None: + formatted_field = self._mime_format(field, formatter) + bundle['text/plain'].append((title, formatted_field['text/plain'])) + bundle['text/html'] += '<h1>' + title + '</h1>\n' + formatted_field['text/html'] + '\n' + + def code_formatter(text): + return { + 'text/plain': self.format(text), + 'text/html': pylight(text) + } + if info['isalias']: - append_field(_mime, 'Repr', 'string_form') + append_field(_mime, 'Repr', 'string_form') elif info['ismagic']: - if detail_level > 0: - append_field(_mime, 'Source', 'source', code_formatter) + if detail_level > 0: + append_field(_mime, 'Source', 'source', code_formatter) else: - append_field(_mime, 'Docstring', 'docstring', formatter) - append_field(_mime, 'File', 'file') + append_field(_mime, 'Docstring', 'docstring', formatter) + append_field(_mime, 'File', 'file') elif info['isclass'] or is_simple_callable(obj): # Functions, methods, classes - append_field(_mime, 'Signature', 'definition', code_formatter) - append_field(_mime, 'Init signature', 'init_definition', code_formatter) + append_field(_mime, 'Signature', 'definition', code_formatter) + append_field(_mime, 'Init signature', 'init_definition', code_formatter) if detail_level > 0 and info['source']: - append_field(_mime, 'Source', 'source', code_formatter) + append_field(_mime, 'Source', 'source', code_formatter) else: - append_field(_mime, 'Docstring', 'docstring', formatter) - append_field(_mime, 'Init docstring', 'init_docstring', formatter) + append_field(_mime, 'Docstring', 'docstring', formatter) + append_field(_mime, 'Init docstring', 'init_docstring', formatter) - append_field(_mime, 'File', 'file') - append_field(_mime, 'Type', 'type_name') + append_field(_mime, 'File', 'file') + append_field(_mime, 'Type', 'type_name') else: # General Python objects append_field(_mime, 'Signature', 'definition', code_formatter) append_field(_mime, 'Call signature', 'call_def', code_formatter) - append_field(_mime, 'Type', 'type_name') + append_field(_mime, 'Type', 'type_name') # Base class for old-style instances if (not py3compat.PY3) and isinstance(obj, types.InstanceType) and info['base_class']: - append_field(_mime, 'Base Class', 'base_class') + append_field(_mime, 'Base Class', 'base_class') - append_field(_mime, 'String form', 'string_form') + append_field(_mime, 'String form', 'string_form') # Namespace if info['namespace'] != 'Interactive': - append_field(_mime, 'Namespace', 'namespace') + append_field(_mime, 'Namespace', 'namespace') - append_field(_mime, 'Length', 'length') + append_field(_mime, 'Length', 'length') append_field(_mime, 'File', 'file') # Source or docstring, depending on detail level and whether # source found. - if detail_level > 0: - append_field(_mime, 'Source', 'source', code_formatter) - else: - append_field(_mime, 'Docstring', 'docstring', formatter) - - append_field(_mime, 'Class docstring', 'class_docstring', formatter) - append_field(_mime, 'Init docstring', 'init_docstring', formatter) - append_field(_mime, 'Call docstring', 'call_docstring', formatter) + if detail_level > 0: + append_field(_mime, 'Source', 'source', code_formatter) + else: + append_field(_mime, 'Docstring', 'docstring', formatter) + + append_field(_mime, 'Class docstring', 'class_docstring', formatter) + append_field(_mime, 'Init docstring', 'init_docstring', formatter) + append_field(_mime, 'Call docstring', 'call_docstring', formatter) - - return self.format_mime(_mime) - - def pinfo(self, obj, oname='', formatter=None, info=None, detail_level=0, enable_html_pager=True): + + return self.format_mime(_mime) + + def pinfo(self, obj, oname='', formatter=None, info=None, detail_level=0, enable_html_pager=True): """Show detailed information about an object. Optional arguments: - oname: name of the variable pointing to the object. - - formatter: callable (optional) - A special formatter for docstrings. - - The formatter is a callable that takes a string as an input - and returns either a formatted string or a mime type bundle - in the form of a dictionnary. - - Although the support of custom formatter returning a string - instead of a mime type bundle is deprecated. + - formatter: callable (optional) + A special formatter for docstrings. + The formatter is a callable that takes a string as an input + and returns either a formatted string or a mime type bundle + in the form of a dictionnary. + + Although the support of custom formatter returning a string + instead of a mime type bundle is deprecated. + - info: a structure with some information fields which may have been precomputed already. - detail_level: if set to 1, more information is given. """ - info = self._get_info(obj, oname, formatter, info, detail_level) - if not enable_html_pager: - del info['text/html'] - page.page(info) - + info = self._get_info(obj, oname, formatter, info, detail_level) + if not enable_html_pager: + del info['text/html'] + page.page(info) + def info(self, obj, oname='', formatter=None, info=None, detail_level=0): - """DEPRECATED. Compute a dict with detailed information about an object. - """ - if formatter is not None: - warnings.warn('The `formatter` keyword argument to `Inspector.info`' - 'is deprecated as of IPython 5.0 and will have no effects.', - DeprecationWarning, stacklevel=2) - return self._info(obj, oname=oname, info=info, detail_level=detail_level) - - def _info(self, obj, oname='', info=None, detail_level=0): + """DEPRECATED. Compute a dict with detailed information about an object. + """ + if formatter is not None: + warnings.warn('The `formatter` keyword argument to `Inspector.info`' + 'is deprecated as of IPython 5.0 and will have no effects.', + DeprecationWarning, stacklevel=2) + return self._info(obj, oname=oname, info=info, detail_level=detail_level) + + def _info(self, obj, oname='', info=None, detail_level=0): """Compute a dict with detailed information about an object. Optional arguments: @@ -774,7 +774,7 @@ class Inspector(Colorable): out = dict(name=oname, found=True, isalias=isalias, ismagic=ismagic) string_max = 200 # max size of strings to show (snipped if longer) - shalf = int((string_max - 5) / 2) + shalf = int((string_max - 5) / 2) if ismagic: obj_type_name = 'Magic function' @@ -846,43 +846,43 @@ class Inspector(Colorable): # Constructor docstring for classes if inspect.isclass(obj): out['isclass'] = True - - # get the init signature: + + # get the init signature: try: - init_def = self._getdef(obj, oname) + init_def = self._getdef(obj, oname) except AttributeError: - init_def = None - - # get the __init__ docstring - try: - obj_init = obj.__init__ - except AttributeError: - init_ds = None + init_def = None + + # get the __init__ docstring + try: + obj_init = obj.__init__ + except AttributeError: + init_ds = None else: - if init_def is None: - # Get signature from init if top-level sig failed. - # Can happen for built-in types (list, etc.). - try: - init_def = self._getdef(obj_init, oname) - except AttributeError: - pass - init_ds = getdoc(obj_init) + if init_def is None: + # Get signature from init if top-level sig failed. + # Can happen for built-in types (list, etc.). + try: + init_def = self._getdef(obj_init, oname) + except AttributeError: + pass + init_ds = getdoc(obj_init) # Skip Python's auto-generated docstrings if init_ds == _object_init_docstring: init_ds = None - if init_def: - out['init_definition'] = init_def - - if init_ds: - out['init_docstring'] = init_ds + if init_def: + out['init_definition'] = init_def + if init_ds: + out['init_docstring'] = init_ds + # and class docstring for instances: else: # reconstruct the function definition and print it: defln = self._getdef(obj, oname) if defln: - out['definition'] = defln + out['definition'] = defln # First, check whether the instance docstring is identical to the # class one, and print it separately if they don't coincide. In @@ -915,10 +915,10 @@ class Inspector(Colorable): # Call form docstring for callable instances if safe_hasattr(obj, '__call__') and not is_simple_callable(obj): call_def = self._getdef(obj.__call__, oname) - if call_def and (call_def != out.get('definition')): + if call_def and (call_def != out.get('definition')): # it may never be the case that call def and definition differ, # but don't include the same signature twice - out['call_def'] = call_def + out['call_def'] = call_def call_ds = getdoc(obj.__call__) # Skip Python's auto-generated docstrings if call_ds == _func_call_docstring: diff --git a/contrib/python/ipython/py2/IPython/core/page.py b/contrib/python/ipython/py2/IPython/core/page.py index 6d213c9f29..a9de4f4805 100644 --- a/contrib/python/ipython/py2/IPython/core/page.py +++ b/contrib/python/ipython/py2/IPython/core/page.py @@ -38,7 +38,7 @@ def display_page(strng, start=0, screen_lines=25): else: if start: strng = u'\n'.join(strng.splitlines()[start:]) - data = { 'text/plain': strng } + data = { 'text/plain': strng } display(data, raw=True) @@ -56,25 +56,25 @@ def page_dumb(strng, start=0, screen_lines=25): """Very dumb 'pager' in Python, for when nothing else works. Only moves forward, same interface as page(), except for pager_cmd and - mode. - """ - if isinstance(strng, dict): - strng = strng.get('text/plain', '') + mode. + """ + if isinstance(strng, dict): + strng = strng.get('text/plain', '') out_ln = strng.splitlines()[start:] screens = chop(out_ln,screen_lines-1) if len(screens) == 1: - print(os.linesep.join(screens[0])) + print(os.linesep.join(screens[0])) else: last_escape = "" for scr in screens[0:-1]: hunk = os.linesep.join(scr) - print(last_escape + hunk) + print(last_escape + hunk) if not page_more(): return esc_list = esc_re.findall(hunk) if len(esc_list) > 0: last_escape = esc_list[-1] - print(last_escape + os.linesep.join(screens[-1])) + print(last_escape + os.linesep.join(screens[-1])) def _detect_screen_size(screen_lines_def): """Attempt to work out the number of lines on the screen. @@ -192,13 +192,13 @@ def pager_page(strng, start=0, screen_lines=0, pager_cmd=None): try: screen_lines += _detect_screen_size(screen_lines_def) except (TypeError, UnsupportedOperation): - print(str_toprint) + print(str_toprint) return #print 'numlines',numlines,'screenlines',screen_lines # dbg if numlines <= screen_lines : #print '*** normal print' # dbg - print(str_toprint) + print(str_toprint) else: # Try to open pager and default to internal one if that fails. # All failure modes are tagged as 'retval=1', to match the return @@ -300,7 +300,7 @@ def get_pager_cmd(pager_cmd=None): Makes some attempts at finding an OS-correct one. """ if os.name == 'posix': - default_pager_cmd = 'less -R' # -R for color control sequences + default_pager_cmd = 'less -R' # -R for color control sequences elif os.name in ['nt','dos']: default_pager_cmd = 'type' @@ -309,10 +309,10 @@ def get_pager_cmd(pager_cmd=None): pager_cmd = os.environ['PAGER'] except: pager_cmd = default_pager_cmd - - if pager_cmd == 'less' and '-r' not in os.environ.get('LESS', '').lower(): - pager_cmd += ' -R' - + + if pager_cmd == 'less' and '-r' not in os.environ.get('LESS', '').lower(): + pager_cmd += ' -R' + return pager_cmd @@ -340,13 +340,13 @@ if os.name == 'nt' and os.environ.get('TERM','dumb') != 'emacs': @return: True if need print more lines, False if quit """ - sys.stdout.write('---Return to continue, q to quit--- ') + sys.stdout.write('---Return to continue, q to quit--- ') ans = msvcrt.getwch() if ans in ("q", "Q"): result = False else: result = True - sys.stdout.write("\b"*37 + " "*37 + "\b"*37) + sys.stdout.write("\b"*37 + " "*37 + "\b"*37) return result else: def page_more(): diff --git a/contrib/python/ipython/py2/IPython/core/prefilter.py b/contrib/python/ipython/py2/IPython/core/prefilter.py index cbed3fd80a..1f2367fe52 100644 --- a/contrib/python/ipython/py2/IPython/core/prefilter.py +++ b/contrib/python/ipython/py2/IPython/core/prefilter.py @@ -6,8 +6,8 @@ Prefilters transform user input before it is exec'd by Python. These transforms are used to implement additional syntax such as !ls and %magic. """ -# Copyright (c) IPython Development Team. -# Distributed under the terms of the Modified BSD License. +# Copyright (c) IPython Development Team. +# Distributed under the terms of the Modified BSD License. from keyword import iskeyword import re @@ -24,7 +24,7 @@ from IPython.core.macro import Macro from IPython.core.splitinput import LineInfo from traitlets import ( - List, Integer, Unicode, Bool, Instance, CRegExp + List, Integer, Unicode, Bool, Instance, CRegExp ) #----------------------------------------------------------------------------- @@ -114,7 +114,7 @@ class PrefilterManager(Configurable): or :meth:`sort_transformers` method after changing the priority. """ - multi_line_specials = Bool(True).tag(config=True) + multi_line_specials = Bool(True).tag(config=True) shell = Instance('IPython.core.interactiveshell.InteractiveShellABC', allow_none=True) def __init__(self, shell=None, **kwargs): @@ -344,12 +344,12 @@ class PrefilterManager(Configurable): class PrefilterTransformer(Configurable): """Transform a line of user input.""" - priority = Integer(100).tag(config=True) + priority = Integer(100).tag(config=True) # Transformers don't currently use shell or prefilter_manager, but as we # move away from checkers and handlers, they will need them. shell = Instance('IPython.core.interactiveshell.InteractiveShellABC', allow_none=True) prefilter_manager = Instance('IPython.core.prefilter.PrefilterManager', allow_none=True) - enabled = Bool(True).tag(config=True) + enabled = Bool(True).tag(config=True) def __init__(self, shell=None, prefilter_manager=None, **kwargs): super(PrefilterTransformer, self).__init__( @@ -374,10 +374,10 @@ class PrefilterTransformer(Configurable): class PrefilterChecker(Configurable): """Inspect an input line and return a handler for that line.""" - priority = Integer(100).tag(config=True) + priority = Integer(100).tag(config=True) shell = Instance('IPython.core.interactiveshell.InteractiveShellABC', allow_none=True) prefilter_manager = Instance('IPython.core.prefilter.PrefilterManager', allow_none=True) - enabled = Bool(True).tag(config=True) + enabled = Bool(True).tag(config=True) def __init__(self, shell=None, prefilter_manager=None, **kwargs): super(PrefilterChecker, self).__init__( @@ -396,8 +396,8 @@ class PrefilterChecker(Configurable): class EmacsChecker(PrefilterChecker): - priority = Integer(100).tag(config=True) - enabled = Bool(False).tag(config=True) + priority = Integer(100).tag(config=True) + enabled = Bool(False).tag(config=True) def check(self, line_info): "Emacs ipython-mode tags certain input lines." @@ -409,7 +409,7 @@ class EmacsChecker(PrefilterChecker): class MacroChecker(PrefilterChecker): - priority = Integer(250).tag(config=True) + priority = Integer(250).tag(config=True) def check(self, line_info): obj = self.shell.user_ns.get(line_info.ifun) @@ -421,7 +421,7 @@ class MacroChecker(PrefilterChecker): class IPyAutocallChecker(PrefilterChecker): - priority = Integer(300).tag(config=True) + priority = Integer(300).tag(config=True) def check(self, line_info): "Instances of IPyAutocall in user_ns get autocalled immediately" @@ -435,7 +435,7 @@ class IPyAutocallChecker(PrefilterChecker): class AssignmentChecker(PrefilterChecker): - priority = Integer(600).tag(config=True) + priority = Integer(600).tag(config=True) def check(self, line_info): """Check to see if user is assigning to a var for the first time, in @@ -453,7 +453,7 @@ class AssignmentChecker(PrefilterChecker): class AutoMagicChecker(PrefilterChecker): - priority = Integer(700).tag(config=True) + priority = Integer(700).tag(config=True) def check(self, line_info): """If the ifun is magic, and automagic is on, run it. Note: normal, @@ -477,7 +477,7 @@ class AutoMagicChecker(PrefilterChecker): class PythonOpsChecker(PrefilterChecker): - priority = Integer(900).tag(config=True) + priority = Integer(900).tag(config=True) def check(self, line_info): """If the 'rest' of the line begins with a function call or pretty much @@ -492,14 +492,14 @@ class PythonOpsChecker(PrefilterChecker): class AutocallChecker(PrefilterChecker): - priority = Integer(1000).tag(config=True) + priority = Integer(1000).tag(config=True) - function_name_regexp = CRegExp(re_fun_name, - help="RegExp to identify potential function names." - ).tag(config=True) - exclude_regexp = CRegExp(re_exclude_auto, - help="RegExp to exclude strings with this start from autocalling." - ).tag(config=True) + function_name_regexp = CRegExp(re_fun_name, + help="RegExp to identify potential function names." + ).tag(config=True) + exclude_regexp = CRegExp(re_exclude_auto, + help="RegExp to exclude strings with this start from autocalling." + ).tag(config=True) def check(self, line_info): "Check if the initial word/function is callable and autocall is on." diff --git a/contrib/python/ipython/py2/IPython/core/profileapp.py b/contrib/python/ipython/py2/IPython/core/profileapp.py index b8e5fd26ac..3f9ce97b8b 100644 --- a/contrib/python/ipython/py2/IPython/core/profileapp.py +++ b/contrib/python/ipython/py2/IPython/core/profileapp.py @@ -32,7 +32,7 @@ from IPython.core.profiledir import ProfileDir from IPython.utils.importstring import import_item from IPython.paths import get_ipython_dir, get_ipython_package_dir from IPython.utils import py3compat -from traitlets import Unicode, Bool, Dict, observe +from traitlets import Unicode, Bool, Dict, observe #----------------------------------------------------------------------------- # Constants @@ -149,14 +149,14 @@ class ProfileList(Application): ) )) - ipython_dir = Unicode(get_ipython_dir(), + ipython_dir = Unicode(get_ipython_dir(), help=""" The name of the IPython directory. This directory is used for logging configuration (through profiles), history storage, etc. The default is usually $HOME/.ipython. This options can also be specified through the environment variable IPYTHONDIR. """ - ).tag(config=True) + ).tag(config=True) def _print_profiles(self, profiles): @@ -211,24 +211,24 @@ class ProfileCreate(BaseIPythonApplication): name = u'ipython-profile' description = create_help examples = _create_examples - auto_create = Bool(True) + auto_create = Bool(True) def _log_format_default(self): return "[%(name)s] %(message)s" def _copy_config_files_default(self): return True - parallel = Bool(False, - help="whether to include parallel computing config files" - ).tag(config=True) - - @observe('parallel') - def _parallel_changed(self, change): + parallel = Bool(False, + help="whether to include parallel computing config files" + ).tag(config=True) + + @observe('parallel') + def _parallel_changed(self, change): parallel_files = [ 'ipcontroller_config.py', 'ipengine_config.py', 'ipcluster_config.py' ] - if change['new']: + if change['new']: for cf in parallel_files: self.config_files.append(cf) else: diff --git a/contrib/python/ipython/py2/IPython/core/profiledir.py b/contrib/python/ipython/py2/IPython/core/profiledir.py index b777f13da0..e0e754a78f 100644 --- a/contrib/python/ipython/py2/IPython/core/profiledir.py +++ b/contrib/python/ipython/py2/IPython/core/profiledir.py @@ -12,7 +12,7 @@ from traitlets.config.configurable import LoggingConfigurable from IPython.paths import get_ipython_package_dir from IPython.utils.path import expand_path, ensure_dir_exists from IPython.utils import py3compat -from traitlets import Unicode, Bool, observe +from traitlets import Unicode, Bool, observe #----------------------------------------------------------------------------- # Module errors @@ -47,18 +47,18 @@ class ProfileDir(LoggingConfigurable): pid_dir = Unicode(u'') static_dir = Unicode(u'') - location = Unicode(u'', + location = Unicode(u'', help="""Set the profile location directly. This overrides the logic used by the `profile` option.""", - ).tag(config=True) + ).tag(config=True) _location_isset = Bool(False) # flag for detecting multiply set location - @observe('location') - def _location_changed(self, change): + @observe('location') + def _location_changed(self, change): if self._location_isset: raise RuntimeError("Cannot set profile location more than once.") self._location_isset = True - new = change['new'] + new = change['new'] ensure_dir_exists(new) # ensure config files exist: @@ -68,7 +68,7 @@ class ProfileDir(LoggingConfigurable): self.pid_dir = os.path.join(new, self.pid_dir_name) self.static_dir = os.path.join(new, self.static_dir_name) self.check_dirs() - + def _mkdir(self, path, mode=None): """ensure a directory exists at a given path @@ -102,13 +102,13 @@ class ProfileDir(LoggingConfigurable): raise return True - - @observe('log_dir') - def check_log_dir(self, change=None): + + @observe('log_dir') + def check_log_dir(self, change=None): self._mkdir(self.log_dir) - - @observe('startup_dir') - def check_startup_dir(self, change=None): + + @observe('startup_dir') + def check_startup_dir(self, change=None): self._mkdir(self.startup_dir) readme = os.path.join(self.startup_dir, 'README') @@ -118,12 +118,12 @@ class ProfileDir(LoggingConfigurable): with open(readme, 'wb') as f: f.write(pkgutil.get_data(__name__, 'profile/README_STARTUP')) - @observe('security_dir') - def check_security_dir(self, change=None): + @observe('security_dir') + def check_security_dir(self, change=None): self._mkdir(self.security_dir, 0o40700) - @observe('pid_dir') - def check_pid_dir(self, change=None): + @observe('pid_dir') + def check_pid_dir(self, change=None): self._mkdir(self.pid_dir, 0o40700) def check_dirs(self): diff --git a/contrib/python/ipython/py2/IPython/core/prompts.py b/contrib/python/ipython/py2/IPython/core/prompts.py index 7802bc5363..cc6bcb721f 100644 --- a/contrib/python/ipython/py2/IPython/core/prompts.py +++ b/contrib/python/ipython/py2/IPython/core/prompts.py @@ -1,8 +1,8 @@ # -*- coding: utf-8 -*- -"""Being removed +"""Being removed """ -from IPython.utils import py3compat +from IPython.utils import py3compat class LazyEvaluate(object): """This is used for formatting strings with values that need to be updated diff --git a/contrib/python/ipython/py2/IPython/core/pylabtools.py b/contrib/python/ipython/py2/IPython/core/pylabtools.py index a1932d8c48..ace18b57e8 100644 --- a/contrib/python/ipython/py2/IPython/core/pylabtools.py +++ b/contrib/python/ipython/py2/IPython/core/pylabtools.py @@ -377,7 +377,7 @@ def configure_inline_support(shell, backend): from ipykernel.pylab.backend_inline import InlineBackend except ImportError: return - import matplotlib + import matplotlib cfg = InlineBackend.instance(parent=shell) cfg.shell = shell @@ -391,9 +391,9 @@ def configure_inline_support(shell, backend): # Save rcParams that will be overwrittern shell._saved_rcParams = dict() for k in cfg.rc: - shell._saved_rcParams[k] = matplotlib.rcParams[k] + shell._saved_rcParams[k] = matplotlib.rcParams[k] # load inline_rc - matplotlib.rcParams.update(cfg.rc) + matplotlib.rcParams.update(cfg.rc) new_backend_name = "inline" else: from ipykernel.pylab.backend_inline import flush_figures @@ -402,7 +402,7 @@ def configure_inline_support(shell, backend): except ValueError: pass if hasattr(shell, '_saved_rcParams'): - matplotlib.rcParams.update(shell._saved_rcParams) + matplotlib.rcParams.update(shell._saved_rcParams) del shell._saved_rcParams new_backend_name = "other" diff --git a/contrib/python/ipython/py2/IPython/core/release.py b/contrib/python/ipython/py2/IPython/core/release.py index 94dea1073b..127e59629f 100644 --- a/contrib/python/ipython/py2/IPython/core/release.py +++ b/contrib/python/ipython/py2/IPython/core/release.py @@ -19,11 +19,11 @@ name = 'ipython' # IPython version information. An empty _version_extra corresponds to a full # release. 'dev' as a _version_extra string means this is a development # version -_version_major = 5 +_version_major = 5 _version_minor = 9 -_version_patch = 0 +_version_patch = 0 _version_extra = '.dev' -# _version_extra = 'rc1' +# _version_extra = 'rc1' _version_extra = '' # Uncomment this for full releases # release.codename is deprecated in 2.0, will be removed in 3.0 diff --git a/contrib/python/ipython/py2/IPython/core/shellapp.py b/contrib/python/ipython/py2/IPython/core/shellapp.py index 213648246e..0684b41880 100644 --- a/contrib/python/ipython/py2/IPython/core/shellapp.py +++ b/contrib/python/ipython/py2/IPython/core/shellapp.py @@ -24,15 +24,15 @@ from IPython.utils import py3compat from IPython.utils.contexts import preserve_keys from IPython.utils.path import filefind from traitlets import ( - Unicode, Instance, List, Bool, CaselessStrEnum, observe, + Unicode, Instance, List, Bool, CaselessStrEnum, observe, ) -from IPython.terminal import pt_inputhooks +from IPython.terminal import pt_inputhooks #----------------------------------------------------------------------------- # Aliases and Flags #----------------------------------------------------------------------------- -gui_keys = tuple(sorted(pt_inputhooks.backends) + sorted(pt_inputhooks.aliases)) +gui_keys = tuple(sorted(pt_inputhooks.backends) + sorted(pt_inputhooks.aliases)) backend_keys = sorted(pylabtools.backends.keys()) backend_keys.insert(0, 'auto') @@ -102,7 +102,7 @@ shell_aliases['cache-size'] = 'InteractiveShell.cache_size' class InteractiveShellApp(Configurable): """A Mixin for applications that start InteractiveShell instances. - + Provides configurables for loading extensions and executing files as part of configuring a Shell environment. @@ -115,73 +115,73 @@ class InteractiveShellApp(Configurable): - :meth:`init_extensions` - :meth:`init_code` """ - extensions = List(Unicode(), + extensions = List(Unicode(), help="A list of dotted module names of IPython extensions to load." - ).tag(config=True) - extra_extension = Unicode('', + ).tag(config=True) + extra_extension = Unicode('', help="dotted module name of an IPython extension to load." - ).tag(config=True) + ).tag(config=True) - reraise_ipython_extension_failures = Bool(False, + reraise_ipython_extension_failures = Bool(False, help="Reraise exceptions encountered loading IPython extensions?", - ).tag(config=True) + ).tag(config=True) # Extensions that are always loaded (not configurable) - default_extensions = List(Unicode(), [u'storemagic']).tag(config=False) - - hide_initial_ns = Bool(True, + default_extensions = List(Unicode(), [u'storemagic']).tag(config=False) + + hide_initial_ns = Bool(True, help="""Should variables loaded at startup (by startup files, exec_lines, etc.) be hidden from tools like %who?""" - ).tag(config=True) + ).tag(config=True) - exec_files = List(Unicode(), + exec_files = List(Unicode(), help="""List of files to run at IPython startup.""" - ).tag(config=True) - exec_PYTHONSTARTUP = Bool(True, + ).tag(config=True) + exec_PYTHONSTARTUP = Bool(True, help="""Run the file referenced by the PYTHONSTARTUP environment variable at IPython startup.""" - ).tag(config=True) - file_to_run = Unicode('', - help="""A file to be run""").tag(config=True) + ).tag(config=True) + file_to_run = Unicode('', + help="""A file to be run""").tag(config=True) - exec_lines = List(Unicode(), + exec_lines = List(Unicode(), help="""lines of code to run at IPython startup.""" - ).tag(config=True) - code_to_run = Unicode('', + ).tag(config=True) + code_to_run = Unicode('', help="Execute the given command string." - ).tag(config=True) - module_to_run = Unicode('', + ).tag(config=True) + module_to_run = Unicode('', help="Run the module as a script." - ).tag(config=True) - gui = CaselessStrEnum(gui_keys, allow_none=True, + ).tag(config=True) + gui = CaselessStrEnum(gui_keys, allow_none=True, help="Enable GUI event loop integration with any of {0}.".format(gui_keys) - ).tag(config=True) + ).tag(config=True) matplotlib = CaselessStrEnum(backend_keys, allow_none=True, help="""Configure matplotlib for interactive use with the default matplotlib backend.""" - ).tag(config=True) + ).tag(config=True) pylab = CaselessStrEnum(backend_keys, allow_none=True, help="""Pre-load matplotlib and numpy for interactive use, selecting a particular matplotlib backend and loop integration. """ - ).tag(config=True) - pylab_import_all = Bool(True, + ).tag(config=True) + pylab_import_all = Bool(True, help="""If true, IPython will populate the user namespace with numpy, pylab, etc. and an ``import *`` is done from numpy and pylab, when using pylab mode. - + When False, pylab mode should not import any names into the user namespace. """ - ).tag(config=True) + ).tag(config=True) shell = Instance('IPython.core.interactiveshell.InteractiveShellABC', allow_none=True) - # whether interact-loop should start - interact = Bool(True) - + # whether interact-loop should start + interact = Bool(True) + user_ns = Instance(dict, args=None, allow_none=True) - @observe('user_ns') - def _user_ns_changed(self, change): + @observe('user_ns') + def _user_ns_changed(self, change): if self.shell is not None: - self.shell.user_ns = change['new'] + self.shell.user_ns = change['new'] self.shell.init_user_ns() def init_path(self): @@ -205,10 +205,10 @@ class InteractiveShellApp(Configurable): elif self.gui: enable = shell.enable_gui key = self.gui - + if not enable: return - + try: r = enable(key) except ImportError: @@ -219,7 +219,7 @@ class InteractiveShellApp(Configurable): self.log.warning("GUI event loop or pylab initialization failed") self.shell.showtraceback() return - + if isinstance(r, tuple): gui, backend = r[:2] self.log.info("Enabling GUI event loop integration, " @@ -265,16 +265,16 @@ class InteractiveShellApp(Configurable): self._run_startup_files() self._run_exec_lines() self._run_exec_files() - + # Hide variables defined here from %who etc. if self.hide_initial_ns: self.shell.user_ns_hidden.update(self.shell.user_ns) - + # command-line execution (ipython -i script.py, ipython -m module) # should *not* be excluded from %whos self._run_cmd_line_code() self._run_module() - + # flush output, so itwon't be attached to the first cell sys.stdout.flush() sys.stderr.flush() @@ -301,7 +301,7 @@ class InteractiveShellApp(Configurable): def _exec_file(self, fname, shell_futures=False): try: full_filename = filefind(fname, [u'.', self.ipython_dir]) - except IOError: + except IOError: self.log.warning("File not found: %r"%fname) return # Make sure that the running script gets a proper sys.argv as if it @@ -337,7 +337,7 @@ class InteractiveShellApp(Configurable): os.path.join(p, 'startup') for p in chain(ENV_CONFIG_DIRS, SYSTEM_CONFIG_DIRS) ] startup_files = [] - + if self.exec_PYTHONSTARTUP and os.environ.get('PYTHONSTARTUP', False) and \ not (self.file_to_run or self.code_to_run or self.module_to_run): python_startup = os.environ['PYTHONSTARTUP'] @@ -352,7 +352,7 @@ class InteractiveShellApp(Configurable): startup_files += glob.glob(os.path.join(startup_dir, '*.ipy')) if not startup_files: return - + self.log.debug("Running startup files from %s...", startup_dir) try: for fname in sorted(startup_files): @@ -386,20 +386,20 @@ class InteractiveShellApp(Configurable): self.log.warning("Error in executing line in user namespace: %s" % line) self.shell.showtraceback() - if not self.interact: - self.exit(1) + if not self.interact: + self.exit(1) # Like Python itself, ignore the second if the first of these is present elif self.file_to_run: fname = self.file_to_run - if os.path.isdir(fname): - fname = os.path.join(fname, "__main__.py") + if os.path.isdir(fname): + fname = os.path.join(fname, "__main__.py") try: self._exec_file(fname, shell_futures=True) except: self.shell.showtraceback(tb_offset=4) - if not self.interact: - self.exit(1) + if not self.interact: + self.exit(1) def _run_module(self): """Run module specified at the command-line.""" diff --git a/contrib/python/ipython/py2/IPython/core/ultratb.py b/contrib/python/ipython/py2/IPython/core/ultratb.py index a855145825..f327943eb8 100644 --- a/contrib/python/ipython/py2/IPython/core/ultratb.py +++ b/contrib/python/ipython/py2/IPython/core/ultratb.py @@ -38,12 +38,12 @@ Give it a shot--you'll love it or you'll hate it. variables (but otherwise includes the information and context given by Verbose). -.. note:: - - The verbose mode print all variables in the stack, which means it can - potentially leak sensitive information like access keys, or unencryted - password. +.. note:: + The verbose mode print all variables in the stack, which means it can + potentially leak sensitive information like access keys, or unencryted + password. + Installation instructions for VerboseTB:: import sys,ultratb @@ -67,9 +67,9 @@ ColorSchemeTable class. Currently the following exist: - LightBG: similar to Linux but swaps dark/light colors to be more readable in light background terminals. - - Neutral: a neutral color scheme that should be readable on both light and - dark background - + - Neutral: a neutral color scheme that should be readable on both light and + dark background + You can implement other color schemes easily, the syntax is fairly self-explanatory. Please send back new schemes you develop to the author for possible inclusion in future releases. @@ -88,7 +88,7 @@ Inheritance diagram: # the file COPYING, distributed as part of this software. #***************************************************************************** -from __future__ import absolute_import +from __future__ import absolute_import from __future__ import unicode_literals from __future__ import print_function @@ -125,11 +125,11 @@ from IPython.utils import path as util_path from IPython.utils import py3compat from IPython.utils import ulinecache from IPython.utils.data import uniq_stable -from IPython.utils.terminal import get_terminal_size -from logging import info, error - -import IPython.utils.colorable as colorable +from IPython.utils.terminal import get_terminal_size +from logging import info, error +import IPython.utils.colorable as colorable + # Globals # amount of space to put line numbers before verbose tracebacks INDENT_SIZE = 8 @@ -226,8 +226,8 @@ def findsource(object): # the length of lines, which causes an error. Safeguard against that. lnum = min(object.co_firstlineno, len(lines)) - 1 while lnum > 0: - if pmatch(lines[lnum]): - break + if pmatch(lines[lnum]): + break lnum -= 1 return lines, lnum @@ -283,11 +283,11 @@ def getargs(co): remain.pop() size = count.pop() stack[-size:] = [stack[-size:]] - if not remain: - break + if not remain: + break remain[-1] = remain[-1] - 1 - if not remain: - break + if not remain: + break args[i] = stack[0] varargs = None @@ -413,7 +413,7 @@ def _format_traceback_lines(lnum, index, lines, Colors, lvals=None, scheme=None) if i == lnum: # This is the line with the error pad = numbers_width - len(str(i)) - num = '%s%s' % (debugger.make_arrow(pad), str(lnum)) + num = '%s%s' % (debugger.make_arrow(pad), str(lnum)) line = '%s%s%s %s%s' % (Colors.linenoEm, num, Colors.line, line, Colors.Normal) else: @@ -481,22 +481,22 @@ def find_recursion(etype, value, records): #--------------------------------------------------------------------------- # Module classes -class TBTools(colorable.Colorable): +class TBTools(colorable.Colorable): """Basic tools used by all traceback printer classes.""" # Number of frames to skip when reporting tracebacks tb_offset = 0 - def __init__(self, color_scheme='NoColor', call_pdb=False, ostream=None, parent=None, config=None): + def __init__(self, color_scheme='NoColor', call_pdb=False, ostream=None, parent=None, config=None): # Whether to call the interactive pdb debugger after printing # tracebacks or not - super(TBTools, self).__init__(parent=parent, config=config) + super(TBTools, self).__init__(parent=parent, config=config) self.call_pdb = call_pdb # Output stream to write to. Note that we store the original value in # a private attribute and then make the public ostream a property, so - # that we can delay accessing sys.stdout until runtime. The way - # things are written now, the sys.stdout object is dynamically managed + # that we can delay accessing sys.stdout until runtime. The way + # things are written now, the sys.stdout object is dynamically managed # so a reference to it should NEVER be stored statically. This # property approach confines this detail to a single location, and all # subclasses can simply access self.ostream for writing. @@ -509,7 +509,7 @@ class TBTools(colorable.Colorable): self.old_scheme = color_scheme # save initial value for toggles if call_pdb: - self.pdb = debugger.Pdb() + self.pdb = debugger.Pdb() else: self.pdb = None @@ -519,12 +519,12 @@ class TBTools(colorable.Colorable): Valid values are: - None: the default, which means that IPython will dynamically resolve - to sys.stdout. This ensures compatibility with most tools, including + to sys.stdout. This ensures compatibility with most tools, including Windows (where plain stdout doesn't recognize ANSI escapes). - Any object with 'write' and 'flush' attributes. """ - return sys.stdout if self._ostream is None else self._ostream + return sys.stdout if self._ostream is None else self._ostream def _set_ostream(self, val): assert val is None or (hasattr(val, 'write') and hasattr(val, 'flush')) @@ -596,9 +596,9 @@ class ListTB(TBTools): Because they are meant to be called without a full traceback (only a list), instances of this class can't call the interactive pdb debugger.""" - def __init__(self, color_scheme='NoColor', call_pdb=False, ostream=None, parent=None): + def __init__(self, color_scheme='NoColor', call_pdb=False, ostream=None, parent=None): TBTools.__init__(self, color_scheme=color_scheme, call_pdb=call_pdb, - ostream=ostream, parent=parent) + ostream=ostream, parent=parent) def __call__(self, etype, value, elist): self.ostream.flush() @@ -711,10 +711,10 @@ class ListTB(TBTools): have_filedata = False Colors = self.Colors list = [] - stype = py3compat.cast_unicode(Colors.excName + etype.__name__ + Colors.Normal) + stype = py3compat.cast_unicode(Colors.excName + etype.__name__ + Colors.Normal) if value is None: # Not sure if this can still happen in Python 2.6 and above - list.append(stype + '\n') + list.append(stype + '\n') else: if issubclass(etype, SyntaxError): have_filedata = True @@ -754,10 +754,10 @@ class ListTB(TBTools): except Exception: s = self._some_str(value) if s: - list.append('%s%s:%s %s\n' % (stype, Colors.excName, + list.append('%s%s:%s %s\n' % (stype, Colors.excName, Colors.Normal, s)) else: - list.append('%s\n' % stype) + list.append('%s\n' % stype) # sync with user hooks if have_filedata: @@ -795,9 +795,9 @@ class ListTB(TBTools): def _some_str(self, value): # Lifted from traceback.py try: - return py3compat.cast_unicode(str(value)) + return py3compat.cast_unicode(str(value)) except: - return u'<unprintable %s object>' % type(value).__name__ + return u'<unprintable %s object>' % type(value).__name__ #---------------------------------------------------------------------------- @@ -811,7 +811,7 @@ class VerboseTB(TBTools): def __init__(self, color_scheme='Linux', call_pdb=False, ostream=None, tb_offset=0, long_header=False, include_vars=True, - check_cache=None, debugger_cls = None): + check_cache=None, debugger_cls = None): """Specify traceback offset, headers and color scheme. Define how many frames to drop from the tracebacks. Calling it with @@ -832,8 +832,8 @@ class VerboseTB(TBTools): check_cache = linecache.checkcache self.check_cache = check_cache - self.debugger_cls = debugger_cls or debugger.Pdb - + self.debugger_cls = debugger_cls or debugger.Pdb + def format_records(self, records, last_unique, recursion_repeat): """Format the stack frames of the traceback""" frames = [] @@ -929,12 +929,12 @@ class VerboseTB(TBTools): elif file.endswith(('.pyc', '.pyo')): # Look up the corresponding source file. - try: - file = openpy.source_from_cache(file) - except ValueError: - # Failed to get the source file for some reason - # E.g. https://github.com/ipython/ipython/issues/9486 - return '%s %s\n' % (link, call) + try: + file = openpy.source_from_cache(file) + except ValueError: + # Failed to get the source file for some reason + # E.g. https://github.com/ipython/ipython/issues/9486 + return '%s %s\n' % (link, call) def linereader(file=file, lnum=[lnum], getline=ulinecache.getline): line = getline(file, lnum[0]) @@ -1038,21 +1038,21 @@ class VerboseTB(TBTools): colors = self.Colors # just a shorthand + quicker name lookup colorsnormal = colors.Normal # used a lot exc = '%s%s%s' % (colors.excName, etype, colorsnormal) - width = min(75, get_terminal_size()[0]) + width = min(75, get_terminal_size()[0]) if long_version: # Header with the exception type, python version, and date pyver = 'Python ' + sys.version.split()[0] + ': ' + sys.executable date = time.ctime(time.time()) - head = '%s%s%s\n%s%s%s\n%s' % (colors.topline, '-' * width, colorsnormal, - exc, ' ' * (width - len(str(etype)) - len(pyver)), - pyver, date.rjust(width) ) + head = '%s%s%s\n%s%s%s\n%s' % (colors.topline, '-' * width, colorsnormal, + exc, ' ' * (width - len(str(etype)) - len(pyver)), + pyver, date.rjust(width) ) head += "\nA problem occurred executing Python code. Here is the sequence of function" \ "\ncalls leading up to the error, with the most recent (innermost) call last." else: # Simplified header head = '%s%s' % (exc, 'Traceback (most recent call last)'. \ - rjust(width - len(str(etype))) ) + rjust(width - len(str(etype))) ) return head @@ -1171,7 +1171,7 @@ class VerboseTB(TBTools): colors = self.Colors # just a shorthand + quicker name lookup colorsnormal = colors.Normal # used a lot - head = '%s%s%s' % (colors.topline, '-' * min(75, get_terminal_size()[0]), colorsnormal) + head = '%s%s%s' % (colors.topline, '-' * min(75, get_terminal_size()[0]), colorsnormal) structured_traceback_parts = [head] if py3compat.PY3: chained_exceptions_tb_offset = 0 @@ -1287,7 +1287,7 @@ class FormattedTB(VerboseTB, ListTB): def __init__(self, mode='Plain', color_scheme='Linux', call_pdb=False, ostream=None, tb_offset=0, long_header=False, include_vars=False, - check_cache=None, debugger_cls=None): + check_cache=None, debugger_cls=None): # NEVER change the order of this list. Put new modes at the end: self.valid_modes = ['Plain', 'Context', 'Verbose'] @@ -1296,7 +1296,7 @@ class FormattedTB(VerboseTB, ListTB): VerboseTB.__init__(self, color_scheme=color_scheme, call_pdb=call_pdb, ostream=ostream, tb_offset=tb_offset, long_header=long_header, include_vars=include_vars, - check_cache=check_cache, debugger_cls=debugger_cls) + check_cache=check_cache, debugger_cls=debugger_cls) # Different types of tracebacks are joined with different separators to # form a single string. They are taken from this dict @@ -1446,7 +1446,7 @@ class SyntaxTB(ListTB): newtext = ulinecache.getline(value.filename, value.lineno) if newtext: value.text = newtext - self.last_syntax_error = value + self.last_syntax_error = value return super(SyntaxTB, self).structured_traceback(etype, value, elist, tb_offset=tb_offset, context=context) diff --git a/contrib/python/ipython/py2/IPython/core/usage.py b/contrib/python/ipython/py2/IPython/core/usage.py index c4d3c16eca..26506281a7 100644 --- a/contrib/python/ipython/py2/IPython/core/usage.py +++ b/contrib/python/ipython/py2/IPython/core/usage.py @@ -114,7 +114,7 @@ MAIN FEATURES your history for lines that match what you've typed so far, completing as much as it can. - - %hist: search history by index. + - %hist: search history by index. * Persistent command history across sessions. @@ -337,9 +337,9 @@ default_banner_parts = [ default_banner = ''.join(default_banner_parts) -# deprecated GUI banner +# deprecated GUI banner -default_gui_banner = '\n'.join([ - 'DEPRECATED: IPython.core.usage.default_gui_banner is deprecated and will be removed', - default_banner, -]) +default_gui_banner = '\n'.join([ + 'DEPRECATED: IPython.core.usage.default_gui_banner is deprecated and will be removed', + default_banner, +]) diff --git a/contrib/python/ipython/py2/IPython/extensions/storemagic.py b/contrib/python/ipython/py2/IPython/extensions/storemagic.py index 2fd1abf993..7de7271772 100644 --- a/contrib/python/ipython/py2/IPython/extensions/storemagic.py +++ b/contrib/python/ipython/py2/IPython/extensions/storemagic.py @@ -11,8 +11,8 @@ To automatically restore stored variables at startup, add this to your """ from __future__ import print_function -# Copyright (c) IPython Development Team. -# Distributed under the terms of the Modified BSD License. +# Copyright (c) IPython Development Team. +# Distributed under the terms of the Modified BSD License. import inspect, os, sys, textwrap @@ -61,11 +61,11 @@ class StoreMagics(Magics): Provides the %store magic.""" - autorestore = Bool(False, help= + autorestore = Bool(False, help= """If True, any %store-d variables will be automatically restored when IPython starts. """ - ).tag(config=True) + ).tag(config=True) def __init__(self, shell): super(StoreMagics, self).__init__(shell=shell) diff --git a/contrib/python/ipython/py2/IPython/external/decorators/_numpy_testing_utils.py b/contrib/python/ipython/py2/IPython/external/decorators/_numpy_testing_utils.py index ad7bd0f981..34de37d525 100644 --- a/contrib/python/ipython/py2/IPython/external/decorators/_numpy_testing_utils.py +++ b/contrib/python/ipython/py2/IPython/external/decorators/_numpy_testing_utils.py @@ -85,7 +85,7 @@ class WarningManager: else: return None - def __exit__(self, type_, value, traceback): + def __exit__(self, type_, value, traceback): if not self._entered: raise RuntimeError("Cannot exit %r without entering first" % self) self._module.filters = self._filters @@ -101,8 +101,8 @@ def assert_warns(warning_class, func, *args, **kw): # XXX: once we may depend on python >= 2.6, this can be replaced by the # warnings module context manager. - with WarningManager(record=True) as l: - warnings.simplefilter('always') + with WarningManager(record=True) as l: + warnings.simplefilter('always') func(*args, **kw) if not len(l) > 0: raise AssertionError("No warning raised when calling %s" diff --git a/contrib/python/ipython/py2/IPython/lib/backgroundjobs.py b/contrib/python/ipython/py2/IPython/lib/backgroundjobs.py index b724126bbb..62ae52e94e 100644 --- a/contrib/python/ipython/py2/IPython/lib/backgroundjobs.py +++ b/contrib/python/ipython/py2/IPython/lib/backgroundjobs.py @@ -36,7 +36,7 @@ import threading from IPython import get_ipython from IPython.core.ultratb import AutoFormattedTB -from logging import error +from logging import error from IPython.utils.py3compat import string_types diff --git a/contrib/python/ipython/py2/IPython/lib/deepreload.py b/contrib/python/ipython/py2/IPython/lib/deepreload.py index 76b493c0bb..45efcb45d2 100644 --- a/contrib/python/ipython/py2/IPython/lib/deepreload.py +++ b/contrib/python/ipython/py2/IPython/lib/deepreload.py @@ -351,11 +351,11 @@ def _dreload(module, **kwargs): import reload explicitly from `IPython.lib.deepreload` to use it """ - # this was marked as deprecated and for 5.0 removal, but - # IPython.core_builtin_trap have a Deprecation warning for 6.0, so cannot - # remove that now. + # this was marked as deprecated and for 5.0 removal, but + # IPython.core_builtin_trap have a Deprecation warning for 6.0, so cannot + # remove that now. warn(""" -injecting `dreload` in interactive namespace is deprecated since IPython 4.0. +injecting `dreload` in interactive namespace is deprecated since IPython 4.0. Please import `reload` explicitly from `IPython.lib.deepreload`. """, DeprecationWarning, stacklevel=2) reload(module, **kwargs) diff --git a/contrib/python/ipython/py2/IPython/lib/demo.py b/contrib/python/ipython/py2/IPython/lib/demo.py index b0f3503ed7..7b047ad82a 100644 --- a/contrib/python/ipython/py2/IPython/lib/demo.py +++ b/contrib/python/ipython/py2/IPython/lib/demo.py @@ -326,7 +326,7 @@ class Demo(object): if index is None: if self.finished: - print('Demo finished. Use <demo_name>.reset() if you want to rerun it.') + print('Demo finished. Use <demo_name>.reset() if you want to rerun it.') return None index = self.block_index else: @@ -397,8 +397,8 @@ class Demo(object): return print(self.marquee('<%s> block # %s (%s remaining)' % - (self.title,index,self.nblocks-index-1))) - print(self.src_blocks_colored[index]) + (self.title,index,self.nblocks-index-1))) + print(self.src_blocks_colored[index]) sys.stdout.flush() def show_all(self): @@ -412,11 +412,11 @@ class Demo(object): for index,block in enumerate(self.src_blocks_colored): if silent[index]: print(marquee('<%s> SILENT block # %s (%s remaining)' % - (title,index,nblocks-index-1))) + (title,index,nblocks-index-1))) else: print(marquee('<%s> block # %s (%s remaining)' % - (title,index,nblocks-index-1))) - print(block, end=' ') + (title,index,nblocks-index-1))) + print(block, end=' ') sys.stdout.flush() def run_cell(self,source): @@ -442,17 +442,17 @@ class Demo(object): self.block_index += 1 if self._silent[index]: print(marquee('Executing silent block # %s (%s remaining)' % - (index,self.nblocks-index-1))) + (index,self.nblocks-index-1))) else: self.pre_cmd() self.show(index) if self.auto_all or self._auto[index]: - print(marquee('output:')) + print(marquee('output:')) else: - print(marquee('Press <q> to quit, <Enter> to execute...'), end=' ') + print(marquee('Press <q> to quit, <Enter> to execute...'), end=' ') ans = py3compat.input().strip() if ans: - print(marquee('Block NOT executed')) + print(marquee('Block NOT executed')) return try: save_argv = sys.argv @@ -470,10 +470,10 @@ class Demo(object): if self.block_index == self.nblocks: mq1 = self.marquee('END OF DEMO') if mq1: - # avoid spurious print if empty marquees are used - print() - print(mq1) - print(self.marquee('Use <demo_name>.reset() if you want to rerun it.')) + # avoid spurious print if empty marquees are used + print() + print(mq1) + print(self.marquee('Use <demo_name>.reset() if you want to rerun it.')) self.finished = True # These methods are meant to be overridden by subclasses who may wish to diff --git a/contrib/python/ipython/py2/IPython/lib/display.py b/contrib/python/ipython/py2/IPython/lib/display.py index 9221e2e062..5a8d79ad47 100644 --- a/contrib/python/ipython/py2/IPython/lib/display.py +++ b/contrib/python/ipython/py2/IPython/lib/display.py @@ -41,7 +41,7 @@ class Audio(DisplayObject): filename : unicode Path to a local file to load the data from. embed : boolean - Should the audio data be embedded using a data URI (True) or should + Should the audio data be embedded using a data URI (True) or should the original source be referenced. Set this to True if you want the audio to playable later with no internet connection in the notebook. diff --git a/contrib/python/ipython/py2/IPython/lib/inputhook.py b/contrib/python/ipython/py2/IPython/lib/inputhook.py index e6e8f2dbbc..e742264914 100644 --- a/contrib/python/ipython/py2/IPython/lib/inputhook.py +++ b/contrib/python/ipython/py2/IPython/lib/inputhook.py @@ -1,7 +1,7 @@ # coding: utf-8 """ -Deprecated since IPython 5.0 - +Deprecated since IPython 5.0 + Inputhook management for GUI event loop integration. """ @@ -19,13 +19,13 @@ import platform import sys from distutils.version import LooseVersion as V -from warnings import warn - - -warn("`IPython.lib.inputhook` is deprecated since IPython 5.0 and will be removed in future versions.", - DeprecationWarning, stacklevel=2) - +from warnings import warn + +warn("`IPython.lib.inputhook` is deprecated since IPython 5.0 and will be removed in future versions.", + DeprecationWarning, stacklevel=2) + + #----------------------------------------------------------------------------- # Constants #----------------------------------------------------------------------------- @@ -105,10 +105,10 @@ else: class InputHookManager(object): - """DEPRECATED since IPython 5.0 - - Manage PyOS_InputHook for different GUI toolkits. + """DEPRECATED since IPython 5.0 + Manage PyOS_InputHook for different GUI toolkits. + This class installs various hooks under ``PyOSInputHook`` to handle GUI event loop integration. """ @@ -130,25 +130,25 @@ class InputHookManager(object): self._current_gui = None def get_pyos_inputhook(self): - """DEPRECATED since IPython 5.0 - - Return the current PyOS_InputHook as a ctypes.c_void_p.""" - warn("`get_pyos_inputhook` is deprecated since IPython 5.0 and will be removed in future versions.", - DeprecationWarning, stacklevel=2) + """DEPRECATED since IPython 5.0 + + Return the current PyOS_InputHook as a ctypes.c_void_p.""" + warn("`get_pyos_inputhook` is deprecated since IPython 5.0 and will be removed in future versions.", + DeprecationWarning, stacklevel=2) return ctypes.c_void_p.in_dll(ctypes.pythonapi,"PyOS_InputHook") def get_pyos_inputhook_as_func(self): - """DEPRECATED since IPython 5.0 - - Return the current PyOS_InputHook as a ctypes.PYFUNCYPE.""" - warn("`get_pyos_inputhook_as_func` is deprecated since IPython 5.0 and will be removed in future versions.", - DeprecationWarning, stacklevel=2) + """DEPRECATED since IPython 5.0 + + Return the current PyOS_InputHook as a ctypes.PYFUNCYPE.""" + warn("`get_pyos_inputhook_as_func` is deprecated since IPython 5.0 and will be removed in future versions.", + DeprecationWarning, stacklevel=2) return self.PYFUNC.in_dll(ctypes.pythonapi,"PyOS_InputHook") def set_inputhook(self, callback): - """DEPRECATED since IPython 5.0 - - Set PyOS_InputHook to callback and return the previous one.""" + """DEPRECATED since IPython 5.0 + + Set PyOS_InputHook to callback and return the previous one.""" # On platforms with 'readline' support, it's all too likely to # have a KeyboardInterrupt signal delivered *even before* an # initial ``try:`` clause in the callback can be executed, so @@ -164,10 +164,10 @@ class InputHookManager(object): return original def clear_inputhook(self, app=None): - """DEPRECATED since IPython 5.0 - - Set PyOS_InputHook to NULL and return the previous one. + """DEPRECATED since IPython 5.0 + Set PyOS_InputHook to NULL and return the previous one. + Parameters ---------- app : optional, ignored @@ -176,8 +176,8 @@ class InputHookManager(object): the actual value of the parameter is ignored. This uniform interface makes it easier to have user-level entry points in the main IPython app like :meth:`enable_gui`.""" - warn("`clear_inputhook` is deprecated since IPython 5.0 and will be removed in future versions.", - DeprecationWarning, stacklevel=2) + warn("`clear_inputhook` is deprecated since IPython 5.0 and will be removed in future versions.", + DeprecationWarning, stacklevel=2) pyos_inputhook_ptr = self.get_pyos_inputhook() original = self.get_pyos_inputhook_as_func() pyos_inputhook_ptr.value = ctypes.c_void_p(None).value @@ -186,10 +186,10 @@ class InputHookManager(object): return original def clear_app_refs(self, gui=None): - """DEPRECATED since IPython 5.0 - - Clear IPython's internal reference to an application instance. + """DEPRECATED since IPython 5.0 + Clear IPython's internal reference to an application instance. + Whenever we create an app for a user on qt4 or wx, we hold a reference to the app. This is needed because in some cases bad things can happen if a user doesn't hold a reference themselves. This @@ -202,17 +202,17 @@ class InputHookManager(object): the app for that toolkit. References are not held for gtk or tk as those toolkits don't have the notion of an app. """ - warn("`clear_app_refs` is deprecated since IPython 5.0 and will be removed in future versions.", - DeprecationWarning, stacklevel=2) + warn("`clear_app_refs` is deprecated since IPython 5.0 and will be removed in future versions.", + DeprecationWarning, stacklevel=2) if gui is None: self.apps = {} elif gui in self.apps: del self.apps[gui] def register(self, toolkitname, *aliases): - """DEPRECATED since IPython 5.0 - - Register a class to provide the event loop for a given GUI. + """DEPRECATED since IPython 5.0 + + Register a class to provide the event loop for a given GUI. This is intended to be used as a class decorator. It should be passed the names with which to register this GUI integration. The classes @@ -225,8 +225,8 @@ class InputHookManager(object): def enable(self, app=None): ... """ - warn("`register` is deprecated since IPython 5.0 and will be removed in future versions.", - DeprecationWarning, stacklevel=2) + warn("`register` is deprecated since IPython 5.0 and will be removed in future versions.", + DeprecationWarning, stacklevel=2) def decorator(cls): if ctypes is not None: inst = cls(self) @@ -237,18 +237,18 @@ class InputHookManager(object): return decorator def current_gui(self): - """DEPRECATED since IPython 5.0 - - Return a string indicating the currently active GUI or None.""" - warn("`current_gui` is deprecated since IPython 5.0 and will be removed in future versions.", - DeprecationWarning, stacklevel=2) + """DEPRECATED since IPython 5.0 + + Return a string indicating the currently active GUI or None.""" + warn("`current_gui` is deprecated since IPython 5.0 and will be removed in future versions.", + DeprecationWarning, stacklevel=2) return self._current_gui def enable_gui(self, gui=None, app=None): - """DEPRECATED since IPython 5.0 - - Switch amongst GUI input hooks by name. + """DEPRECATED since IPython 5.0 + Switch amongst GUI input hooks by name. + This is a higher level method than :meth:`set_inputhook` - it uses the GUI name to look up a registered object which enables the input hook for that GUI. @@ -271,8 +271,8 @@ class InputHookManager(object): PyOS_InputHook wrapper object or the GUI toolkit app created, if there was one. """ - warn("`enable_gui` is deprecated since IPython 5.0 and will be removed in future versions.", - DeprecationWarning, stacklevel=2) + warn("`enable_gui` is deprecated since IPython 5.0 and will be removed in future versions.", + DeprecationWarning, stacklevel=2) if gui in (None, GUI_NONE): return self.disable_gui() @@ -289,28 +289,28 @@ class InputHookManager(object): app = gui_hook.enable(app) if app is not None: app._in_event_loop = True - self.apps[gui] = app + self.apps[gui] = app return app def disable_gui(self): - """DEPRECATED since IPython 5.0 - - Disable GUI event loop integration. + """DEPRECATED since IPython 5.0 + + Disable GUI event loop integration. If an application was registered, this sets its ``_in_event_loop`` attribute to False. It then calls :meth:`clear_inputhook`. """ - warn("`disable_gui` is deprecated since IPython 5.0 and will be removed in future versions.", - DeprecationWarning, stacklevel=2) + warn("`disable_gui` is deprecated since IPython 5.0 and will be removed in future versions.", + DeprecationWarning, stacklevel=2) gui = self._current_gui if gui in self.apps: self.apps[gui]._in_event_loop = False return self.clear_inputhook() class InputHookBase(object): - """DEPRECATED since IPython 5.0 - - Base class for input hooks for specific toolkits. + """DEPRECATED since IPython 5.0 + + Base class for input hooks for specific toolkits. Subclasses should define an :meth:`enable` method with one argument, ``app``, which will either be an instance of the toolkit's application class, or None. @@ -326,20 +326,20 @@ inputhook_manager = InputHookManager() @inputhook_manager.register('osx') class NullInputHook(InputHookBase): - """DEPRECATED since IPython 5.0 - - A null inputhook that doesn't need to do anything""" + """DEPRECATED since IPython 5.0 + + A null inputhook that doesn't need to do anything""" def enable(self, app=None): - warn("This function is deprecated since IPython 5.0 and will be removed in future versions.", - DeprecationWarning, stacklevel=2) + warn("This function is deprecated since IPython 5.0 and will be removed in future versions.", + DeprecationWarning, stacklevel=2) @inputhook_manager.register('wx') class WxInputHook(InputHookBase): def enable(self, app=None): - """DEPRECATED since IPython 5.0 - - Enable event loop integration with wxPython. + """DEPRECATED since IPython 5.0 + Enable event loop integration with wxPython. + Parameters ---------- app : WX Application, optional. @@ -359,8 +359,8 @@ class WxInputHook(InputHookBase): import wx app = wx.App(redirect=False, clearSigInt=False) """ - warn("This function is deprecated since IPython 5.0 and will be removed in future versions.", - DeprecationWarning, stacklevel=2) + warn("This function is deprecated since IPython 5.0 and will be removed in future versions.", + DeprecationWarning, stacklevel=2) import wx wx_version = V(wx.__version__).version @@ -383,14 +383,14 @@ class WxInputHook(InputHookBase): return app def disable(self): - """DEPRECATED since IPython 5.0 - - Disable event loop integration with wxPython. + """DEPRECATED since IPython 5.0 + Disable event loop integration with wxPython. + This restores appnapp on OS X """ - warn("This function is deprecated since IPython 5.0 and will be removed in future versions.", - DeprecationWarning, stacklevel=2) + warn("This function is deprecated since IPython 5.0 and will be removed in future versions.", + DeprecationWarning, stacklevel=2) if _use_appnope(): from appnope import nap nap() @@ -398,9 +398,9 @@ class WxInputHook(InputHookBase): @inputhook_manager.register('qt', 'qt4') class Qt4InputHook(InputHookBase): def enable(self, app=None): - """DEPRECATED since IPython 5.0 - - Enable event loop integration with PyQt4. + """DEPRECATED since IPython 5.0 + + Enable event loop integration with PyQt4. Parameters ---------- @@ -421,8 +421,8 @@ class Qt4InputHook(InputHookBase): from PyQt4 import QtCore app = QtGui.QApplication(sys.argv) """ - warn("This function is deprecated since IPython 5.0 and will be removed in future versions.", - DeprecationWarning, stacklevel=2) + warn("This function is deprecated since IPython 5.0 and will be removed in future versions.", + DeprecationWarning, stacklevel=2) from IPython.lib.inputhookqt4 import create_inputhook_qt4 app, inputhook_qt4 = create_inputhook_qt4(self.manager, app) self.manager.set_inputhook(inputhook_qt4) @@ -433,14 +433,14 @@ class Qt4InputHook(InputHookBase): return app def disable_qt4(self): - """DEPRECATED since IPython 5.0 - - Disable event loop integration with PyQt4. + """DEPRECATED since IPython 5.0 + Disable event loop integration with PyQt4. + This restores appnapp on OS X """ - warn("This function is deprecated since IPython 5.0 and will be removed in future versions.", - DeprecationWarning, stacklevel=2) + warn("This function is deprecated since IPython 5.0 and will be removed in future versions.", + DeprecationWarning, stacklevel=2) if _use_appnope(): from appnope import nap nap() @@ -449,8 +449,8 @@ class Qt4InputHook(InputHookBase): @inputhook_manager.register('qt5') class Qt5InputHook(Qt4InputHook): def enable(self, app=None): - warn("This function is deprecated since IPython 5.0 and will be removed in future versions.", - DeprecationWarning, stacklevel=2) + warn("This function is deprecated since IPython 5.0 and will be removed in future versions.", + DeprecationWarning, stacklevel=2) os.environ['QT_API'] = 'pyqt5' return Qt4InputHook.enable(self, app) @@ -458,10 +458,10 @@ class Qt5InputHook(Qt4InputHook): @inputhook_manager.register('gtk') class GtkInputHook(InputHookBase): def enable(self, app=None): - """DEPRECATED since IPython 5.0 - - Enable event loop integration with PyGTK. + """DEPRECATED since IPython 5.0 + Enable event loop integration with PyGTK. + Parameters ---------- app : ignored @@ -475,8 +475,8 @@ class GtkInputHook(InputHookBase): the PyGTK to integrate with terminal based applications like IPython. """ - warn("This function is deprecated since IPython 5.0 and will be removed in future versions.", - DeprecationWarning, stacklevel=2) + warn("This function is deprecated since IPython 5.0 and will be removed in future versions.", + DeprecationWarning, stacklevel=2) import gtk try: gtk.set_interactive(True) @@ -489,10 +489,10 @@ class GtkInputHook(InputHookBase): @inputhook_manager.register('tk') class TkInputHook(InputHookBase): def enable(self, app=None): - """DEPRECATED since IPython 5.0 - - Enable event loop integration with Tk. + """DEPRECATED since IPython 5.0 + Enable event loop integration with Tk. + Parameters ---------- app : toplevel :class:`Tkinter.Tk` widget, optional. @@ -506,8 +506,8 @@ class TkInputHook(InputHookBase): :class:`InputHookManager`, since creating that object automatically sets ``PyOS_InputHook``. """ - warn("This function is deprecated since IPython 5.0 and will be removed in future versions.", - DeprecationWarning, stacklevel=2) + warn("This function is deprecated since IPython 5.0 and will be removed in future versions.", + DeprecationWarning, stacklevel=2) if app is None: try: from tkinter import Tk # Py 3 @@ -522,10 +522,10 @@ class TkInputHook(InputHookBase): @inputhook_manager.register('glut') class GlutInputHook(InputHookBase): def enable(self, app=None): - """DEPRECATED since IPython 5.0 - - Enable event loop integration with GLUT. + """DEPRECATED since IPython 5.0 + Enable event loop integration with GLUT. + Parameters ---------- @@ -547,8 +547,8 @@ class GlutInputHook(InputHookBase): The default screen mode is set to: glut.GLUT_DOUBLE | glut.GLUT_RGBA | glut.GLUT_DEPTH """ - warn("This function is deprecated since IPython 5.0 and will be removed in future versions.", - DeprecationWarning, stacklevel=2) + warn("This function is deprecated since IPython 5.0 and will be removed in future versions.", + DeprecationWarning, stacklevel=2) import OpenGL.GLUT as glut from IPython.lib.inputhookglut import glut_display_mode, \ @@ -576,16 +576,16 @@ class GlutInputHook(InputHookBase): def disable(self): - """DEPRECATED since IPython 5.0 - - Disable event loop integration with glut. + """DEPRECATED since IPython 5.0 + + Disable event loop integration with glut. This sets PyOS_InputHook to NULL and set the display function to a dummy one and set the timer to a dummy timer that will be triggered very far in the future. """ - warn("This function is deprecated since IPython 5.0 and will be removed in future versions.", - DeprecationWarning, stacklevel=2) + warn("This function is deprecated since IPython 5.0 and will be removed in future versions.", + DeprecationWarning, stacklevel=2) import OpenGL.GLUT as glut from glut_support import glutMainLoopEvent @@ -596,10 +596,10 @@ class GlutInputHook(InputHookBase): @inputhook_manager.register('pyglet') class PygletInputHook(InputHookBase): def enable(self, app=None): - """DEPRECATED since IPython 5.0 - - Enable event loop integration with pyglet. + """DEPRECATED since IPython 5.0 + Enable event loop integration with pyglet. + Parameters ---------- app : ignored @@ -614,8 +614,8 @@ class PygletInputHook(InputHookBase): IPython. """ - warn("This function is deprecated since IPython 5.0 and will be removed in future versions.", - DeprecationWarning, stacklevel=2) + warn("This function is deprecated since IPython 5.0 and will be removed in future versions.", + DeprecationWarning, stacklevel=2) from IPython.lib.inputhookpyglet import inputhook_pyglet self.manager.set_inputhook(inputhook_pyglet) return app @@ -624,10 +624,10 @@ class PygletInputHook(InputHookBase): @inputhook_manager.register('gtk3') class Gtk3InputHook(InputHookBase): def enable(self, app=None): - """DEPRECATED since IPython 5.0 - - Enable event loop integration with Gtk3 (gir bindings). + """DEPRECATED since IPython 5.0 + Enable event loop integration with Gtk3 (gir bindings). + Parameters ---------- app : ignored @@ -641,8 +641,8 @@ class Gtk3InputHook(InputHookBase): the Gtk3 to integrate with terminal based applications like IPython. """ - warn("This function is deprecated since IPython 5.0 and will be removed in future versions.", - DeprecationWarning, stacklevel=2) + warn("This function is deprecated since IPython 5.0 and will be removed in future versions.", + DeprecationWarning, stacklevel=2) from IPython.lib.inputhookgtk3 import inputhook_gtk3 self.manager.set_inputhook(inputhook_gtk3) diff --git a/contrib/python/ipython/py2/IPython/lib/latextools.py b/contrib/python/ipython/py2/IPython/lib/latextools.py index c3230dd489..5b3c93dc63 100644 --- a/contrib/python/ipython/py2/IPython/lib/latextools.py +++ b/contrib/python/ipython/py2/IPython/lib/latextools.py @@ -39,24 +39,24 @@ class LaTeXTool(SingletonConfigurable): # for display style, the default ["matplotlib", "dvipng"] can # be used. To NOT use dvipng so that other repr such as # unicode pretty printing is used, you can use ["matplotlib"]. - ).tag(config=True) + ).tag(config=True) use_breqn = Bool( True, help="Use breqn.sty to automatically break long equations. " "This configuration takes effect only for dvipng backend.", - ).tag(config=True) + ).tag(config=True) packages = List( ['amsmath', 'amsthm', 'amssymb', 'bm'], help="A list of packages to use for dvipng backend. " "'breqn' will be automatically appended when use_breqn=True.", - ).tag(config=True) + ).tag(config=True) preamble = Unicode( help="Additional preamble to use when generating LaTeX source " "for dvipng backend.", - ).tag(config=True) + ).tag(config=True) def latex_to_png(s, encode=False, backend=None, wrap=False): @@ -64,7 +64,7 @@ def latex_to_png(s, encode=False, backend=None, wrap=False): Parameters ---------- - s : str + s : str The raw string containing valid inline LaTeX. encode : bool, optional Should the PNG data base64 encoded to make it JSON'able. @@ -97,24 +97,24 @@ def latex_to_png(s, encode=False, backend=None, wrap=False): def latex_to_png_mpl(s, wrap): try: from matplotlib import mathtext - from pyparsing import ParseFatalException + from pyparsing import ParseFatalException except ImportError: return None - + # mpl mathtext doesn't support display math, force inline s = s.replace('$$', '$') if wrap: s = u'${0}$'.format(s) - try: - mt = mathtext.MathTextParser('bitmap') - f = BytesIO() - mt.to_png(f, s, fontsize=12) - return f.getvalue() - except (ValueError, RuntimeError, ParseFatalException): - return None - + try: + mt = mathtext.MathTextParser('bitmap') + f = BytesIO() + mt.to_png(f, s, fontsize=12) + return f.getvalue() + except (ValueError, RuntimeError, ParseFatalException): + return None + def latex_to_png_dvipng(s, wrap): try: find_cmd('latex') @@ -142,8 +142,8 @@ def latex_to_png_dvipng(s, wrap): with open(outfile, "rb") as f: return f.read() - except subprocess.CalledProcessError: - return None + except subprocess.CalledProcessError: + return None finally: shutil.rmtree(workdir) diff --git a/contrib/python/ipython/py2/IPython/lib/lexers.py b/contrib/python/ipython/py2/IPython/lib/lexers.py index 9160ae1245..1b81e3db61 100644 --- a/contrib/python/ipython/py2/IPython/lib/lexers.py +++ b/contrib/python/ipython/py2/IPython/lib/lexers.py @@ -44,7 +44,7 @@ from pygments.lexer import ( Lexer, DelegatingLexer, RegexLexer, do_insertions, bygroups, using, ) from pygments.token import ( - Generic, Keyword, Literal, Name, Operator, Other, Text, Error, + Generic, Keyword, Literal, Name, Operator, Other, Text, Error, ) from pygments.util import get_bool_opt @@ -235,13 +235,13 @@ class IPythonConsoleLexer(Lexer): # The regexps used to determine what is input and what is output. # The default prompts for IPython are: # - # in = 'In [#]: ' - # continuation = ' .D.: ' - # template = 'Out[#]: ' - # - # Where '#' is the 'prompt number' or 'execution count' and 'D' - # D is a number of dots matching the width of the execution count + # in = 'In [#]: ' + # continuation = ' .D.: ' + # template = 'Out[#]: ' # + # Where '#' is the 'prompt number' or 'execution count' and 'D' + # D is a number of dots matching the width of the execution count + # in1_regex = r'In \[[0-9]+\]: ' in2_regex = r' \.\.+\.: ' out_regex = r'Out\[[0-9]+\]: ' @@ -475,9 +475,9 @@ class IPythonConsoleLexer(Lexer): self.insertions.append((len(self.buffer), [insertion])) self.buffer += code - for token in self.buffered_tokens(): - yield token - + for token in self.buffered_tokens(): + yield token + class IPyLexer(Lexer): """ Primary lexer for all IPython-like code. diff --git a/contrib/python/ipython/py2/IPython/lib/pretty.py b/contrib/python/ipython/py2/IPython/lib/pretty.py index 28eee523c5..09d638cbcb 100644 --- a/contrib/python/ipython/py2/IPython/lib/pretty.py +++ b/contrib/python/ipython/py2/IPython/lib/pretty.py @@ -85,7 +85,7 @@ import re import datetime from collections import deque -from IPython.utils.py3compat import PY3, PYPY, cast_unicode, string_types +from IPython.utils.py3compat import PY3, PYPY, cast_unicode, string_types from IPython.utils.encoding import get_stream_enc from io import StringIO @@ -609,8 +609,8 @@ def _dict_pprinter_factory(start, end): def inner(obj, p, cycle): if cycle: return p.text('{...}') - step = len(start) - p.begin_group(step, start) + step = len(start) + p.begin_group(step, start) keys = obj.keys() # if dict isn't large enough to be truncated, sort keys before displaying # From Python 3.7, dicts preserve order by definition, so we don't sort. @@ -624,7 +624,7 @@ def _dict_pprinter_factory(start, end): p.pretty(key) p.text(': ') p.pretty(obj[key]) - p.end_group(step, end) + p.end_group(step, end) return inner @@ -634,11 +634,11 @@ def _super_pprint(obj, p, cycle): p.pretty(obj.__thisclass__) p.text(',') p.breakable() - if PYPY: # In PyPy, super() objects don't have __self__ attributes - dself = obj.__repr__.__self__ - p.pretty(None if dself is obj else dself) - else: - p.pretty(obj.__self__) + if PYPY: # In PyPy, super() objects don't have __self__ attributes + dself = obj.__repr__.__self__ + p.pretty(None if dself is obj else dself) + else: + p.pretty(obj.__self__) p.end_group(8, '>') @@ -672,10 +672,10 @@ def _type_pprint(obj, p, cycle): # Heap allocated types might not have the module attribute, # and others may set it to None. - # Checks for a __repr__ override in the metaclass. Can't compare the - # type(obj).__repr__ directly because in PyPy the representation function - # inherited from type isn't the same type.__repr__ - if [m for m in _get_mro(type(obj)) if "__repr__" in vars(m)][:1] != [type]: + # Checks for a __repr__ override in the metaclass. Can't compare the + # type(obj).__repr__ directly because in PyPy the representation function + # inherited from type isn't the same type.__repr__ + if [m for m in _get_mro(type(obj)) if "__repr__" in vars(m)][:1] != [type]: _repr_pprint(obj, p, cycle) return @@ -762,15 +762,15 @@ _type_pprinters = { } try: - # In PyPy, types.DictProxyType is dict, setting the dictproxy printer - # using dict.setdefault avoids overwritting the dict printer - _type_pprinters.setdefault(types.DictProxyType, - _dict_pprinter_factory('dict_proxy({', '})')) + # In PyPy, types.DictProxyType is dict, setting the dictproxy printer + # using dict.setdefault avoids overwritting the dict printer + _type_pprinters.setdefault(types.DictProxyType, + _dict_pprinter_factory('dict_proxy({', '})')) _type_pprinters[types.ClassType] = _type_pprint _type_pprinters[types.SliceType] = _repr_pprint except AttributeError: # Python 3 - _type_pprinters[types.MappingProxyType] = \ - _dict_pprinter_factory('mappingproxy({', '})') + _type_pprinters[types.MappingProxyType] = \ + _dict_pprinter_factory('mappingproxy({', '})') _type_pprinters[slice] = _repr_pprint try: diff --git a/contrib/python/ipython/py2/IPython/sphinxext/ipython_directive.py b/contrib/python/ipython/py2/IPython/sphinxext/ipython_directive.py index 8df9ace1f3..2173954c20 100644 --- a/contrib/python/ipython/py2/IPython/sphinxext/ipython_directive.py +++ b/contrib/python/ipython/py2/IPython/sphinxext/ipython_directive.py @@ -874,7 +874,7 @@ class IPythonDirective(Directive): # EmbeddedSphinxShell is created, its interactive shell member # is the same for each instance. - if mplbackend and 'matplotlib.backends' not in sys.modules: + if mplbackend and 'matplotlib.backends' not in sys.modules: import matplotlib matplotlib.use(mplbackend) diff --git a/contrib/python/ipython/py2/IPython/terminal/debugger.py b/contrib/python/ipython/py2/IPython/terminal/debugger.py index c68a3204a6..4be1bae6a8 100644 --- a/contrib/python/ipython/py2/IPython/terminal/debugger.py +++ b/contrib/python/ipython/py2/IPython/terminal/debugger.py @@ -1,46 +1,46 @@ import signal import sys -from IPython.core.debugger import Pdb - -from IPython.core.completer import IPCompleter -from .ptutils import IPythonPTCompleter +from IPython.core.debugger import Pdb + +from IPython.core.completer import IPCompleter +from .ptutils import IPythonPTCompleter from .shortcuts import suspend_to_bg, cursor_in_leading_ws - + from prompt_toolkit.enums import DEFAULT_BUFFER from prompt_toolkit.filters import (Condition, HasFocus, HasSelection, ViInsertMode, EmacsInsertMode) from prompt_toolkit.keys import Keys from prompt_toolkit.key_binding.manager import KeyBindingManager from prompt_toolkit.key_binding.bindings.completion import display_completions_like_readline -from prompt_toolkit.token import Token -from prompt_toolkit.shortcuts import create_prompt_application -from prompt_toolkit.interface import CommandLineInterface -from prompt_toolkit.enums import EditingMode - - -class TerminalPdb(Pdb): - def __init__(self, *args, **kwargs): - Pdb.__init__(self, *args, **kwargs) - self._ptcomp = None - self.pt_init() - - def pt_init(self): - def get_prompt_tokens(cli): - return [(Token.Prompt, self.prompt)] - +from prompt_toolkit.token import Token +from prompt_toolkit.shortcuts import create_prompt_application +from prompt_toolkit.interface import CommandLineInterface +from prompt_toolkit.enums import EditingMode + + +class TerminalPdb(Pdb): + def __init__(self, *args, **kwargs): + Pdb.__init__(self, *args, **kwargs) + self._ptcomp = None + self.pt_init() + + def pt_init(self): + def get_prompt_tokens(cli): + return [(Token.Prompt, self.prompt)] + def patch_stdout(**kwargs): return self.pt_cli.patch_stdout_context(**kwargs) - if self._ptcomp is None: - compl = IPCompleter(shell=self.shell, - namespace={}, - global_namespace={}, - use_readline=False, - parent=self.shell, - ) + if self._ptcomp is None: + compl = IPCompleter(shell=self.shell, + namespace={}, + global_namespace={}, + use_readline=False, + parent=self.shell, + ) self._ptcomp = IPythonPTCompleter(compl, patch_stdout=patch_stdout) - + kbmanager = KeyBindingManager.for_prompt() supports_suspend = Condition(lambda cli: hasattr(signal, 'SIGTSTP')) kbmanager.registry.add_binding(Keys.ControlZ, filter=supports_suspend @@ -55,55 +55,55 @@ class TerminalPdb(Pdb): ))(display_completions_like_readline) multicolumn = (self.shell.display_completions == 'multicolumn') - self._pt_app = create_prompt_application( - editing_mode=getattr(EditingMode, self.shell.editing_mode.upper()), + self._pt_app = create_prompt_application( + editing_mode=getattr(EditingMode, self.shell.editing_mode.upper()), key_bindings_registry=kbmanager.registry, - history=self.shell.debugger_history, - completer= self._ptcomp, - enable_history_search=True, - mouse_support=self.shell.mouse_support, + history=self.shell.debugger_history, + completer= self._ptcomp, + enable_history_search=True, + mouse_support=self.shell.mouse_support, get_prompt_tokens=get_prompt_tokens, display_completions_in_columns=multicolumn, style=self.shell.style - ) - self.pt_cli = CommandLineInterface(self._pt_app, eventloop=self.shell._eventloop) - - def cmdloop(self, intro=None): - """Repeatedly issue a prompt, accept input, parse an initial prefix - off the received input, and dispatch to action methods, passing them - the remainder of the line as argument. - - override the same methods from cmd.Cmd to provide prompt toolkit replacement. - """ - if not self.use_rawinput: - raise ValueError('Sorry ipdb does not support use_rawinput=False') - - self.preloop() - - try: - if intro is not None: - self.intro = intro - if self.intro: - self.stdout.write(str(self.intro)+"\n") - stop = None - while not stop: - if self.cmdqueue: - line = self.cmdqueue.pop(0) - else: - self._ptcomp.ipy_completer.namespace = self.curframe_locals - self._ptcomp.ipy_completer.global_namespace = self.curframe.f_globals - try: - line = self.pt_cli.run(reset_current_buffer=True).text - except EOFError: - line = 'EOF' - line = self.precmd(line) - stop = self.onecmd(line) - stop = self.postcmd(stop, line) - self.postloop() - except Exception: - raise - - + ) + self.pt_cli = CommandLineInterface(self._pt_app, eventloop=self.shell._eventloop) + + def cmdloop(self, intro=None): + """Repeatedly issue a prompt, accept input, parse an initial prefix + off the received input, and dispatch to action methods, passing them + the remainder of the line as argument. + + override the same methods from cmd.Cmd to provide prompt toolkit replacement. + """ + if not self.use_rawinput: + raise ValueError('Sorry ipdb does not support use_rawinput=False') + + self.preloop() + + try: + if intro is not None: + self.intro = intro + if self.intro: + self.stdout.write(str(self.intro)+"\n") + stop = None + while not stop: + if self.cmdqueue: + line = self.cmdqueue.pop(0) + else: + self._ptcomp.ipy_completer.namespace = self.curframe_locals + self._ptcomp.ipy_completer.global_namespace = self.curframe.f_globals + try: + line = self.pt_cli.run(reset_current_buffer=True).text + except EOFError: + line = 'EOF' + line = self.precmd(line) + stop = self.onecmd(line) + stop = self.postcmd(stop, line) + self.postloop() + except Exception: + raise + + def set_trace(frame=None): """ Start debugging from `frame`. diff --git a/contrib/python/ipython/py2/IPython/terminal/embed.py b/contrib/python/ipython/py2/IPython/terminal/embed.py index 5ad70431e4..9f8be00a77 100644 --- a/contrib/python/ipython/py2/IPython/terminal/embed.py +++ b/contrib/python/ipython/py2/IPython/terminal/embed.py @@ -14,7 +14,7 @@ import warnings from IPython.core import ultratb, compilerop from IPython.core import magic_arguments from IPython.core.magic import Magics, magics_class, line_magic -from IPython.core.interactiveshell import DummyMod, InteractiveShell +from IPython.core.interactiveshell import DummyMod, InteractiveShell from IPython.terminal.interactiveshell import TerminalInteractiveShell from IPython.terminal.ipapp import load_default_config @@ -117,33 +117,33 @@ class InteractiveShellEmbed(TerminalInteractiveShell): display_banner = CBool(True) exit_msg = Unicode() - # When embedding, by default we don't change the terminal title - term_title = Bool(False, - help="Automatically set the terminal title" - ).tag(config=True) - - _inactive_locations = set() - - @property - def embedded_active(self): + # When embedding, by default we don't change the terminal title + term_title = Bool(False, + help="Automatically set the terminal title" + ).tag(config=True) + + _inactive_locations = set() + + @property + def embedded_active(self): return (self._call_location_id not in InteractiveShellEmbed._inactive_locations)\ and (self._init_location_id not in InteractiveShellEmbed._inactive_locations) - + def _disable_init_location(self): """Disable the current Instance creation location""" InteractiveShellEmbed._inactive_locations.add(self._init_location_id) - @embedded_active.setter - def embedded_active(self, value): + @embedded_active.setter + def embedded_active(self, value): if value: InteractiveShellEmbed._inactive_locations.discard( self._call_location_id) InteractiveShellEmbed._inactive_locations.discard( self._init_location_id) - else: + else: InteractiveShellEmbed._inactive_locations.add( self._call_location_id) - + def __init__(self, **kw): if kw.get('user_global_ns', None) is not None: raise DeprecationWarning( @@ -154,7 +154,7 @@ class InteractiveShellEmbed(TerminalInteractiveShell): frame = sys._getframe(1) clid = '%s:%s' % (frame.f_code.co_filename, frame.f_lineno) self._init_location_id = clid - + super(InteractiveShellEmbed,self).__init__(**kw) # don't use the ipython crash handler so that user exceptions aren't @@ -219,9 +219,9 @@ class InteractiveShellEmbed(TerminalInteractiveShell): else: self.old_banner2 = '' - if self.display_banner: - self.show_banner() - + if self.display_banner: + self.show_banner() + # Call the embedding code with a stack depth of 1 so it can skip over # our call and get the original caller's namespaces. self.mainloop(local_ns, module, stack_depth=stack_depth, @@ -264,11 +264,11 @@ class InteractiveShellEmbed(TerminalInteractiveShell): """ if (global_ns is not None) and (module is None): - raise DeprecationWarning("'global_ns' keyword argument is deprecated, and has been removed in IPython 5.0 use `module` keyword argument instead.") - - if (display_banner is not None): - warnings.warn("The display_banner parameter is deprecated since IPython 4.0", DeprecationWarning) + 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): @@ -278,14 +278,14 @@ class InteractiveShellEmbed(TerminalInteractiveShell): local_ns = call_frame.f_locals if module is None: global_ns = call_frame.f_globals - try: - module = sys.modules[global_ns['__name__']] - except KeyError: - warnings.warn("Failed to get module %s" % \ - global_ns.get('__name__', 'unknown module') - ) - module = DummyMod() - module.__dict__ = global_ns + try: + module = sys.modules[global_ns['__name__']] + except KeyError: + warnings.warn("Failed to get module %s" % \ + global_ns.get('__name__', 'unknown module') + ) + module = DummyMod() + module.__dict__ = global_ns if compile_flags is None: compile_flags = (call_frame.f_code.co_flags & compilerop.PyCF_MASK) @@ -320,7 +320,7 @@ class InteractiveShellEmbed(TerminalInteractiveShell): self.set_completer_frame() with self.builtin_trap, self.display_trap: - self.interact() + self.interact() # now, purge out the local namespace of IPython's hidden variables. if local_ns is not None: @@ -378,7 +378,7 @@ def embed(**kwargs): if saved_shell_instance is not None: cls = type(saved_shell_instance) cls.clear_instance() - frame = sys._getframe(1) + frame = sys._getframe(1) shell = InteractiveShellEmbed.instance(_init_location_id='%s:%s' % ( frame.f_code.co_filename, frame.f_lineno), **kwargs) shell(header=header, stack_depth=2, compile_flags=compile_flags, diff --git a/contrib/python/ipython/py2/IPython/terminal/interactiveshell.py b/contrib/python/ipython/py2/IPython/terminal/interactiveshell.py index f67cc6b502..c5b0d7d921 100644 --- a/contrib/python/ipython/py2/IPython/terminal/interactiveshell.py +++ b/contrib/python/ipython/py2/IPython/terminal/interactiveshell.py @@ -1,68 +1,68 @@ -"""IPython terminal interface using prompt_toolkit""" +"""IPython terminal interface using prompt_toolkit""" from __future__ import print_function import os import sys -import warnings -from warnings import warn +import warnings +from warnings import warn from IPython.core.interactiveshell import InteractiveShell, InteractiveShellABC -from IPython.utils import io +from IPython.utils import io from IPython.utils.py3compat import PY3, cast_unicode_py2, input, string_types from IPython.utils.terminal import toggle_set_term_title, set_term_title from IPython.utils.process import abbrev_cwd from traitlets import Bool, Unicode, Dict, Integer, observe, Instance, Type, default, Enum, Union from prompt_toolkit.document import Document -from prompt_toolkit.enums import DEFAULT_BUFFER, EditingMode -from prompt_toolkit.filters import (HasFocus, Condition, IsDone) -from prompt_toolkit.history import InMemoryHistory -from prompt_toolkit.shortcuts import create_prompt_application, create_eventloop, create_prompt_layout, create_output -from prompt_toolkit.interface import CommandLineInterface -from prompt_toolkit.key_binding.manager import KeyBindingManager -from prompt_toolkit.layout.processors import ConditionalProcessor, HighlightMatchingBracketProcessor -from prompt_toolkit.styles import PygmentsStyle, DynamicStyle +from prompt_toolkit.enums import DEFAULT_BUFFER, EditingMode +from prompt_toolkit.filters import (HasFocus, Condition, IsDone) +from prompt_toolkit.history import InMemoryHistory +from prompt_toolkit.shortcuts import create_prompt_application, create_eventloop, create_prompt_layout, create_output +from prompt_toolkit.interface import CommandLineInterface +from prompt_toolkit.key_binding.manager import KeyBindingManager +from prompt_toolkit.layout.processors import ConditionalProcessor, HighlightMatchingBracketProcessor +from prompt_toolkit.styles import PygmentsStyle, DynamicStyle from pygments.styles import get_style_by_name from pygments.style import Style -from pygments.token import Token - -from .debugger import TerminalPdb, Pdb -from .magics import TerminalMagics +from pygments.token import Token + +from .debugger import TerminalPdb, Pdb +from .magics import TerminalMagics from .pt_inputhooks import get_inputhook_name_and_func -from .prompts import Prompts, ClassicPrompts, RichPromptDisplayHook -from .ptutils import IPythonPTCompleter, IPythonPTLexer -from .shortcuts import register_ipython_shortcuts - -DISPLAY_BANNER_DEPRECATED = object() - - -from pygments.style import Style - -class _NoStyle(Style): pass - - - -_style_overrides_light_bg = { - Token.Prompt: '#0000ff', - Token.PromptNum: '#0000ee bold', - Token.OutPrompt: '#cc0000', - Token.OutPromptNum: '#bb0000 bold', -} - -_style_overrides_linux = { - Token.Prompt: '#00cc00', - Token.PromptNum: '#00bb00 bold', - Token.OutPrompt: '#cc0000', - Token.OutPromptNum: '#bb0000 bold', -} - - - +from .prompts import Prompts, ClassicPrompts, RichPromptDisplayHook +from .ptutils import IPythonPTCompleter, IPythonPTLexer +from .shortcuts import register_ipython_shortcuts + +DISPLAY_BANNER_DEPRECATED = object() + + +from pygments.style import Style + +class _NoStyle(Style): pass + + + +_style_overrides_light_bg = { + Token.Prompt: '#0000ff', + Token.PromptNum: '#0000ee bold', + Token.OutPrompt: '#cc0000', + Token.OutPromptNum: '#bb0000 bold', +} + +_style_overrides_linux = { + Token.Prompt: '#00cc00', + Token.PromptNum: '#00bb00 bold', + Token.OutPrompt: '#cc0000', + Token.OutPromptNum: '#bb0000 bold', +} + + + def get_default_editor(): try: ed = os.environ['EDITOR'] - if not PY3: + if not PY3: ed = ed.decode() return ed except KeyError: @@ -76,153 +76,153 @@ def get_default_editor(): else: return 'notepad' # same in Windows! -# conservatively check for tty -# overridden streams can result in things like: -# - sys.stdin = None -# - no isatty method -for _name in ('stdin', 'stdout', 'stderr'): - _stream = getattr(sys, _name) - if not _stream or not hasattr(_stream, 'isatty') or not _stream.isatty(): - _is_tty = False - break -else: - _is_tty = True +# conservatively check for tty +# overridden streams can result in things like: +# - sys.stdin = None +# - no isatty method +for _name in ('stdin', 'stdout', 'stderr'): + _stream = getattr(sys, _name) + if not _stream or not hasattr(_stream, 'isatty') or not _stream.isatty(): + _is_tty = False + break +else: + _is_tty = True -_use_simple_prompt = ('IPY_TEST_SIMPLE_PROMPT' in os.environ) or (not _is_tty) +_use_simple_prompt = ('IPY_TEST_SIMPLE_PROMPT' in os.environ) or (not _is_tty) -class TerminalInteractiveShell(InteractiveShell): - space_for_menu = Integer(6, help='Number of line at the bottom of the screen ' - 'to reserve for the completion menu' - ).tag(config=True) +class TerminalInteractiveShell(InteractiveShell): + space_for_menu = Integer(6, help='Number of line at the bottom of the screen ' + 'to reserve for the completion menu' + ).tag(config=True) - def _space_for_menu_changed(self, old, new): - self._update_layout() + def _space_for_menu_changed(self, old, new): + self._update_layout() - pt_cli = None - debugger_history = None - _pt_app = None + pt_cli = None + debugger_history = None + _pt_app = None - simple_prompt = Bool(_use_simple_prompt, + simple_prompt = Bool(_use_simple_prompt, help="""Use `raw_input` for the REPL, without completion and prompt colors. - Useful when controlling IPython as a subprocess, and piping STDIN/OUT/ERR. Known usage are: - IPython own testing machinery, and emacs inferior-shell integration through elpy. + Useful when controlling IPython as a subprocess, and piping STDIN/OUT/ERR. Known usage are: + IPython own testing machinery, and emacs inferior-shell integration through elpy. - This mode default to `True` if the `IPY_TEST_SIMPLE_PROMPT` - environment variable is set, or the current terminal is not a tty. + This mode default to `True` if the `IPY_TEST_SIMPLE_PROMPT` + environment variable is set, or the current terminal is not a tty. - """ - ).tag(config=True) + """ + ).tag(config=True) - @property - def debugger_cls(self): - return Pdb if self.simple_prompt else TerminalPdb + @property + def debugger_cls(self): + return Pdb if self.simple_prompt else TerminalPdb - confirm_exit = Bool(True, - help=""" - Set to confirm when you try to exit IPython with an EOF (Control-D - in Unix, Control-Z/Enter in Windows). By typing 'exit' or 'quit', - you can force a direct exit without any confirmation.""", - ).tag(config=True) + confirm_exit = Bool(True, + help=""" + Set to confirm when you try to exit IPython with an EOF (Control-D + in Unix, Control-Z/Enter in Windows). By typing 'exit' or 'quit', + you can force a direct exit without any confirmation.""", + ).tag(config=True) - editing_mode = Unicode('emacs', - help="Shortcut style to use at the prompt. 'vi' or 'emacs'.", - ).tag(config=True) + editing_mode = Unicode('emacs', + help="Shortcut style to use at the prompt. 'vi' or 'emacs'.", + ).tag(config=True) - mouse_support = Bool(False, - help="Enable mouse support in the prompt" - ).tag(config=True) + mouse_support = Bool(False, + help="Enable mouse support in the prompt" + ).tag(config=True) # We don't load the list of styles for the help string, because loading # Pygments plugins takes time and can cause unexpected errors. highlighting_style = Union([Unicode('legacy'), Type(klass=Style)], help="""The name or class of a Pygments style to use for syntax highlighting. To see available styles, run `pygmentize -L styles`.""" - ).tag(config=True) + ).tag(config=True) - @observe('highlighting_style') - @observe('colors') - def _highlighting_style_changed(self, change): - self.refresh_style() + @observe('highlighting_style') + @observe('colors') + def _highlighting_style_changed(self, change): + self.refresh_style() - def refresh_style(self): + def refresh_style(self): self._style = self._make_style_from_name_or_cls(self.highlighting_style) - highlighting_style_overrides = Dict( - help="Override highlighting format for specific tokens" - ).tag(config=True) + highlighting_style_overrides = Dict( + help="Override highlighting format for specific tokens" + ).tag(config=True) - true_color = Bool(False, - help=("Use 24bit colors instead of 256 colors in prompt highlighting. " - "If your terminal supports true color, the following command " - "should print 'TRUECOLOR' in orange: " - "printf \"\\x1b[38;2;255;100;0mTRUECOLOR\\x1b[0m\\n\"") - ).tag(config=True) + true_color = Bool(False, + help=("Use 24bit colors instead of 256 colors in prompt highlighting. " + "If your terminal supports true color, the following command " + "should print 'TRUECOLOR' in orange: " + "printf \"\\x1b[38;2;255;100;0mTRUECOLOR\\x1b[0m\\n\"") + ).tag(config=True) - editor = Unicode(get_default_editor(), - help="Set the editor used by IPython (default to $EDITOR/vi/notepad)." - ).tag(config=True) + editor = Unicode(get_default_editor(), + help="Set the editor used by IPython (default to $EDITOR/vi/notepad)." + ).tag(config=True) - prompts_class = Type(Prompts, help='Class used to generate Prompt token for prompt_toolkit').tag(config=True) + prompts_class = Type(Prompts, help='Class used to generate Prompt token for prompt_toolkit').tag(config=True) - prompts = Instance(Prompts) + prompts = Instance(Prompts) - @default('prompts') - def _prompts_default(self): - return self.prompts_class(self) + @default('prompts') + def _prompts_default(self): + return self.prompts_class(self) - @observe('prompts') - def _(self, change): - self._update_layout() + @observe('prompts') + def _(self, change): + self._update_layout() - @default('displayhook_class') - def _displayhook_class_default(self): - return RichPromptDisplayHook + @default('displayhook_class') + def _displayhook_class_default(self): + return RichPromptDisplayHook - term_title = Bool(True, - help="Automatically set the terminal title" - ).tag(config=True) + term_title = Bool(True, + help="Automatically set the terminal title" + ).tag(config=True) display_completions = Enum(('column', 'multicolumn','readlinelike'), - help= ( "Options for displaying tab completions, 'column', 'multicolumn', and " - "'readlinelike'. These options are for `prompt_toolkit`, see " - "`prompt_toolkit` documentation for more information." - ), - default_value='multicolumn').tag(config=True) + help= ( "Options for displaying tab completions, 'column', 'multicolumn', and " + "'readlinelike'. These options are for `prompt_toolkit`, see " + "`prompt_toolkit` documentation for more information." + ), + default_value='multicolumn').tag(config=True) - highlight_matching_brackets = Bool(True, + highlight_matching_brackets = Bool(True, help="Highlight matching brackets.", - ).tag(config=True) + ).tag(config=True) extra_open_editor_shortcuts = Bool(False, help="Enable vi (v) or Emacs (C-X C-E) shortcuts to open an external editor. " "This is in addition to the F2 binding, which is always enabled." ).tag(config=True) - @observe('term_title') - def init_term_title(self, change=None): - # Enable or disable the terminal title. - if self.term_title: - toggle_set_term_title(True) - set_term_title('IPython: ' + abbrev_cwd()) - else: - toggle_set_term_title(False) - - def init_display_formatter(self): - super(TerminalInteractiveShell, self).init_display_formatter() - # terminal only supports plain text - self.display_formatter.active_types = ['text/plain'] + @observe('term_title') + def init_term_title(self, change=None): + # Enable or disable the terminal title. + if self.term_title: + toggle_set_term_title(True) + set_term_title('IPython: ' + abbrev_cwd()) + else: + toggle_set_term_title(False) + + def init_display_formatter(self): + super(TerminalInteractiveShell, self).init_display_formatter() + # terminal only supports plain text + self.display_formatter.active_types = ['text/plain'] # disable `_ipython_display_` self.display_formatter.ipython_display_formatter.enabled = False - def init_prompt_toolkit_cli(self): - if self.simple_prompt: - # Fall back to plain non-interactive output for tests. - # This is very limited, and only accepts a single line. - def prompt(): + def init_prompt_toolkit_cli(self): + if self.simple_prompt: + # Fall back to plain non-interactive output for tests. + # This is very limited, and only accepts a single line. + def prompt(): isp = self.input_splitter prompt_text = "".join(x[1] for x in self.prompts.in_prompt_tokens()) prompt_continuation = "".join(x[1] for x in self.prompts.continuation_prompt_tokens()) @@ -231,82 +231,82 @@ class TerminalInteractiveShell(InteractiveShell): isp.push(line) prompt_text = prompt_continuation return isp.source_reset() - self.prompt_for_code = prompt - return + self.prompt_for_code = prompt + return - # Set up keyboard shortcuts + # Set up keyboard shortcuts kbmanager = KeyBindingManager.for_prompt( enable_open_in_editor=self.extra_open_editor_shortcuts, ) - register_ipython_shortcuts(kbmanager.registry, self) - - # Pre-populate history from IPython's history database - history = InMemoryHistory() - last_cell = u"" - for __, ___, cell in self.history_manager.get_tail(self.history_load_length, - include_latest=True): - # Ignore blank lines and consecutive duplicates - cell = cell.rstrip() - if cell and (cell != last_cell): - history.append(cell) + register_ipython_shortcuts(kbmanager.registry, self) + + # Pre-populate history from IPython's history database + history = InMemoryHistory() + last_cell = u"" + for __, ___, cell in self.history_manager.get_tail(self.history_load_length, + include_latest=True): + # Ignore blank lines and consecutive duplicates + cell = cell.rstrip() + if cell and (cell != last_cell): + history.append(cell) last_cell = cell self._style = self._make_style_from_name_or_cls(self.highlighting_style) self.style = DynamicStyle(lambda: self._style) - editing_mode = getattr(EditingMode, self.editing_mode.upper()) + editing_mode = getattr(EditingMode, self.editing_mode.upper()) def patch_stdout(**kwargs): return self.pt_cli.patch_stdout_context(**kwargs) - self._pt_app = create_prompt_application( - editing_mode=editing_mode, - key_bindings_registry=kbmanager.registry, - history=history, + self._pt_app = create_prompt_application( + editing_mode=editing_mode, + key_bindings_registry=kbmanager.registry, + history=history, completer=IPythonPTCompleter(shell=self, patch_stdout=patch_stdout), - enable_history_search=True, + enable_history_search=True, style=self.style, - mouse_support=self.mouse_support, - **self._layout_options() - ) - self._eventloop = create_eventloop(self.inputhook) - self.pt_cli = CommandLineInterface( - self._pt_app, eventloop=self._eventloop, - output=create_output(true_color=self.true_color)) + mouse_support=self.mouse_support, + **self._layout_options() + ) + self._eventloop = create_eventloop(self.inputhook) + self.pt_cli = CommandLineInterface( + self._pt_app, eventloop=self._eventloop, + output=create_output(true_color=self.true_color)) def _make_style_from_name_or_cls(self, name_or_cls): - """ - Small wrapper that make an IPython compatible style from a style name + """ + Small wrapper that make an IPython compatible style from a style name We need that to add style for prompt ... etc. """ - style_overrides = {} + style_overrides = {} if name_or_cls == 'legacy': - legacy = self.colors.lower() - if legacy == 'linux': - style_cls = get_style_by_name('monokai') - style_overrides = _style_overrides_linux - elif legacy == 'lightbg': - style_overrides = _style_overrides_light_bg - style_cls = get_style_by_name('pastie') - elif legacy == 'neutral': - # The default theme needs to be visible on both a dark background - # and a light background, because we can't tell what the terminal - # looks like. These tweaks to the default theme help with that. - style_cls = get_style_by_name('default') - style_overrides.update({ - Token.Number: '#007700', - Token.Operator: 'noinherit', - Token.String: '#BB6622', - Token.Name.Function: '#2080D0', - Token.Name.Class: 'bold #2080D0', - Token.Name.Namespace: 'bold #2080D0', - Token.Prompt: '#009900', - Token.PromptNum: '#00ff00 bold', - Token.OutPrompt: '#990000', - Token.OutPromptNum: '#ff0000 bold', - }) + legacy = self.colors.lower() + if legacy == 'linux': + style_cls = get_style_by_name('monokai') + style_overrides = _style_overrides_linux + elif legacy == 'lightbg': + style_overrides = _style_overrides_light_bg + style_cls = get_style_by_name('pastie') + elif legacy == 'neutral': + # The default theme needs to be visible on both a dark background + # and a light background, because we can't tell what the terminal + # looks like. These tweaks to the default theme help with that. + style_cls = get_style_by_name('default') + style_overrides.update({ + Token.Number: '#007700', + Token.Operator: 'noinherit', + Token.String: '#BB6622', + Token.Name.Function: '#2080D0', + Token.Name.Class: 'bold #2080D0', + Token.Name.Namespace: 'bold #2080D0', + Token.Prompt: '#009900', + Token.PromptNum: '#00ff00 bold', + Token.OutPrompt: '#990000', + Token.OutPromptNum: '#ff0000 bold', + }) # Hack: Due to limited color support on the Windows console # the prompt colors will be wrong without this @@ -317,111 +317,111 @@ class TerminalInteractiveShell(InteractiveShell): Token.OutPrompt: '#ansidarkred', Token.OutPromptNum: '#ansired bold', }) - elif legacy =='nocolor': - style_cls=_NoStyle - style_overrides = {} - else : - raise ValueError('Got unknown colors: ', legacy) - else : + elif legacy =='nocolor': + style_cls=_NoStyle + style_overrides = {} + else : + raise ValueError('Got unknown colors: ', legacy) + else : if isinstance(name_or_cls, string_types): style_cls = get_style_by_name(name_or_cls) else: style_cls = name_or_cls - style_overrides = { - Token.Prompt: '#009900', - Token.PromptNum: '#00ff00 bold', - Token.OutPrompt: '#990000', - Token.OutPromptNum: '#ff0000 bold', - } - style_overrides.update(self.highlighting_style_overrides) - style = PygmentsStyle.from_defaults(pygments_style_cls=style_cls, - style_dict=style_overrides) - - return style - - def _layout_options(self): + style_overrides = { + Token.Prompt: '#009900', + Token.PromptNum: '#00ff00 bold', + Token.OutPrompt: '#990000', + Token.OutPromptNum: '#ff0000 bold', + } + style_overrides.update(self.highlighting_style_overrides) + style = PygmentsStyle.from_defaults(pygments_style_cls=style_cls, + style_dict=style_overrides) + + return style + + def _layout_options(self): + """ + Return the current layout option for the current Terminal InteractiveShell + """ + return { + 'lexer':IPythonPTLexer(), + 'reserve_space_for_menu':self.space_for_menu, + 'get_prompt_tokens':self.prompts.in_prompt_tokens, + 'get_continuation_tokens':self.prompts.continuation_prompt_tokens, + 'multiline':True, + 'display_completions_in_columns': (self.display_completions == 'multicolumn'), + + # Highlight matching brackets, but only when this setting is + # enabled, and only when the DEFAULT_BUFFER has the focus. + 'extra_input_processors': [ConditionalProcessor( + processor=HighlightMatchingBracketProcessor(chars='[](){}'), + filter=HasFocus(DEFAULT_BUFFER) & ~IsDone() & + Condition(lambda cli: self.highlight_matching_brackets))], + } + + def _update_layout(self): """ - Return the current layout option for the current Terminal InteractiveShell - """ - return { - 'lexer':IPythonPTLexer(), - 'reserve_space_for_menu':self.space_for_menu, - 'get_prompt_tokens':self.prompts.in_prompt_tokens, - 'get_continuation_tokens':self.prompts.continuation_prompt_tokens, - 'multiline':True, - 'display_completions_in_columns': (self.display_completions == 'multicolumn'), - - # Highlight matching brackets, but only when this setting is - # enabled, and only when the DEFAULT_BUFFER has the focus. - 'extra_input_processors': [ConditionalProcessor( - processor=HighlightMatchingBracketProcessor(chars='[](){}'), - filter=HasFocus(DEFAULT_BUFFER) & ~IsDone() & - Condition(lambda cli: self.highlight_matching_brackets))], - } - - def _update_layout(self): - """ - Ask for a re computation of the application layout, if for example , - some configuration options have changed. - """ - if self._pt_app: - self._pt_app.layout = create_prompt_layout(**self._layout_options()) - - def prompt_for_code(self): - document = self.pt_cli.run( - pre_run=self.pre_prompt, reset_current_buffer=True) - return document.text - - def enable_win_unicode_console(self): + Ask for a re computation of the application layout, if for example , + some configuration options have changed. + """ + if self._pt_app: + self._pt_app.layout = create_prompt_layout(**self._layout_options()) + + def prompt_for_code(self): + document = self.pt_cli.run( + pre_run=self.pre_prompt, reset_current_buffer=True) + return document.text + + def enable_win_unicode_console(self): if sys.version_info >= (3, 6): # Since PEP 528, Python uses the unicode APIs for the Windows # console by default, so WUC shouldn't be needed. return - import win_unicode_console + import win_unicode_console - if PY3: - win_unicode_console.enable() + if PY3: + win_unicode_console.enable() else: - # https://github.com/ipython/ipython/issues/9768 - from win_unicode_console.streams import (TextStreamWrapper, - stdout_text_transcoded, stderr_text_transcoded) + # https://github.com/ipython/ipython/issues/9768 + from win_unicode_console.streams import (TextStreamWrapper, + stdout_text_transcoded, stderr_text_transcoded) - class LenientStrStreamWrapper(TextStreamWrapper): - def write(self, s): - if isinstance(s, bytes): - s = s.decode(self.encoding, 'replace') + class LenientStrStreamWrapper(TextStreamWrapper): + def write(self, s): + if isinstance(s, bytes): + s = s.decode(self.encoding, 'replace') - self.base.write(s) + self.base.write(s) - stdout_text_str = LenientStrStreamWrapper(stdout_text_transcoded) - stderr_text_str = LenientStrStreamWrapper(stderr_text_transcoded) + stdout_text_str = LenientStrStreamWrapper(stdout_text_transcoded) + stderr_text_str = LenientStrStreamWrapper(stderr_text_transcoded) - win_unicode_console.enable(stdout=stdout_text_str, - stderr=stderr_text_str) + win_unicode_console.enable(stdout=stdout_text_str, + stderr=stderr_text_str) - def init_io(self): - if sys.platform not in {'win32', 'cli'}: - return + def init_io(self): + if sys.platform not in {'win32', 'cli'}: + return - self.enable_win_unicode_console() + self.enable_win_unicode_console() - import colorama - colorama.init() + import colorama + colorama.init() - # For some reason we make these wrappers around stdout/stderr. - # For now, we need to reset them so all output gets coloured. - # https://github.com/ipython/ipython/issues/8669 - # io.std* are deprecated, but don't show our own deprecation warnings - # during initialization of the deprecated API. - with warnings.catch_warnings(): - warnings.simplefilter('ignore', DeprecationWarning) - io.stdout = io.IOStream(sys.stdout) - io.stderr = io.IOStream(sys.stderr) + # For some reason we make these wrappers around stdout/stderr. + # For now, we need to reset them so all output gets coloured. + # https://github.com/ipython/ipython/issues/8669 + # io.std* are deprecated, but don't show our own deprecation warnings + # during initialization of the deprecated API. + with warnings.catch_warnings(): + warnings.simplefilter('ignore', DeprecationWarning) + io.stdout = io.IOStream(sys.stdout) + io.stderr = io.IOStream(sys.stderr) - def init_magics(self): - super(TerminalInteractiveShell, self).init_magics() - self.register_magics(TerminalMagics) + def init_magics(self): + super(TerminalInteractiveShell, self).init_magics() + self.register_magics(TerminalMagics) def init_alias(self): # The parent class defines aliases that can be safely used with any @@ -432,25 +432,25 @@ class TerminalInteractiveShell(InteractiveShell): # need direct access to the console in a way that we can't emulate in # GUI or web frontend if os.name == 'posix': - for cmd in ['clear', 'more', 'less', 'man']: - self.alias_manager.soft_define_alias(cmd, cmd) + for cmd in ['clear', 'more', 'less', 'man']: + self.alias_manager.soft_define_alias(cmd, cmd) - def __init__(self, *args, **kwargs): - super(TerminalInteractiveShell, self).__init__(*args, **kwargs) - self.init_prompt_toolkit_cli() - self.init_term_title() - self.keep_running = True + def __init__(self, *args, **kwargs): + super(TerminalInteractiveShell, self).__init__(*args, **kwargs) + self.init_prompt_toolkit_cli() + self.init_term_title() + self.keep_running = True - self.debugger_history = InMemoryHistory() + self.debugger_history = InMemoryHistory() - def ask_exit(self): - self.keep_running = False + def ask_exit(self): + self.keep_running = False - rl_next_input = None + rl_next_input = None - def pre_prompt(self): - if self.rl_next_input: + def pre_prompt(self): + if self.rl_next_input: # We can't set the buffer here, because it will be reset just after # this. Adding a callable to pre_run_callables does what we need # after the buffer is reset. @@ -463,37 +463,37 @@ class TerminalInteractiveShell(InteractiveShell): # Older version of prompt_toolkit; it's OK to set the document # directly here. set_doc() - self.rl_next_input = None + self.rl_next_input = None - def interact(self, display_banner=DISPLAY_BANNER_DEPRECATED): + def interact(self, display_banner=DISPLAY_BANNER_DEPRECATED): - if display_banner is not DISPLAY_BANNER_DEPRECATED: - warn('interact `display_banner` argument is deprecated since IPython 5.0. Call `show_banner()` if needed.', DeprecationWarning, stacklevel=2) + if display_banner is not DISPLAY_BANNER_DEPRECATED: + warn('interact `display_banner` argument is deprecated since IPython 5.0. Call `show_banner()` if needed.', DeprecationWarning, stacklevel=2) - self.keep_running = True - while self.keep_running: - print(self.separate_in, end='') + self.keep_running = True + while self.keep_running: + print(self.separate_in, end='') try: - code = self.prompt_for_code() - except EOFError: - if (not self.confirm_exit) \ - or self.ask_yes_no('Do you really want to exit ([y]/n)?','y','n'): - self.ask_exit() + code = self.prompt_for_code() + except EOFError: + if (not self.confirm_exit) \ + or self.ask_yes_no('Do you really want to exit ([y]/n)?','y','n'): + self.ask_exit() else: - if code: - self.run_cell(code, store_history=True) - - def mainloop(self, display_banner=DISPLAY_BANNER_DEPRECATED): - # An extra layer of protection in case someone mashing Ctrl-C breaks - # out of our internal code. - if display_banner is not DISPLAY_BANNER_DEPRECATED: - warn('mainloop `display_banner` argument is deprecated since IPython 5.0. Call `show_banner()` if needed.', DeprecationWarning, stacklevel=2) - while True: + if code: + self.run_cell(code, store_history=True) + + def mainloop(self, display_banner=DISPLAY_BANNER_DEPRECATED): + # An extra layer of protection in case someone mashing Ctrl-C breaks + # out of our internal code. + if display_banner is not DISPLAY_BANNER_DEPRECATED: + warn('mainloop `display_banner` argument is deprecated since IPython 5.0. Call `show_banner()` if needed.', DeprecationWarning, stacklevel=2) + while True: try: - self.interact() - break + self.interact() + break except KeyboardInterrupt as e: print("\n%s escaped interact()\n" % type(e).__name__) finally: @@ -504,49 +504,49 @@ class TerminalInteractiveShell(InteractiveShell): if hasattr(self, '_eventloop'): self._eventloop.stop() - _inputhook = None - def inputhook(self, context): - if self._inputhook is not None: - self._inputhook(context) + _inputhook = None + def inputhook(self, context): + if self._inputhook is not None: + self._inputhook(context) active_eventloop = None - def enable_gui(self, gui=None): - if gui: + def enable_gui(self, gui=None): + if gui: self.active_eventloop, self._inputhook =\ get_inputhook_name_and_func(gui) - else: + else: self.active_eventloop = self._inputhook = None - # Run !system commands directly, not through pipes, so terminal programs - # work correctly. - system = InteractiveShell.system_raw + # Run !system commands directly, not through pipes, so terminal programs + # work correctly. + system = InteractiveShell.system_raw - def auto_rewrite_input(self, cmd): - """Overridden from the parent class to use fancy rewriting prompt""" - if not self.show_rewritten_input: - return + def auto_rewrite_input(self, cmd): + """Overridden from the parent class to use fancy rewriting prompt""" + if not self.show_rewritten_input: + return - tokens = self.prompts.rewrite_prompt_tokens() - if self.pt_cli: - self.pt_cli.print_tokens(tokens) - print(cmd) + tokens = self.prompts.rewrite_prompt_tokens() + if self.pt_cli: + self.pt_cli.print_tokens(tokens) + print(cmd) else: - prompt = ''.join(s for t, s in tokens) - print(prompt, cmd, sep='') + prompt = ''.join(s for t, s in tokens) + print(prompt, cmd, sep='') - _prompts_before = None - def switch_doctest_mode(self, mode): - """Switch prompts to classic for %doctest_mode""" - if mode: - self._prompts_before = self.prompts - self.prompts = ClassicPrompts(self) - elif self._prompts_before: - self.prompts = self._prompts_before - self._prompts_before = None - self._update_layout() + _prompts_before = None + def switch_doctest_mode(self, mode): + """Switch prompts to classic for %doctest_mode""" + if mode: + self._prompts_before = self.prompts + self.prompts = ClassicPrompts(self) + elif self._prompts_before: + self.prompts = self._prompts_before + self._prompts_before = None + self._update_layout() -InteractiveShellABC.register(TerminalInteractiveShell) +InteractiveShellABC.register(TerminalInteractiveShell) -if __name__ == '__main__': - TerminalInteractiveShell.instance().interact() +if __name__ == '__main__': + TerminalInteractiveShell.instance().interact() diff --git a/contrib/python/ipython/py2/IPython/terminal/ipapp.py b/contrib/python/ipython/py2/IPython/terminal/ipapp.py index 6b25aaa3e3..a1181c1b0b 100755 --- a/contrib/python/ipython/py2/IPython/terminal/ipapp.py +++ b/contrib/python/ipython/py2/IPython/terminal/ipapp.py @@ -14,7 +14,7 @@ from __future__ import print_function import logging import os import sys -import warnings +import warnings from traitlets.config.loader import Config from traitlets.config.application import boolean_flag, catch_config_error, Application @@ -32,7 +32,7 @@ from IPython.core.shellapp import ( InteractiveShellApp, shell_flags, shell_aliases ) from IPython.extensions.storemagic import StoreMagics -from .interactiveshell import TerminalInteractiveShell +from .interactiveshell import TerminalInteractiveShell from IPython.paths import get_ipython_dir from traitlets import ( Bool, List, Dict, default, observe, Type @@ -101,11 +101,11 @@ addflag('autoedit-syntax', 'TerminalInteractiveShell.autoedit_syntax', 'Turn on auto editing of files with syntax errors.', 'Turn off auto editing of files with syntax errors.' ) -addflag('simple-prompt', 'TerminalInteractiveShell.simple_prompt', - "Force simple minimal prompt using `raw_input`", - "Use a rich interactive prompt with prompt_toolkit", -) - +addflag('simple-prompt', 'TerminalInteractiveShell.simple_prompt', + "Force simple minimal prompt using `raw_input`", + "Use a rich interactive prompt with prompt_toolkit", +) + addflag('banner', 'TerminalIPythonApp.display_banner', "Display a banner upon starting IPython.", "Don't display a banner upon starting IPython." @@ -123,7 +123,7 @@ addflag('term-title', 'TerminalInteractiveShell.term_title', classic_config = Config() classic_config.InteractiveShell.cache_size = 0 classic_config.PlainTextFormatter.pprint = False -classic_config.TerminalInteractiveShell.prompts_class='IPython.terminal.prompts.ClassicPrompts' +classic_config.TerminalInteractiveShell.prompts_class='IPython.terminal.prompts.ClassicPrompts' classic_config.InteractiveShell.separate_in = '' classic_config.InteractiveShell.separate_out = '' classic_config.InteractiveShell.separate_out2 = '' @@ -192,7 +192,7 @@ class TerminalIPythonApp(BaseIPythonApplication, InteractiveShellApp): help="Class to use to instantiate the TerminalInteractiveShell object. Useful for custom Frontends" ).tag(config=True) - @default('classes') + @default('classes') def _classes_default(self): """This has to be in a method, for TerminalIPythonApp to be available.""" return [ @@ -250,33 +250,33 @@ class TerminalIPythonApp(BaseIPythonApplication, InteractiveShellApp): # *do* autocreate requested profile, but don't create the config file. auto_create=Bool(True) # configurables - quick = Bool(False, + quick = Bool(False, help="""Start IPython quickly by skipping the loading of config files.""" - ).tag(config=True) - @observe('quick') - def _quick_changed(self, change): - if change['new']: + ).tag(config=True) + @observe('quick') + def _quick_changed(self, change): + if change['new']: self.load_config_file = lambda *a, **kw: None - display_banner = Bool(True, + display_banner = Bool(True, help="Whether to display a banner upon starting IPython." - ).tag(config=True) + ).tag(config=True) # if there is code of files to run from the cmd line, don't interact # unless the --i flag (App.force_interact) is true. - force_interact = Bool(False, + force_interact = Bool(False, help="""If a command or file is given via the command-line, e.g. 'ipython foo.py', start an interactive shell after executing the file or command.""" - ).tag(config=True) - @observe('force_interact') - def _force_interact_changed(self, change): - if change['new']: + ).tag(config=True) + @observe('force_interact') + def _force_interact_changed(self, change): + if change['new']: self.interact = True - @observe('file_to_run', 'code_to_run', 'module_to_run') - def _file_to_run_changed(self, change): - new = change['new'] + @observe('file_to_run', 'code_to_run', 'module_to_run') + def _file_to_run_changed(self, change): + new = change['new'] if new: self.something_to_run = True if new and not self.force_interact: @@ -295,7 +295,7 @@ class TerminalIPythonApp(BaseIPythonApplication, InteractiveShellApp): # warn and transform into current syntax argv = argv[:] # copy, don't clobber idx = argv.index('-pylab') - warnings.warn("`-pylab` flag has been deprecated.\n" + warnings.warn("`-pylab` flag has been deprecated.\n" " Use `--matplotlib <backend>` and import pylab manually.") argv[idx] = '--pylab' @@ -328,7 +328,7 @@ class TerminalIPythonApp(BaseIPythonApplication, InteractiveShellApp): # based app, because we call shell.show_banner() by hand below # so the banner shows *before* all extension loading stuff. self.shell = self.interactive_shell_class.instance(parent=self, - profile_dir=self.profile_dir, + profile_dir=self.profile_dir, ipython_dir=self.ipython_dir, user_ns=self.user_ns) self.shell.configurables.append(self) @@ -342,7 +342,7 @@ class TerminalIPythonApp(BaseIPythonApplication, InteractiveShellApp): def _pylab_changed(self, name, old, new): """Replace --pylab='inline' with --pylab='auto'""" if new == 'inline': - warnings.warn("'inline' not available as pylab backend, " + warnings.warn("'inline' not available as pylab backend, " "using 'auto' instead.") self.pylab = 'auto' diff --git a/contrib/python/ipython/py2/IPython/terminal/magics.py b/contrib/python/ipython/py2/IPython/terminal/magics.py index 3a844a0397..60f465b0dc 100644 --- a/contrib/python/ipython/py2/IPython/terminal/magics.py +++ b/contrib/python/ipython/py2/IPython/terminal/magics.py @@ -1,208 +1,208 @@ -"""Extra magics for terminal use.""" - -# Copyright (c) IPython Development Team. -# Distributed under the terms of the Modified BSD License. - -from __future__ import print_function - -from logging import error -import os -import sys - -from IPython.core.error import TryNext, UsageError -from IPython.core.inputsplitter import IPythonInputSplitter -from IPython.core.magic import Magics, magics_class, line_magic -from IPython.lib.clipboard import ClipboardEmpty -from IPython.utils.text import SList, strip_email_quotes -from IPython.utils import py3compat - -def get_pasted_lines(sentinel, l_input=py3compat.input, quiet=False): - """ Yield pasted lines until the user enters the given sentinel value. - """ - if not quiet: - print("Pasting code; enter '%s' alone on the line to stop or use Ctrl-D." \ - % sentinel) - prompt = ":" - else: - prompt = "" - while True: - try: - l = py3compat.str_to_unicode(l_input(prompt)) - if l == sentinel: - return - else: - yield l - except EOFError: - print('<EOF>') - return - - -@magics_class -class TerminalMagics(Magics): - def __init__(self, shell): - super(TerminalMagics, self).__init__(shell) - self.input_splitter = IPythonInputSplitter() - - def store_or_execute(self, block, name): - """ Execute a block, or store it in a variable, per the user's request. - """ - if name: - # If storing it for further editing - self.shell.user_ns[name] = SList(block.splitlines()) - print("Block assigned to '%s'" % name) - else: - b = self.preclean_input(block) - self.shell.user_ns['pasted_block'] = b - self.shell.using_paste_magics = True - try: - self.shell.run_cell(b) - finally: - self.shell.using_paste_magics = False - - def preclean_input(self, block): - lines = block.splitlines() - while lines and not lines[0].strip(): - lines = lines[1:] - return strip_email_quotes('\n'.join(lines)) - - def rerun_pasted(self, name='pasted_block'): - """ Rerun a previously pasted command. - """ - b = self.shell.user_ns.get(name) - - # Sanity checks - if b is None: - raise UsageError('No previous pasted block available') - if not isinstance(b, py3compat.string_types): - raise UsageError( - "Variable 'pasted_block' is not a string, can't execute") - - print("Re-executing '%s...' (%d chars)"% (b.split('\n',1)[0], len(b))) - self.shell.run_cell(b) - - @line_magic - def autoindent(self, parameter_s = ''): +"""Extra magics for terminal use.""" + +# Copyright (c) IPython Development Team. +# Distributed under the terms of the Modified BSD License. + +from __future__ import print_function + +from logging import error +import os +import sys + +from IPython.core.error import TryNext, UsageError +from IPython.core.inputsplitter import IPythonInputSplitter +from IPython.core.magic import Magics, magics_class, line_magic +from IPython.lib.clipboard import ClipboardEmpty +from IPython.utils.text import SList, strip_email_quotes +from IPython.utils import py3compat + +def get_pasted_lines(sentinel, l_input=py3compat.input, quiet=False): + """ Yield pasted lines until the user enters the given sentinel value. + """ + if not quiet: + print("Pasting code; enter '%s' alone on the line to stop or use Ctrl-D." \ + % sentinel) + prompt = ":" + else: + prompt = "" + while True: + try: + l = py3compat.str_to_unicode(l_input(prompt)) + if l == sentinel: + return + else: + yield l + except EOFError: + print('<EOF>') + return + + +@magics_class +class TerminalMagics(Magics): + def __init__(self, shell): + super(TerminalMagics, self).__init__(shell) + self.input_splitter = IPythonInputSplitter() + + def store_or_execute(self, block, name): + """ Execute a block, or store it in a variable, per the user's request. + """ + if name: + # If storing it for further editing + self.shell.user_ns[name] = SList(block.splitlines()) + print("Block assigned to '%s'" % name) + else: + b = self.preclean_input(block) + self.shell.user_ns['pasted_block'] = b + self.shell.using_paste_magics = True + try: + self.shell.run_cell(b) + finally: + self.shell.using_paste_magics = False + + def preclean_input(self, block): + lines = block.splitlines() + while lines and not lines[0].strip(): + lines = lines[1:] + return strip_email_quotes('\n'.join(lines)) + + def rerun_pasted(self, name='pasted_block'): + """ Rerun a previously pasted command. + """ + b = self.shell.user_ns.get(name) + + # Sanity checks + if b is None: + raise UsageError('No previous pasted block available') + if not isinstance(b, py3compat.string_types): + raise UsageError( + "Variable 'pasted_block' is not a string, can't execute") + + print("Re-executing '%s...' (%d chars)"% (b.split('\n',1)[0], len(b))) + self.shell.run_cell(b) + + @line_magic + def autoindent(self, parameter_s = ''): """Toggle autoindent on/off (deprecated)""" print("%autoindent is deprecated since IPython 5: you can now paste " "multiple lines without turning autoindentation off.") - self.shell.set_autoindent() - print("Automatic indentation is:",['OFF','ON'][self.shell.autoindent]) - - @line_magic - def cpaste(self, parameter_s=''): - """Paste & execute a pre-formatted code block from clipboard. - - You must terminate the block with '--' (two minus-signs) or Ctrl-D - alone on the line. You can also provide your own sentinel with '%paste - -s %%' ('%%' is the new sentinel for this operation). - - The block is dedented prior to execution to enable execution of method - definitions. '>' and '+' characters at the beginning of a line are - ignored, to allow pasting directly from e-mails, diff files and - doctests (the '...' continuation prompt is also stripped). The - executed block is also assigned to variable named 'pasted_block' for - later editing with '%edit pasted_block'. - - You can also pass a variable name as an argument, e.g. '%cpaste foo'. - This assigns the pasted block to variable 'foo' as string, without - dedenting or executing it (preceding >>> and + is still stripped) - - '%cpaste -r' re-executes the block previously entered by cpaste. - '%cpaste -q' suppresses any additional output messages. - - Do not be alarmed by garbled output on Windows (it's a readline bug). - Just press enter and type -- (and press enter again) and the block - will be what was just pasted. - - IPython statements (magics, shell escapes) are not supported (yet). - - See also - -------- - paste: automatically pull code from clipboard. - - Examples - -------- - :: - - In [8]: %cpaste - Pasting code; enter '--' alone on the line to stop. - :>>> a = ["world!", "Hello"] - :>>> print " ".join(sorted(a)) - :-- - Hello world! - """ - opts, name = self.parse_options(parameter_s, 'rqs:', mode='string') - if 'r' in opts: - self.rerun_pasted() - return - - quiet = ('q' in opts) - - sentinel = opts.get('s', u'--') - block = '\n'.join(get_pasted_lines(sentinel, quiet=quiet)) - self.store_or_execute(block, name) - - @line_magic - def paste(self, parameter_s=''): - """Paste & execute a pre-formatted code block from clipboard. - - The text is pulled directly from the clipboard without user - intervention and printed back on the screen before execution (unless - the -q flag is given to force quiet mode). - - The block is dedented prior to execution to enable execution of method - definitions. '>' and '+' characters at the beginning of a line are - ignored, to allow pasting directly from e-mails, diff files and - doctests (the '...' continuation prompt is also stripped). The - executed block is also assigned to variable named 'pasted_block' for - later editing with '%edit pasted_block'. - - You can also pass a variable name as an argument, e.g. '%paste foo'. - This assigns the pasted block to variable 'foo' as string, without - executing it (preceding >>> and + is still stripped). - - Options: - - -r: re-executes the block previously entered by cpaste. - - -q: quiet mode: do not echo the pasted text back to the terminal. - - IPython statements (magics, shell escapes) are not supported (yet). - - See also - -------- - cpaste: manually paste code into terminal until you mark its end. - """ - opts, name = self.parse_options(parameter_s, 'rq', mode='string') - if 'r' in opts: - self.rerun_pasted() - return - try: - block = self.shell.hooks.clipboard_get() - except TryNext as clipboard_exc: - message = getattr(clipboard_exc, 'args') - if message: - error(message[0]) - else: - error('Could not get text from the clipboard.') - return - except ClipboardEmpty: - raise UsageError("The clipboard appears to be empty") - - # By default, echo back to terminal unless quiet mode is requested - if 'q' not in opts: - write = self.shell.write - write(self.shell.pycolorize(block)) - if not block.endswith('\n'): - write('\n') - write("## -- End pasted text --\n") - - self.store_or_execute(block, name) - - # Class-level: add a '%cls' magic only on Windows - if sys.platform == 'win32': - @line_magic - def cls(self, s): - """Clear screen. - """ - os.system("cls") + self.shell.set_autoindent() + print("Automatic indentation is:",['OFF','ON'][self.shell.autoindent]) + + @line_magic + def cpaste(self, parameter_s=''): + """Paste & execute a pre-formatted code block from clipboard. + + You must terminate the block with '--' (two minus-signs) or Ctrl-D + alone on the line. You can also provide your own sentinel with '%paste + -s %%' ('%%' is the new sentinel for this operation). + + The block is dedented prior to execution to enable execution of method + definitions. '>' and '+' characters at the beginning of a line are + ignored, to allow pasting directly from e-mails, diff files and + doctests (the '...' continuation prompt is also stripped). The + executed block is also assigned to variable named 'pasted_block' for + later editing with '%edit pasted_block'. + + You can also pass a variable name as an argument, e.g. '%cpaste foo'. + This assigns the pasted block to variable 'foo' as string, without + dedenting or executing it (preceding >>> and + is still stripped) + + '%cpaste -r' re-executes the block previously entered by cpaste. + '%cpaste -q' suppresses any additional output messages. + + Do not be alarmed by garbled output on Windows (it's a readline bug). + Just press enter and type -- (and press enter again) and the block + will be what was just pasted. + + IPython statements (magics, shell escapes) are not supported (yet). + + See also + -------- + paste: automatically pull code from clipboard. + + Examples + -------- + :: + + In [8]: %cpaste + Pasting code; enter '--' alone on the line to stop. + :>>> a = ["world!", "Hello"] + :>>> print " ".join(sorted(a)) + :-- + Hello world! + """ + opts, name = self.parse_options(parameter_s, 'rqs:', mode='string') + if 'r' in opts: + self.rerun_pasted() + return + + quiet = ('q' in opts) + + sentinel = opts.get('s', u'--') + block = '\n'.join(get_pasted_lines(sentinel, quiet=quiet)) + self.store_or_execute(block, name) + + @line_magic + def paste(self, parameter_s=''): + """Paste & execute a pre-formatted code block from clipboard. + + The text is pulled directly from the clipboard without user + intervention and printed back on the screen before execution (unless + the -q flag is given to force quiet mode). + + The block is dedented prior to execution to enable execution of method + definitions. '>' and '+' characters at the beginning of a line are + ignored, to allow pasting directly from e-mails, diff files and + doctests (the '...' continuation prompt is also stripped). The + executed block is also assigned to variable named 'pasted_block' for + later editing with '%edit pasted_block'. + + You can also pass a variable name as an argument, e.g. '%paste foo'. + This assigns the pasted block to variable 'foo' as string, without + executing it (preceding >>> and + is still stripped). + + Options: + + -r: re-executes the block previously entered by cpaste. + + -q: quiet mode: do not echo the pasted text back to the terminal. + + IPython statements (magics, shell escapes) are not supported (yet). + + See also + -------- + cpaste: manually paste code into terminal until you mark its end. + """ + opts, name = self.parse_options(parameter_s, 'rq', mode='string') + if 'r' in opts: + self.rerun_pasted() + return + try: + block = self.shell.hooks.clipboard_get() + except TryNext as clipboard_exc: + message = getattr(clipboard_exc, 'args') + if message: + error(message[0]) + else: + error('Could not get text from the clipboard.') + return + except ClipboardEmpty: + raise UsageError("The clipboard appears to be empty") + + # By default, echo back to terminal unless quiet mode is requested + if 'q' not in opts: + write = self.shell.write + write(self.shell.pycolorize(block)) + if not block.endswith('\n'): + write('\n') + write("## -- End pasted text --\n") + + self.store_or_execute(block, name) + + # Class-level: add a '%cls' magic only on Windows + if sys.platform == 'win32': + @line_magic + def cls(self, s): + """Clear screen. + """ + os.system("cls") diff --git a/contrib/python/ipython/py2/IPython/terminal/prompts.py b/contrib/python/ipython/py2/IPython/terminal/prompts.py index 43c2170503..a2203fe417 100644 --- a/contrib/python/ipython/py2/IPython/terminal/prompts.py +++ b/contrib/python/ipython/py2/IPython/terminal/prompts.py @@ -1,80 +1,80 @@ -"""Terminal input and output prompts.""" -from __future__ import print_function - -from pygments.token import Token -import sys - -from IPython.core.displayhook import DisplayHook - -from prompt_toolkit.layout.utils import token_list_width - -class Prompts(object): - def __init__(self, shell): - self.shell = shell - - def in_prompt_tokens(self, cli=None): - return [ - (Token.Prompt, 'In ['), - (Token.PromptNum, str(self.shell.execution_count)), - (Token.Prompt, ']: '), - ] - - def _width(self): - return token_list_width(self.in_prompt_tokens()) - - def continuation_prompt_tokens(self, cli=None, width=None): - if width is None: - width = self._width() - return [ - (Token.Prompt, (' ' * (width - 5)) + '...: '), - ] - - def rewrite_prompt_tokens(self): - width = self._width() - return [ - (Token.Prompt, ('-' * (width - 2)) + '> '), - ] - - def out_prompt_tokens(self): - return [ - (Token.OutPrompt, 'Out['), - (Token.OutPromptNum, str(self.shell.execution_count)), - (Token.OutPrompt, ']: '), - ] - -class ClassicPrompts(Prompts): - def in_prompt_tokens(self, cli=None): - return [ - (Token.Prompt, '>>> '), - ] - - def continuation_prompt_tokens(self, cli=None, width=None): - return [ - (Token.Prompt, '... ') - ] - - def rewrite_prompt_tokens(self): - return [] - - def out_prompt_tokens(self): - return [] - -class RichPromptDisplayHook(DisplayHook): - """Subclass of base display hook using coloured prompt""" - def write_output_prompt(self): - sys.stdout.write(self.shell.separate_out) +"""Terminal input and output prompts.""" +from __future__ import print_function + +from pygments.token import Token +import sys + +from IPython.core.displayhook import DisplayHook + +from prompt_toolkit.layout.utils import token_list_width + +class Prompts(object): + def __init__(self, shell): + self.shell = shell + + def in_prompt_tokens(self, cli=None): + return [ + (Token.Prompt, 'In ['), + (Token.PromptNum, str(self.shell.execution_count)), + (Token.Prompt, ']: '), + ] + + def _width(self): + return token_list_width(self.in_prompt_tokens()) + + def continuation_prompt_tokens(self, cli=None, width=None): + if width is None: + width = self._width() + return [ + (Token.Prompt, (' ' * (width - 5)) + '...: '), + ] + + def rewrite_prompt_tokens(self): + width = self._width() + return [ + (Token.Prompt, ('-' * (width - 2)) + '> '), + ] + + def out_prompt_tokens(self): + return [ + (Token.OutPrompt, 'Out['), + (Token.OutPromptNum, str(self.shell.execution_count)), + (Token.OutPrompt, ']: '), + ] + +class ClassicPrompts(Prompts): + def in_prompt_tokens(self, cli=None): + return [ + (Token.Prompt, '>>> '), + ] + + def continuation_prompt_tokens(self, cli=None, width=None): + return [ + (Token.Prompt, '... ') + ] + + def rewrite_prompt_tokens(self): + return [] + + def out_prompt_tokens(self): + return [] + +class RichPromptDisplayHook(DisplayHook): + """Subclass of base display hook using coloured prompt""" + def write_output_prompt(self): + sys.stdout.write(self.shell.separate_out) # If we're not displaying a prompt, it effectively ends with a newline, # because the output will be left-aligned. self.prompt_end_newline = True - if self.do_full_cache: - tokens = self.shell.prompts.out_prompt_tokens() + if self.do_full_cache: + tokens = self.shell.prompts.out_prompt_tokens() prompt_txt = ''.join(s for t, s in tokens) if prompt_txt and not prompt_txt.endswith('\n'): # Ask for a newline before multiline output self.prompt_end_newline = False - if self.shell.pt_cli: - self.shell.pt_cli.print_tokens(tokens) - else: + if self.shell.pt_cli: + self.shell.pt_cli.print_tokens(tokens) + else: sys.stdout.write(prompt_txt) diff --git a/contrib/python/ipython/py2/IPython/terminal/pt_inputhooks/__init__.py b/contrib/python/ipython/py2/IPython/terminal/pt_inputhooks/__init__.py index 3766973e82..95fdad0b59 100644 --- a/contrib/python/ipython/py2/IPython/terminal/pt_inputhooks/__init__.py +++ b/contrib/python/ipython/py2/IPython/terminal/pt_inputhooks/__init__.py @@ -1,49 +1,49 @@ -import importlib -import os - -aliases = { - 'qt4': 'qt', - 'gtk2': 'gtk', -} - -backends = [ - 'qt', 'qt4', 'qt5', - 'gtk', 'gtk2', 'gtk3', - 'tk', - 'wx', - 'pyglet', 'glut', - 'osx', -] - -registered = {} - -def register(name, inputhook): - """Register the function *inputhook* as an event loop integration.""" - registered[name] = inputhook - -class UnknownBackend(KeyError): - def __init__(self, name): - self.name = name - - def __str__(self): - return ("No event loop integration for {!r}. " - "Supported event loops are: {}").format(self.name, - ', '.join(backends + sorted(registered))) - +import importlib +import os + +aliases = { + 'qt4': 'qt', + 'gtk2': 'gtk', +} + +backends = [ + 'qt', 'qt4', 'qt5', + 'gtk', 'gtk2', 'gtk3', + 'tk', + 'wx', + 'pyglet', 'glut', + 'osx', +] + +registered = {} + +def register(name, inputhook): + """Register the function *inputhook* as an event loop integration.""" + registered[name] = inputhook + +class UnknownBackend(KeyError): + def __init__(self, name): + self.name = name + + def __str__(self): + return ("No event loop integration for {!r}. " + "Supported event loops are: {}").format(self.name, + ', '.join(backends + sorted(registered))) + def get_inputhook_name_and_func(gui): - if gui in registered: + if gui in registered: return gui, registered[gui] - - if gui not in backends: - raise UnknownBackend(gui) - - if gui in aliases: + + if gui not in backends: + raise UnknownBackend(gui) + + if gui in aliases: return get_inputhook_name_and_func(aliases[gui]) - + gui_mod = gui - if gui == 'qt5': - os.environ['QT_API'] = 'pyqt5' + if gui == 'qt5': + os.environ['QT_API'] = 'pyqt5' gui_mod = 'qt' - + mod = importlib.import_module('IPython.terminal.pt_inputhooks.'+gui_mod) return gui, mod.inputhook diff --git a/contrib/python/ipython/py2/IPython/terminal/pt_inputhooks/glut.py b/contrib/python/ipython/py2/IPython/terminal/pt_inputhooks/glut.py index f336e6830f..d6b1387649 100644 --- a/contrib/python/ipython/py2/IPython/terminal/pt_inputhooks/glut.py +++ b/contrib/python/ipython/py2/IPython/terminal/pt_inputhooks/glut.py @@ -1,141 +1,141 @@ -"""GLUT Input hook for interactive use with prompt_toolkit -""" -from __future__ import print_function - - -# GLUT is quite an old library and it is difficult to ensure proper -# integration within IPython since original GLUT does not allow to handle -# events one by one. Instead, it requires for the mainloop to be entered -# and never returned (there is not even a function to exit he -# mainloop). Fortunately, there are alternatives such as freeglut -# (available for linux and windows) and the OSX implementation gives -# access to a glutCheckLoop() function that blocks itself until a new -# event is received. This means we have to setup the idle callback to -# ensure we got at least one event that will unblock the function. -# -# Furthermore, it is not possible to install these handlers without a window -# being first created. We choose to make this window invisible. This means that -# display mode options are set at this level and user won't be able to change -# them later without modifying the code. This should probably be made available -# via IPython options system. - -import sys -import time -import signal -import OpenGL.GLUT as glut -import OpenGL.platform as platform -from timeit import default_timer as clock - -# Frame per second : 60 -# Should probably be an IPython option -glut_fps = 60 - -# Display mode : double buffeed + rgba + depth -# Should probably be an IPython option -glut_display_mode = (glut.GLUT_DOUBLE | - glut.GLUT_RGBA | - glut.GLUT_DEPTH) - -glutMainLoopEvent = None -if sys.platform == 'darwin': - try: - glutCheckLoop = platform.createBaseFunction( - 'glutCheckLoop', dll=platform.GLUT, resultType=None, - argTypes=[], - doc='glutCheckLoop( ) -> None', - argNames=(), - ) - except AttributeError: - raise RuntimeError( - '''Your glut implementation does not allow interactive sessions''' - '''Consider installing freeglut.''') - glutMainLoopEvent = glutCheckLoop -elif glut.HAVE_FREEGLUT: - glutMainLoopEvent = glut.glutMainLoopEvent -else: - raise RuntimeError( - '''Your glut implementation does not allow interactive sessions. ''' - '''Consider installing freeglut.''') - - -def glut_display(): - # Dummy display function - pass - -def glut_idle(): - # Dummy idle function - pass - -def glut_close(): - # Close function only hides the current window - glut.glutHideWindow() - glutMainLoopEvent() - -def glut_int_handler(signum, frame): - # Catch sigint and print the defaultipyt message - signal.signal(signal.SIGINT, signal.default_int_handler) - print('\nKeyboardInterrupt') - # Need to reprint the prompt at this stage - -# Initialisation code -glut.glutInit( sys.argv ) -glut.glutInitDisplayMode( glut_display_mode ) -# This is specific to freeglut -if bool(glut.glutSetOption): - glut.glutSetOption( glut.GLUT_ACTION_ON_WINDOW_CLOSE, - glut.GLUT_ACTION_GLUTMAINLOOP_RETURNS ) -glut.glutCreateWindow( b'ipython' ) -glut.glutReshapeWindow( 1, 1 ) -glut.glutHideWindow( ) -glut.glutWMCloseFunc( glut_close ) -glut.glutDisplayFunc( glut_display ) -glut.glutIdleFunc( glut_idle ) - - -def inputhook(context): - """Run the pyglet event loop by processing pending events only. - - This keeps processing pending events until stdin is ready. After - processing all pending events, a call to time.sleep is inserted. This is - needed, otherwise, CPU usage is at 100%. This sleep time should be tuned - though for best performance. - """ - # We need to protect against a user pressing Control-C when IPython is - # idle and this is running. We trap KeyboardInterrupt and pass. - - signal.signal(signal.SIGINT, glut_int_handler) - - try: - t = clock() - - # Make sure the default window is set after a window has been closed - if glut.glutGetWindow() == 0: - glut.glutSetWindow( 1 ) - glutMainLoopEvent() - return 0 - - while not context.input_is_ready(): - glutMainLoopEvent() - # We need to sleep at this point to keep the idle CPU load - # low. However, if sleep to long, GUI response is poor. As - # a compromise, we watch how often GUI events are being processed - # and switch between a short and long sleep time. Here are some - # stats useful in helping to tune this. - # time CPU load - # 0.001 13% - # 0.005 3% - # 0.01 1.5% - # 0.05 0.5% - used_time = clock() - t - if used_time > 10.0: - # print 'Sleep for 1 s' # dbg - time.sleep(1.0) - elif used_time > 0.1: - # Few GUI events coming in, so we can sleep longer - # print 'Sleep for 0.05 s' # dbg - time.sleep(0.05) - else: - # Many GUI events coming in, so sleep only very little - time.sleep(0.001) - except KeyboardInterrupt: - pass +"""GLUT Input hook for interactive use with prompt_toolkit +""" +from __future__ import print_function + + +# GLUT is quite an old library and it is difficult to ensure proper +# integration within IPython since original GLUT does not allow to handle +# events one by one. Instead, it requires for the mainloop to be entered +# and never returned (there is not even a function to exit he +# mainloop). Fortunately, there are alternatives such as freeglut +# (available for linux and windows) and the OSX implementation gives +# access to a glutCheckLoop() function that blocks itself until a new +# event is received. This means we have to setup the idle callback to +# ensure we got at least one event that will unblock the function. +# +# Furthermore, it is not possible to install these handlers without a window +# being first created. We choose to make this window invisible. This means that +# display mode options are set at this level and user won't be able to change +# them later without modifying the code. This should probably be made available +# via IPython options system. + +import sys +import time +import signal +import OpenGL.GLUT as glut +import OpenGL.platform as platform +from timeit import default_timer as clock + +# Frame per second : 60 +# Should probably be an IPython option +glut_fps = 60 + +# Display mode : double buffeed + rgba + depth +# Should probably be an IPython option +glut_display_mode = (glut.GLUT_DOUBLE | + glut.GLUT_RGBA | + glut.GLUT_DEPTH) + +glutMainLoopEvent = None +if sys.platform == 'darwin': + try: + glutCheckLoop = platform.createBaseFunction( + 'glutCheckLoop', dll=platform.GLUT, resultType=None, + argTypes=[], + doc='glutCheckLoop( ) -> None', + argNames=(), + ) + except AttributeError: + raise RuntimeError( + '''Your glut implementation does not allow interactive sessions''' + '''Consider installing freeglut.''') + glutMainLoopEvent = glutCheckLoop +elif glut.HAVE_FREEGLUT: + glutMainLoopEvent = glut.glutMainLoopEvent +else: + raise RuntimeError( + '''Your glut implementation does not allow interactive sessions. ''' + '''Consider installing freeglut.''') + + +def glut_display(): + # Dummy display function + pass + +def glut_idle(): + # Dummy idle function + pass + +def glut_close(): + # Close function only hides the current window + glut.glutHideWindow() + glutMainLoopEvent() + +def glut_int_handler(signum, frame): + # Catch sigint and print the defaultipyt message + signal.signal(signal.SIGINT, signal.default_int_handler) + print('\nKeyboardInterrupt') + # Need to reprint the prompt at this stage + +# Initialisation code +glut.glutInit( sys.argv ) +glut.glutInitDisplayMode( glut_display_mode ) +# This is specific to freeglut +if bool(glut.glutSetOption): + glut.glutSetOption( glut.GLUT_ACTION_ON_WINDOW_CLOSE, + glut.GLUT_ACTION_GLUTMAINLOOP_RETURNS ) +glut.glutCreateWindow( b'ipython' ) +glut.glutReshapeWindow( 1, 1 ) +glut.glutHideWindow( ) +glut.glutWMCloseFunc( glut_close ) +glut.glutDisplayFunc( glut_display ) +glut.glutIdleFunc( glut_idle ) + + +def inputhook(context): + """Run the pyglet event loop by processing pending events only. + + This keeps processing pending events until stdin is ready. After + processing all pending events, a call to time.sleep is inserted. This is + needed, otherwise, CPU usage is at 100%. This sleep time should be tuned + though for best performance. + """ + # We need to protect against a user pressing Control-C when IPython is + # idle and this is running. We trap KeyboardInterrupt and pass. + + signal.signal(signal.SIGINT, glut_int_handler) + + try: + t = clock() + + # Make sure the default window is set after a window has been closed + if glut.glutGetWindow() == 0: + glut.glutSetWindow( 1 ) + glutMainLoopEvent() + return 0 + + while not context.input_is_ready(): + glutMainLoopEvent() + # We need to sleep at this point to keep the idle CPU load + # low. However, if sleep to long, GUI response is poor. As + # a compromise, we watch how often GUI events are being processed + # and switch between a short and long sleep time. Here are some + # stats useful in helping to tune this. + # time CPU load + # 0.001 13% + # 0.005 3% + # 0.01 1.5% + # 0.05 0.5% + used_time = clock() - t + if used_time > 10.0: + # print 'Sleep for 1 s' # dbg + time.sleep(1.0) + elif used_time > 0.1: + # Few GUI events coming in, so we can sleep longer + # print 'Sleep for 0.05 s' # dbg + time.sleep(0.05) + else: + # Many GUI events coming in, so sleep only very little + time.sleep(0.001) + except KeyboardInterrupt: + pass diff --git a/contrib/python/ipython/py2/IPython/terminal/pt_inputhooks/gtk.py b/contrib/python/ipython/py2/IPython/terminal/pt_inputhooks/gtk.py index 8f27e12c46..ac7529ca00 100644 --- a/contrib/python/ipython/py2/IPython/terminal/pt_inputhooks/gtk.py +++ b/contrib/python/ipython/py2/IPython/terminal/pt_inputhooks/gtk.py @@ -1,59 +1,59 @@ -# Code borrowed from python-prompt-toolkit examples -# https://github.com/jonathanslenders/python-prompt-toolkit/blob/77cdcfbc7f4b4c34a9d2f9a34d422d7152f16209/examples/inputhook.py - -# Copyright (c) 2014, Jonathan Slenders -# All rights reserved. -# -# Redistribution and use in source and binary forms, with or without modification, -# are permitted provided that the following conditions are met: -# -# * Redistributions of source code must retain the above copyright notice, this -# list of conditions and the following disclaimer. -# -# * Redistributions in binary form must reproduce the above copyright notice, this -# list of conditions and the following disclaimer in the documentation and/or -# other materials provided with the distribution. -# -# * Neither the name of the {organization} nor the names of its -# contributors may be used to endorse or promote products derived from -# this software without specific prior written permission. -# -# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND -# ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED -# WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE -# DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR -# ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES -# (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; -# LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON -# ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS -# SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - -""" -PyGTK input hook for prompt_toolkit. - -Listens on the pipe prompt_toolkit sets up for a notification that it should -return control to the terminal event loop. -""" -from __future__ import absolute_import - -import gtk, gobject - -# Enable threading in GTK. (Otherwise, GTK will keep the GIL.) -gtk.gdk.threads_init() - -def inputhook(context): - """ - When the eventloop of prompt-toolkit is idle, call this inputhook. - - This will run the GTK main loop until the file descriptor - `context.fileno()` becomes ready. - - :param context: An `InputHookContext` instance. - """ - def _main_quit(*a, **kw): - gtk.main_quit() - return False - - gobject.io_add_watch(context.fileno(), gobject.IO_IN, _main_quit) - gtk.main() +# Code borrowed from python-prompt-toolkit examples +# https://github.com/jonathanslenders/python-prompt-toolkit/blob/77cdcfbc7f4b4c34a9d2f9a34d422d7152f16209/examples/inputhook.py + +# Copyright (c) 2014, Jonathan Slenders +# All rights reserved. +# +# Redistribution and use in source and binary forms, with or without modification, +# are permitted provided that the following conditions are met: +# +# * Redistributions of source code must retain the above copyright notice, this +# list of conditions and the following disclaimer. +# +# * Redistributions in binary form must reproduce the above copyright notice, this +# list of conditions and the following disclaimer in the documentation and/or +# other materials provided with the distribution. +# +# * Neither the name of the {organization} nor the names of its +# contributors may be used to endorse or promote products derived from +# this software without specific prior written permission. +# +# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND +# ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +# WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +# DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR +# ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES +# (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; +# LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON +# ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS +# SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +""" +PyGTK input hook for prompt_toolkit. + +Listens on the pipe prompt_toolkit sets up for a notification that it should +return control to the terminal event loop. +""" +from __future__ import absolute_import + +import gtk, gobject + +# Enable threading in GTK. (Otherwise, GTK will keep the GIL.) +gtk.gdk.threads_init() + +def inputhook(context): + """ + When the eventloop of prompt-toolkit is idle, call this inputhook. + + This will run the GTK main loop until the file descriptor + `context.fileno()` becomes ready. + + :param context: An `InputHookContext` instance. + """ + def _main_quit(*a, **kw): + gtk.main_quit() + return False + + gobject.io_add_watch(context.fileno(), gobject.IO_IN, _main_quit) + gtk.main() diff --git a/contrib/python/ipython/py2/IPython/terminal/pt_inputhooks/gtk3.py b/contrib/python/ipython/py2/IPython/terminal/pt_inputhooks/gtk3.py index 5c6c545457..40d6673359 100644 --- a/contrib/python/ipython/py2/IPython/terminal/pt_inputhooks/gtk3.py +++ b/contrib/python/ipython/py2/IPython/terminal/pt_inputhooks/gtk3.py @@ -1,12 +1,12 @@ -"""prompt_toolkit input hook for GTK 3 -""" - -from gi.repository import Gtk, GLib - -def _main_quit(*args, **kwargs): - Gtk.main_quit() - return False - -def inputhook(context): - GLib.io_add_watch(context.fileno(), GLib.IO_IN, _main_quit) - Gtk.main() +"""prompt_toolkit input hook for GTK 3 +""" + +from gi.repository import Gtk, GLib + +def _main_quit(*args, **kwargs): + Gtk.main_quit() + return False + +def inputhook(context): + GLib.io_add_watch(context.fileno(), GLib.IO_IN, _main_quit) + Gtk.main() diff --git a/contrib/python/ipython/py2/IPython/terminal/pt_inputhooks/osx.py b/contrib/python/ipython/py2/IPython/terminal/pt_inputhooks/osx.py index 53f4e3838b..b916ee0540 100644 --- a/contrib/python/ipython/py2/IPython/terminal/pt_inputhooks/osx.py +++ b/contrib/python/ipython/py2/IPython/terminal/pt_inputhooks/osx.py @@ -1,137 +1,137 @@ -"""Inputhook for OS X - -Calls NSApp / CoreFoundation APIs via ctypes. -""" - -# obj-c boilerplate from appnope, used under BSD 2-clause - -import ctypes -import ctypes.util -from threading import Event - -objc = ctypes.cdll.LoadLibrary(ctypes.util.find_library('objc')) - -void_p = ctypes.c_void_p - -objc.objc_getClass.restype = void_p -objc.sel_registerName.restype = void_p -objc.objc_msgSend.restype = void_p -objc.objc_msgSend.argtypes = [void_p, void_p] - -msg = objc.objc_msgSend - -def _utf8(s): - """ensure utf8 bytes""" - if not isinstance(s, bytes): - s = s.encode('utf8') - return s - -def n(name): - """create a selector name (for ObjC methods)""" - return objc.sel_registerName(_utf8(name)) - -def C(classname): - """get an ObjC Class by name""" - return objc.objc_getClass(_utf8(classname)) - -# end obj-c boilerplate from appnope - -# CoreFoundation C-API calls we will use: -CoreFoundation = ctypes.cdll.LoadLibrary(ctypes.util.find_library('CoreFoundation')) - -CFFileDescriptorCreate = CoreFoundation.CFFileDescriptorCreate -CFFileDescriptorCreate.restype = void_p -CFFileDescriptorCreate.argtypes = [void_p, ctypes.c_int, ctypes.c_bool, void_p] - -CFFileDescriptorGetNativeDescriptor = CoreFoundation.CFFileDescriptorGetNativeDescriptor -CFFileDescriptorGetNativeDescriptor.restype = ctypes.c_int -CFFileDescriptorGetNativeDescriptor.argtypes = [void_p] - -CFFileDescriptorEnableCallBacks = CoreFoundation.CFFileDescriptorEnableCallBacks -CFFileDescriptorEnableCallBacks.restype = None -CFFileDescriptorEnableCallBacks.argtypes = [void_p, ctypes.c_ulong] - -CFFileDescriptorCreateRunLoopSource = CoreFoundation.CFFileDescriptorCreateRunLoopSource -CFFileDescriptorCreateRunLoopSource.restype = void_p -CFFileDescriptorCreateRunLoopSource.argtypes = [void_p, void_p, void_p] - -CFRunLoopGetCurrent = CoreFoundation.CFRunLoopGetCurrent -CFRunLoopGetCurrent.restype = void_p - -CFRunLoopAddSource = CoreFoundation.CFRunLoopAddSource -CFRunLoopAddSource.restype = None -CFRunLoopAddSource.argtypes = [void_p, void_p, void_p] - -CFRelease = CoreFoundation.CFRelease -CFRelease.restype = None -CFRelease.argtypes = [void_p] - -CFFileDescriptorInvalidate = CoreFoundation.CFFileDescriptorInvalidate -CFFileDescriptorInvalidate.restype = None -CFFileDescriptorInvalidate.argtypes = [void_p] - -# From CFFileDescriptor.h -kCFFileDescriptorReadCallBack = 1 -kCFRunLoopCommonModes = void_p.in_dll(CoreFoundation, 'kCFRunLoopCommonModes') - - -def _NSApp(): - """Return the global NSApplication instance (NSApp)""" - return msg(C('NSApplication'), n('sharedApplication')) - - -def _wake(NSApp): - """Wake the Application""" - event = msg(C('NSEvent'), - n('otherEventWithType:location:modifierFlags:' - 'timestamp:windowNumber:context:subtype:data1:data2:'), - 15, # Type - 0, # location - 0, # flags - 0, # timestamp - 0, # window - None, # context - 0, # subtype - 0, # data1 - 0, # data2 - ) - msg(NSApp, n('postEvent:atStart:'), void_p(event), True) - - -_triggered = Event() - -def _input_callback(fdref, flags, info): - """Callback to fire when there's input to be read""" - _triggered.set() - CFFileDescriptorInvalidate(fdref) - CFRelease(fdref) - NSApp = _NSApp() - msg(NSApp, n('stop:'), NSApp) - _wake(NSApp) - -_c_callback_func_type = ctypes.CFUNCTYPE(None, void_p, void_p, void_p) -_c_input_callback = _c_callback_func_type(_input_callback) - - -def _stop_on_read(fd): - """Register callback to stop eventloop when there's data on fd""" - _triggered.clear() - fdref = CFFileDescriptorCreate(None, fd, False, _c_input_callback, None) - CFFileDescriptorEnableCallBacks(fdref, kCFFileDescriptorReadCallBack) - source = CFFileDescriptorCreateRunLoopSource(None, fdref, 0) - loop = CFRunLoopGetCurrent() - CFRunLoopAddSource(loop, source, kCFRunLoopCommonModes) - CFRelease(source) - - -def inputhook(context): - """Inputhook for Cocoa (NSApp)""" - NSApp = _NSApp() - _stop_on_read(context.fileno()) - msg(NSApp, n('run')) - if not _triggered.is_set(): - # app closed without firing callback, - # probably due to last window being closed. - # Run the loop manually in this case, - # since there may be events still to process (#9734) - CoreFoundation.CFRunLoopRun() +"""Inputhook for OS X + +Calls NSApp / CoreFoundation APIs via ctypes. +""" + +# obj-c boilerplate from appnope, used under BSD 2-clause + +import ctypes +import ctypes.util +from threading import Event + +objc = ctypes.cdll.LoadLibrary(ctypes.util.find_library('objc')) + +void_p = ctypes.c_void_p + +objc.objc_getClass.restype = void_p +objc.sel_registerName.restype = void_p +objc.objc_msgSend.restype = void_p +objc.objc_msgSend.argtypes = [void_p, void_p] + +msg = objc.objc_msgSend + +def _utf8(s): + """ensure utf8 bytes""" + if not isinstance(s, bytes): + s = s.encode('utf8') + return s + +def n(name): + """create a selector name (for ObjC methods)""" + return objc.sel_registerName(_utf8(name)) + +def C(classname): + """get an ObjC Class by name""" + return objc.objc_getClass(_utf8(classname)) + +# end obj-c boilerplate from appnope + +# CoreFoundation C-API calls we will use: +CoreFoundation = ctypes.cdll.LoadLibrary(ctypes.util.find_library('CoreFoundation')) + +CFFileDescriptorCreate = CoreFoundation.CFFileDescriptorCreate +CFFileDescriptorCreate.restype = void_p +CFFileDescriptorCreate.argtypes = [void_p, ctypes.c_int, ctypes.c_bool, void_p] + +CFFileDescriptorGetNativeDescriptor = CoreFoundation.CFFileDescriptorGetNativeDescriptor +CFFileDescriptorGetNativeDescriptor.restype = ctypes.c_int +CFFileDescriptorGetNativeDescriptor.argtypes = [void_p] + +CFFileDescriptorEnableCallBacks = CoreFoundation.CFFileDescriptorEnableCallBacks +CFFileDescriptorEnableCallBacks.restype = None +CFFileDescriptorEnableCallBacks.argtypes = [void_p, ctypes.c_ulong] + +CFFileDescriptorCreateRunLoopSource = CoreFoundation.CFFileDescriptorCreateRunLoopSource +CFFileDescriptorCreateRunLoopSource.restype = void_p +CFFileDescriptorCreateRunLoopSource.argtypes = [void_p, void_p, void_p] + +CFRunLoopGetCurrent = CoreFoundation.CFRunLoopGetCurrent +CFRunLoopGetCurrent.restype = void_p + +CFRunLoopAddSource = CoreFoundation.CFRunLoopAddSource +CFRunLoopAddSource.restype = None +CFRunLoopAddSource.argtypes = [void_p, void_p, void_p] + +CFRelease = CoreFoundation.CFRelease +CFRelease.restype = None +CFRelease.argtypes = [void_p] + +CFFileDescriptorInvalidate = CoreFoundation.CFFileDescriptorInvalidate +CFFileDescriptorInvalidate.restype = None +CFFileDescriptorInvalidate.argtypes = [void_p] + +# From CFFileDescriptor.h +kCFFileDescriptorReadCallBack = 1 +kCFRunLoopCommonModes = void_p.in_dll(CoreFoundation, 'kCFRunLoopCommonModes') + + +def _NSApp(): + """Return the global NSApplication instance (NSApp)""" + return msg(C('NSApplication'), n('sharedApplication')) + + +def _wake(NSApp): + """Wake the Application""" + event = msg(C('NSEvent'), + n('otherEventWithType:location:modifierFlags:' + 'timestamp:windowNumber:context:subtype:data1:data2:'), + 15, # Type + 0, # location + 0, # flags + 0, # timestamp + 0, # window + None, # context + 0, # subtype + 0, # data1 + 0, # data2 + ) + msg(NSApp, n('postEvent:atStart:'), void_p(event), True) + + +_triggered = Event() + +def _input_callback(fdref, flags, info): + """Callback to fire when there's input to be read""" + _triggered.set() + CFFileDescriptorInvalidate(fdref) + CFRelease(fdref) + NSApp = _NSApp() + msg(NSApp, n('stop:'), NSApp) + _wake(NSApp) + +_c_callback_func_type = ctypes.CFUNCTYPE(None, void_p, void_p, void_p) +_c_input_callback = _c_callback_func_type(_input_callback) + + +def _stop_on_read(fd): + """Register callback to stop eventloop when there's data on fd""" + _triggered.clear() + fdref = CFFileDescriptorCreate(None, fd, False, _c_input_callback, None) + CFFileDescriptorEnableCallBacks(fdref, kCFFileDescriptorReadCallBack) + source = CFFileDescriptorCreateRunLoopSource(None, fdref, 0) + loop = CFRunLoopGetCurrent() + CFRunLoopAddSource(loop, source, kCFRunLoopCommonModes) + CFRelease(source) + + +def inputhook(context): + """Inputhook for Cocoa (NSApp)""" + NSApp = _NSApp() + _stop_on_read(context.fileno()) + msg(NSApp, n('run')) + if not _triggered.is_set(): + # app closed without firing callback, + # probably due to last window being closed. + # Run the loop manually in this case, + # since there may be events still to process (#9734) + CoreFoundation.CFRunLoopRun() diff --git a/contrib/python/ipython/py2/IPython/terminal/pt_inputhooks/pyglet.py b/contrib/python/ipython/py2/IPython/terminal/pt_inputhooks/pyglet.py index 1c5ec44250..4fbf790b57 100644 --- a/contrib/python/ipython/py2/IPython/terminal/pt_inputhooks/pyglet.py +++ b/contrib/python/ipython/py2/IPython/terminal/pt_inputhooks/pyglet.py @@ -1,68 +1,68 @@ -"""Enable pyglet to be used interacively with prompt_toolkit -""" -from __future__ import absolute_import - -import os -import sys -import time -from timeit import default_timer as clock -import pyglet - -# On linux only, window.flip() has a bug that causes an AttributeError on -# window close. For details, see: -# http://groups.google.com/group/pyglet-users/browse_thread/thread/47c1aab9aa4a3d23/c22f9e819826799e?#c22f9e819826799e - -if sys.platform.startswith('linux'): - def flip(window): - try: - window.flip() - except AttributeError: - pass -else: - def flip(window): - window.flip() - - -def inputhook(context): - """Run the pyglet event loop by processing pending events only. - - This keeps processing pending events until stdin is ready. After - processing all pending events, a call to time.sleep is inserted. This is - needed, otherwise, CPU usage is at 100%. This sleep time should be tuned - though for best performance. - """ - # We need to protect against a user pressing Control-C when IPython is - # idle and this is running. We trap KeyboardInterrupt and pass. - try: - t = clock() - while not context.input_is_ready(): - pyglet.clock.tick() - for window in pyglet.app.windows: - window.switch_to() - window.dispatch_events() - window.dispatch_event('on_draw') - flip(window) - - # We need to sleep at this point to keep the idle CPU load - # low. However, if sleep to long, GUI response is poor. As - # a compromise, we watch how often GUI events are being processed - # and switch between a short and long sleep time. Here are some - # stats useful in helping to tune this. - # time CPU load - # 0.001 13% - # 0.005 3% - # 0.01 1.5% - # 0.05 0.5% - used_time = clock() - t - if used_time > 10.0: - # print 'Sleep for 1 s' # dbg - time.sleep(1.0) - elif used_time > 0.1: - # Few GUI events coming in, so we can sleep longer - # print 'Sleep for 0.05 s' # dbg - time.sleep(0.05) - else: - # Many GUI events coming in, so sleep only very little - time.sleep(0.001) - except KeyboardInterrupt: - pass +"""Enable pyglet to be used interacively with prompt_toolkit +""" +from __future__ import absolute_import + +import os +import sys +import time +from timeit import default_timer as clock +import pyglet + +# On linux only, window.flip() has a bug that causes an AttributeError on +# window close. For details, see: +# http://groups.google.com/group/pyglet-users/browse_thread/thread/47c1aab9aa4a3d23/c22f9e819826799e?#c22f9e819826799e + +if sys.platform.startswith('linux'): + def flip(window): + try: + window.flip() + except AttributeError: + pass +else: + def flip(window): + window.flip() + + +def inputhook(context): + """Run the pyglet event loop by processing pending events only. + + This keeps processing pending events until stdin is ready. After + processing all pending events, a call to time.sleep is inserted. This is + needed, otherwise, CPU usage is at 100%. This sleep time should be tuned + though for best performance. + """ + # We need to protect against a user pressing Control-C when IPython is + # idle and this is running. We trap KeyboardInterrupt and pass. + try: + t = clock() + while not context.input_is_ready(): + pyglet.clock.tick() + for window in pyglet.app.windows: + window.switch_to() + window.dispatch_events() + window.dispatch_event('on_draw') + flip(window) + + # We need to sleep at this point to keep the idle CPU load + # low. However, if sleep to long, GUI response is poor. As + # a compromise, we watch how often GUI events are being processed + # and switch between a short and long sleep time. Here are some + # stats useful in helping to tune this. + # time CPU load + # 0.001 13% + # 0.005 3% + # 0.01 1.5% + # 0.05 0.5% + used_time = clock() - t + if used_time > 10.0: + # print 'Sleep for 1 s' # dbg + time.sleep(1.0) + elif used_time > 0.1: + # Few GUI events coming in, so we can sleep longer + # print 'Sleep for 0.05 s' # dbg + time.sleep(0.05) + else: + # Many GUI events coming in, so sleep only very little + time.sleep(0.001) + except KeyboardInterrupt: + pass diff --git a/contrib/python/ipython/py2/IPython/terminal/pt_inputhooks/qt.py b/contrib/python/ipython/py2/IPython/terminal/pt_inputhooks/qt.py index 7395ac39eb..5667cd8478 100644 --- a/contrib/python/ipython/py2/IPython/terminal/pt_inputhooks/qt.py +++ b/contrib/python/ipython/py2/IPython/terminal/pt_inputhooks/qt.py @@ -1,16 +1,16 @@ -import sys +import sys import os -from IPython.external.qt_for_kernel import QtCore, QtGui - -# If we create a QApplication, keep a reference to it so that it doesn't get -# garbage collected. -_appref = None +from IPython.external.qt_for_kernel import QtCore, QtGui + +# If we create a QApplication, keep a reference to it so that it doesn't get +# garbage collected. +_appref = None _already_warned = False - -def inputhook(context): - global _appref - app = QtCore.QCoreApplication.instance() - if not app: + +def inputhook(context): + global _appref + app = QtCore.QCoreApplication.instance() + if not app: if sys.platform == 'linux': if not os.environ.get('DISPLAY') \ and not os.environ.get('WAYLAND_DISPLAY'): @@ -24,26 +24,26 @@ def inputhook(context): 'variable. Deactivate Qt5 code.' ) return - _appref = app = QtGui.QApplication([" "]) - event_loop = QtCore.QEventLoop(app) - - if sys.platform == 'win32': - # The QSocketNotifier method doesn't appear to work on Windows. - # Use polling instead. - timer = QtCore.QTimer() - timer.timeout.connect(event_loop.quit) - while not context.input_is_ready(): - timer.start(50) # 50 ms - event_loop.exec_() - timer.stop() - else: - # On POSIX platforms, we can use a file descriptor to quit the event - # loop when there is input ready to read. + _appref = app = QtGui.QApplication([" "]) + event_loop = QtCore.QEventLoop(app) + + if sys.platform == 'win32': + # The QSocketNotifier method doesn't appear to work on Windows. + # Use polling instead. + timer = QtCore.QTimer() + timer.timeout.connect(event_loop.quit) + while not context.input_is_ready(): + timer.start(50) # 50 ms + event_loop.exec_() + timer.stop() + else: + # On POSIX platforms, we can use a file descriptor to quit the event + # loop when there is input ready to read. notifier = QtCore.QSocketNotifier(context.fileno(), QtCore.QSocketNotifier.Read) # connect the callback we care about before we turn it on notifier.activated.connect(event_loop.exit) - notifier.setEnabled(True) + notifier.setEnabled(True) # only start the event loop we are not already flipped if not context.input_is_ready(): event_loop.exec_() diff --git a/contrib/python/ipython/py2/IPython/terminal/pt_inputhooks/tk.py b/contrib/python/ipython/py2/IPython/terminal/pt_inputhooks/tk.py index db205b0d2c..7d13001a65 100644 --- a/contrib/python/ipython/py2/IPython/terminal/pt_inputhooks/tk.py +++ b/contrib/python/ipython/py2/IPython/terminal/pt_inputhooks/tk.py @@ -1,95 +1,95 @@ -# Code borrowed from ptpython -# https://github.com/jonathanslenders/ptpython/blob/86b71a89626114b18898a0af463978bdb32eeb70/ptpython/eventloop.py - -# Copyright (c) 2015, Jonathan Slenders -# All rights reserved. -# -# Redistribution and use in source and binary forms, with or without modification, -# are permitted provided that the following conditions are met: -# -# * Redistributions of source code must retain the above copyright notice, this -# list of conditions and the following disclaimer. -# -# * Redistributions in binary form must reproduce the above copyright notice, this -# list of conditions and the following disclaimer in the documentation and/or -# other materials provided with the distribution. -# -# * Neither the name of the {organization} nor the names of its -# contributors may be used to endorse or promote products derived from -# this software without specific prior written permission. -# -# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND -# ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED -# WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE -# DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR -# ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES -# (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; -# LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON -# ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS -# SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - -""" -Wrapper around the eventloop that gives some time to the Tkinter GUI to process -events when it's loaded and while we are waiting for input at the REPL. This -way we don't block the UI of for instance ``turtle`` and other Tk libraries. - -(Normally Tkinter registeres it's callbacks in ``PyOS_InputHook`` to integrate -in readline. ``prompt-toolkit`` doesn't understand that input hook, but this -will fix it for Tk.) -""" -import time - -from IPython.utils.py3compat import PY3 - -import _tkinter -if PY3: - import tkinter -else: - import Tkinter as tkinter # Python 2 - -def inputhook(inputhook_context): - """ - Inputhook for Tk. - Run the Tk eventloop until prompt-toolkit needs to process the next input. - """ - # Get the current TK application. - root = tkinter._default_root - - def wait_using_filehandler(): - """ - Run the TK eventloop until the file handler that we got from the - inputhook becomes readable. - """ - # Add a handler that sets the stop flag when `prompt-toolkit` has input - # to process. - stop = [False] - def done(*a): - stop[0] = True - - root.createfilehandler(inputhook_context.fileno(), _tkinter.READABLE, done) - - # Run the TK event loop as long as we don't receive input. - while root.dooneevent(_tkinter.ALL_EVENTS): - if stop[0]: - break - - root.deletefilehandler(inputhook_context.fileno()) - - def wait_using_polling(): - """ - Windows TK doesn't support 'createfilehandler'. - So, run the TK eventloop and poll until input is ready. - """ - while not inputhook_context.input_is_ready(): - while root.dooneevent(_tkinter.ALL_EVENTS | _tkinter.DONT_WAIT): - pass - # Sleep to make the CPU idle, but not too long, so that the UI - # stays responsive. - time.sleep(.01) - - if root is not None: - if hasattr(root, 'createfilehandler'): - wait_using_filehandler() - else: - wait_using_polling() +# Code borrowed from ptpython +# https://github.com/jonathanslenders/ptpython/blob/86b71a89626114b18898a0af463978bdb32eeb70/ptpython/eventloop.py + +# Copyright (c) 2015, Jonathan Slenders +# All rights reserved. +# +# Redistribution and use in source and binary forms, with or without modification, +# are permitted provided that the following conditions are met: +# +# * Redistributions of source code must retain the above copyright notice, this +# list of conditions and the following disclaimer. +# +# * Redistributions in binary form must reproduce the above copyright notice, this +# list of conditions and the following disclaimer in the documentation and/or +# other materials provided with the distribution. +# +# * Neither the name of the {organization} nor the names of its +# contributors may be used to endorse or promote products derived from +# this software without specific prior written permission. +# +# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND +# ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +# WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +# DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR +# ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES +# (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; +# LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON +# ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS +# SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +""" +Wrapper around the eventloop that gives some time to the Tkinter GUI to process +events when it's loaded and while we are waiting for input at the REPL. This +way we don't block the UI of for instance ``turtle`` and other Tk libraries. + +(Normally Tkinter registeres it's callbacks in ``PyOS_InputHook`` to integrate +in readline. ``prompt-toolkit`` doesn't understand that input hook, but this +will fix it for Tk.) +""" +import time + +from IPython.utils.py3compat import PY3 + +import _tkinter +if PY3: + import tkinter +else: + import Tkinter as tkinter # Python 2 + +def inputhook(inputhook_context): + """ + Inputhook for Tk. + Run the Tk eventloop until prompt-toolkit needs to process the next input. + """ + # Get the current TK application. + root = tkinter._default_root + + def wait_using_filehandler(): + """ + Run the TK eventloop until the file handler that we got from the + inputhook becomes readable. + """ + # Add a handler that sets the stop flag when `prompt-toolkit` has input + # to process. + stop = [False] + def done(*a): + stop[0] = True + + root.createfilehandler(inputhook_context.fileno(), _tkinter.READABLE, done) + + # Run the TK event loop as long as we don't receive input. + while root.dooneevent(_tkinter.ALL_EVENTS): + if stop[0]: + break + + root.deletefilehandler(inputhook_context.fileno()) + + def wait_using_polling(): + """ + Windows TK doesn't support 'createfilehandler'. + So, run the TK eventloop and poll until input is ready. + """ + while not inputhook_context.input_is_ready(): + while root.dooneevent(_tkinter.ALL_EVENTS | _tkinter.DONT_WAIT): + pass + # Sleep to make the CPU idle, but not too long, so that the UI + # stays responsive. + time.sleep(.01) + + if root is not None: + if hasattr(root, 'createfilehandler'): + wait_using_filehandler() + else: + wait_using_polling() diff --git a/contrib/python/ipython/py2/IPython/terminal/pt_inputhooks/wx.py b/contrib/python/ipython/py2/IPython/terminal/pt_inputhooks/wx.py index 4371b21cb4..6dde092500 100644 --- a/contrib/python/ipython/py2/IPython/terminal/pt_inputhooks/wx.py +++ b/contrib/python/ipython/py2/IPython/terminal/pt_inputhooks/wx.py @@ -1,148 +1,148 @@ -"""Enable wxPython to be used interacively in prompt_toolkit -""" -from __future__ import absolute_import - -import sys -import signal -import time -from timeit import default_timer as clock -import wx - - -def inputhook_wx1(context): - """Run the wx event loop by processing pending events only. - - This approach seems to work, but its performance is not great as it - relies on having PyOS_InputHook called regularly. - """ - try: - app = wx.GetApp() - if app is not None: - assert wx.Thread_IsMain() - - # Make a temporary event loop and process system events until - # there are no more waiting, then allow idle events (which - # will also deal with pending or posted wx events.) - evtloop = wx.EventLoop() - ea = wx.EventLoopActivator(evtloop) - while evtloop.Pending(): - evtloop.Dispatch() - app.ProcessIdle() - del ea - except KeyboardInterrupt: - pass - return 0 - -class EventLoopTimer(wx.Timer): - - def __init__(self, func): - self.func = func - wx.Timer.__init__(self) - - def Notify(self): - self.func() - -class EventLoopRunner(object): - - def Run(self, time, input_is_ready): - self.input_is_ready = input_is_ready - self.evtloop = wx.EventLoop() - self.timer = EventLoopTimer(self.check_stdin) - self.timer.Start(time) - self.evtloop.Run() - - def check_stdin(self): - if self.input_is_ready(): - self.timer.Stop() - self.evtloop.Exit() - -def inputhook_wx2(context): - """Run the wx event loop, polling for stdin. - - This version runs the wx eventloop for an undetermined amount of time, - during which it periodically checks to see if anything is ready on - stdin. If anything is ready on stdin, the event loop exits. - - The argument to elr.Run controls how often the event loop looks at stdin. - This determines the responsiveness at the keyboard. A setting of 1000 - enables a user to type at most 1 char per second. I have found that a - setting of 10 gives good keyboard response. We can shorten it further, - but eventually performance would suffer from calling select/kbhit too - often. - """ - try: - app = wx.GetApp() - if app is not None: - assert wx.Thread_IsMain() - elr = EventLoopRunner() - # As this time is made shorter, keyboard response improves, but idle - # CPU load goes up. 10 ms seems like a good compromise. - elr.Run(time=10, # CHANGE time here to control polling interval - input_is_ready=context.input_is_ready) - except KeyboardInterrupt: - pass - return 0 - -def inputhook_wx3(context): - """Run the wx event loop by processing pending events only. - - This is like inputhook_wx1, but it keeps processing pending events - until stdin is ready. After processing all pending events, a call to - time.sleep is inserted. This is needed, otherwise, CPU usage is at 100%. - This sleep time should be tuned though for best performance. - """ - # We need to protect against a user pressing Control-C when IPython is - # idle and this is running. We trap KeyboardInterrupt and pass. - try: - app = wx.GetApp() - if app is not None: - assert wx.Thread_IsMain() - - # The import of wx on Linux sets the handler for signal.SIGINT - # to 0. This is a bug in wx or gtk. We fix by just setting it - # back to the Python default. - if not callable(signal.getsignal(signal.SIGINT)): - signal.signal(signal.SIGINT, signal.default_int_handler) - - evtloop = wx.EventLoop() - ea = wx.EventLoopActivator(evtloop) - t = clock() - while not context.input_is_ready(): - while evtloop.Pending(): - t = clock() - evtloop.Dispatch() - app.ProcessIdle() - # We need to sleep at this point to keep the idle CPU load - # low. However, if sleep to long, GUI response is poor. As - # a compromise, we watch how often GUI events are being processed - # and switch between a short and long sleep time. Here are some - # stats useful in helping to tune this. - # time CPU load - # 0.001 13% - # 0.005 3% - # 0.01 1.5% - # 0.05 0.5% - used_time = clock() - t - if used_time > 10.0: - # print 'Sleep for 1 s' # dbg - time.sleep(1.0) - elif used_time > 0.1: - # Few GUI events coming in, so we can sleep longer - # print 'Sleep for 0.05 s' # dbg - time.sleep(0.05) - else: - # Many GUI events coming in, so sleep only very little - time.sleep(0.001) - del ea - except KeyboardInterrupt: - pass - return 0 - -if sys.platform == 'darwin': - # On OSX, evtloop.Pending() always returns True, regardless of there being - # any events pending. As such we can't use implementations 1 or 3 of the - # inputhook as those depend on a pending/dispatch loop. - inputhook = inputhook_wx2 -else: - # This is our default implementation - inputhook = inputhook_wx3 +"""Enable wxPython to be used interacively in prompt_toolkit +""" +from __future__ import absolute_import + +import sys +import signal +import time +from timeit import default_timer as clock +import wx + + +def inputhook_wx1(context): + """Run the wx event loop by processing pending events only. + + This approach seems to work, but its performance is not great as it + relies on having PyOS_InputHook called regularly. + """ + try: + app = wx.GetApp() + if app is not None: + assert wx.Thread_IsMain() + + # Make a temporary event loop and process system events until + # there are no more waiting, then allow idle events (which + # will also deal with pending or posted wx events.) + evtloop = wx.EventLoop() + ea = wx.EventLoopActivator(evtloop) + while evtloop.Pending(): + evtloop.Dispatch() + app.ProcessIdle() + del ea + except KeyboardInterrupt: + pass + return 0 + +class EventLoopTimer(wx.Timer): + + def __init__(self, func): + self.func = func + wx.Timer.__init__(self) + + def Notify(self): + self.func() + +class EventLoopRunner(object): + + def Run(self, time, input_is_ready): + self.input_is_ready = input_is_ready + self.evtloop = wx.EventLoop() + self.timer = EventLoopTimer(self.check_stdin) + self.timer.Start(time) + self.evtloop.Run() + + def check_stdin(self): + if self.input_is_ready(): + self.timer.Stop() + self.evtloop.Exit() + +def inputhook_wx2(context): + """Run the wx event loop, polling for stdin. + + This version runs the wx eventloop for an undetermined amount of time, + during which it periodically checks to see if anything is ready on + stdin. If anything is ready on stdin, the event loop exits. + + The argument to elr.Run controls how often the event loop looks at stdin. + This determines the responsiveness at the keyboard. A setting of 1000 + enables a user to type at most 1 char per second. I have found that a + setting of 10 gives good keyboard response. We can shorten it further, + but eventually performance would suffer from calling select/kbhit too + often. + """ + try: + app = wx.GetApp() + if app is not None: + assert wx.Thread_IsMain() + elr = EventLoopRunner() + # As this time is made shorter, keyboard response improves, but idle + # CPU load goes up. 10 ms seems like a good compromise. + elr.Run(time=10, # CHANGE time here to control polling interval + input_is_ready=context.input_is_ready) + except KeyboardInterrupt: + pass + return 0 + +def inputhook_wx3(context): + """Run the wx event loop by processing pending events only. + + This is like inputhook_wx1, but it keeps processing pending events + until stdin is ready. After processing all pending events, a call to + time.sleep is inserted. This is needed, otherwise, CPU usage is at 100%. + This sleep time should be tuned though for best performance. + """ + # We need to protect against a user pressing Control-C when IPython is + # idle and this is running. We trap KeyboardInterrupt and pass. + try: + app = wx.GetApp() + if app is not None: + assert wx.Thread_IsMain() + + # The import of wx on Linux sets the handler for signal.SIGINT + # to 0. This is a bug in wx or gtk. We fix by just setting it + # back to the Python default. + if not callable(signal.getsignal(signal.SIGINT)): + signal.signal(signal.SIGINT, signal.default_int_handler) + + evtloop = wx.EventLoop() + ea = wx.EventLoopActivator(evtloop) + t = clock() + while not context.input_is_ready(): + while evtloop.Pending(): + t = clock() + evtloop.Dispatch() + app.ProcessIdle() + # We need to sleep at this point to keep the idle CPU load + # low. However, if sleep to long, GUI response is poor. As + # a compromise, we watch how often GUI events are being processed + # and switch between a short and long sleep time. Here are some + # stats useful in helping to tune this. + # time CPU load + # 0.001 13% + # 0.005 3% + # 0.01 1.5% + # 0.05 0.5% + used_time = clock() - t + if used_time > 10.0: + # print 'Sleep for 1 s' # dbg + time.sleep(1.0) + elif used_time > 0.1: + # Few GUI events coming in, so we can sleep longer + # print 'Sleep for 0.05 s' # dbg + time.sleep(0.05) + else: + # Many GUI events coming in, so sleep only very little + time.sleep(0.001) + del ea + except KeyboardInterrupt: + pass + return 0 + +if sys.platform == 'darwin': + # On OSX, evtloop.Pending() always returns True, regardless of there being + # any events pending. As such we can't use implementations 1 or 3 of the + # inputhook as those depend on a pending/dispatch loop. + inputhook = inputhook_wx2 +else: + # This is our default implementation + inputhook = inputhook_wx3 diff --git a/contrib/python/ipython/py2/IPython/terminal/ptshell.py b/contrib/python/ipython/py2/IPython/terminal/ptshell.py index 666d3c5b51..aad111b041 100644 --- a/contrib/python/ipython/py2/IPython/terminal/ptshell.py +++ b/contrib/python/ipython/py2/IPython/terminal/ptshell.py @@ -1,8 +1,8 @@ -raise DeprecationWarning("""DEPRECATED: - -After Popular request and decision from the BDFL: -`IPython.terminal.ptshell` has been moved back to `IPython.terminal.interactiveshell` -during the beta cycle (after IPython 5.0.beta3) Sorry about that. - -This file will be removed in 5.0 rc or final. -""") +raise DeprecationWarning("""DEPRECATED: + +After Popular request and decision from the BDFL: +`IPython.terminal.ptshell` has been moved back to `IPython.terminal.interactiveshell` +during the beta cycle (after IPython 5.0.beta3) Sorry about that. + +This file will be removed in 5.0 rc or final. +""") diff --git a/contrib/python/ipython/py2/IPython/terminal/ptutils.py b/contrib/python/ipython/py2/IPython/terminal/ptutils.py index c9ff705642..90def9d209 100644 --- a/contrib/python/ipython/py2/IPython/terminal/ptutils.py +++ b/contrib/python/ipython/py2/IPython/terminal/ptutils.py @@ -1,47 +1,47 @@ -"""prompt-toolkit utilities - -Everything in this module is a private API, -not to be used outside IPython. -""" - -# Copyright (c) IPython Development Team. -# Distributed under the terms of the Modified BSD License. - -import unicodedata -from wcwidth import wcwidth - -from IPython.utils.py3compat import PY3 - -from IPython.core.completer import IPCompleter -from prompt_toolkit.completion import Completer, Completion -from prompt_toolkit.layout.lexers import Lexer -from prompt_toolkit.layout.lexers import PygmentsLexer - -import pygments.lexers as pygments_lexers - - -class IPythonPTCompleter(Completer): - """Adaptor to provide IPython completions to prompt_toolkit""" +"""prompt-toolkit utilities + +Everything in this module is a private API, +not to be used outside IPython. +""" + +# Copyright (c) IPython Development Team. +# Distributed under the terms of the Modified BSD License. + +import unicodedata +from wcwidth import wcwidth + +from IPython.utils.py3compat import PY3 + +from IPython.core.completer import IPCompleter +from prompt_toolkit.completion import Completer, Completion +from prompt_toolkit.layout.lexers import Lexer +from prompt_toolkit.layout.lexers import PygmentsLexer + +import pygments.lexers as pygments_lexers + + +class IPythonPTCompleter(Completer): + """Adaptor to provide IPython completions to prompt_toolkit""" def __init__(self, ipy_completer=None, shell=None, patch_stdout=None): - if shell is None and ipy_completer is None: - raise TypeError("Please pass shell=an InteractiveShell instance.") - self._ipy_completer = ipy_completer - self.shell = shell + if shell is None and ipy_completer is None: + raise TypeError("Please pass shell=an InteractiveShell instance.") + self._ipy_completer = ipy_completer + self.shell = shell if patch_stdout is None: raise TypeError("Please pass patch_stdout") self.patch_stdout = patch_stdout - - @property - def ipy_completer(self): - if self._ipy_completer: - return self._ipy_completer - else: - return self.shell.Completer - - def get_completions(self, document, complete_event): - if not document.current_line.strip(): - return - + + @property + def ipy_completer(self): + if self._ipy_completer: + return self._ipy_completer + else: + return self.shell.Completer + + def get_completions(self, document, complete_event): + if not document.current_line.strip(): + return + # Some bits of our completion system may print stuff (e.g. if a module # is imported). This context manager ensures that doesn't interfere with # the prompt. @@ -50,66 +50,66 @@ class IPythonPTCompleter(Completer): line_buffer=document.current_line, cursor_pos=document.cursor_position_col ) - start_pos = -len(used) - for m in matches: - if not m: - # Guard against completion machinery giving us an empty string. - continue - - m = unicodedata.normalize('NFC', m) - - # When the first character of the completion has a zero length, - # then it's probably a decomposed unicode character. E.g. caused by - # the "\dot" completion. Try to compose again with the previous - # character. - if wcwidth(m[0]) == 0: - if document.cursor_position + start_pos > 0: - char_before = document.text[document.cursor_position + start_pos - 1] - m = unicodedata.normalize('NFC', char_before + m) - - # Yield the modified completion instead, if this worked. - if wcwidth(m[0:1]) == 1: - yield Completion(m, start_position=start_pos - 1) - continue - - # TODO: Use Jedi to determine meta_text - # (Jedi currently has a bug that results in incorrect information.) - # meta_text = '' - # yield Completion(m, start_position=start_pos, - # display_meta=meta_text) - yield Completion(m, start_position=start_pos) - -class IPythonPTLexer(Lexer): - """ - Wrapper around PythonLexer and BashLexer. - """ - def __init__(self): - l = pygments_lexers - self.python_lexer = PygmentsLexer(l.Python3Lexer if PY3 else l.PythonLexer) - self.shell_lexer = PygmentsLexer(l.BashLexer) - - self.magic_lexers = { - 'HTML': PygmentsLexer(l.HtmlLexer), - 'html': PygmentsLexer(l.HtmlLexer), - 'javascript': PygmentsLexer(l.JavascriptLexer), - 'js': PygmentsLexer(l.JavascriptLexer), - 'perl': PygmentsLexer(l.PerlLexer), - 'ruby': PygmentsLexer(l.RubyLexer), - 'latex': PygmentsLexer(l.TexLexer), - } - - def lex_document(self, cli, document): - text = document.text.lstrip() - - lexer = self.python_lexer - - if text.startswith('!') or text.startswith('%%bash'): - lexer = self.shell_lexer - - elif text.startswith('%%'): - for magic, l in self.magic_lexers.items(): - if text.startswith('%%' + magic): - lexer = l - break - - return lexer.lex_document(cli, document) + start_pos = -len(used) + for m in matches: + if not m: + # Guard against completion machinery giving us an empty string. + continue + + m = unicodedata.normalize('NFC', m) + + # When the first character of the completion has a zero length, + # then it's probably a decomposed unicode character. E.g. caused by + # the "\dot" completion. Try to compose again with the previous + # character. + if wcwidth(m[0]) == 0: + if document.cursor_position + start_pos > 0: + char_before = document.text[document.cursor_position + start_pos - 1] + m = unicodedata.normalize('NFC', char_before + m) + + # Yield the modified completion instead, if this worked. + if wcwidth(m[0:1]) == 1: + yield Completion(m, start_position=start_pos - 1) + continue + + # TODO: Use Jedi to determine meta_text + # (Jedi currently has a bug that results in incorrect information.) + # meta_text = '' + # yield Completion(m, start_position=start_pos, + # display_meta=meta_text) + yield Completion(m, start_position=start_pos) + +class IPythonPTLexer(Lexer): + """ + Wrapper around PythonLexer and BashLexer. + """ + def __init__(self): + l = pygments_lexers + self.python_lexer = PygmentsLexer(l.Python3Lexer if PY3 else l.PythonLexer) + self.shell_lexer = PygmentsLexer(l.BashLexer) + + self.magic_lexers = { + 'HTML': PygmentsLexer(l.HtmlLexer), + 'html': PygmentsLexer(l.HtmlLexer), + 'javascript': PygmentsLexer(l.JavascriptLexer), + 'js': PygmentsLexer(l.JavascriptLexer), + 'perl': PygmentsLexer(l.PerlLexer), + 'ruby': PygmentsLexer(l.RubyLexer), + 'latex': PygmentsLexer(l.TexLexer), + } + + def lex_document(self, cli, document): + text = document.text.lstrip() + + lexer = self.python_lexer + + if text.startswith('!') or text.startswith('%%bash'): + lexer = self.shell_lexer + + elif text.startswith('%%'): + for magic, l in self.magic_lexers.items(): + if text.startswith('%%' + magic): + lexer = l + break + + return lexer.lex_document(cli, document) diff --git a/contrib/python/ipython/py2/IPython/terminal/shortcuts.py b/contrib/python/ipython/py2/IPython/terminal/shortcuts.py index 8f0ae43e84..2769cf8e8e 100644 --- a/contrib/python/ipython/py2/IPython/terminal/shortcuts.py +++ b/contrib/python/ipython/py2/IPython/terminal/shortcuts.py @@ -1,101 +1,101 @@ -import signal -import sys - -from prompt_toolkit.enums import DEFAULT_BUFFER, SEARCH_BUFFER -from prompt_toolkit.filters import (HasFocus, HasSelection, Condition, - ViInsertMode, EmacsInsertMode, HasCompletions) -from prompt_toolkit.filters.cli import ViMode -from prompt_toolkit.keys import Keys -from prompt_toolkit.key_binding.bindings.completion import display_completions_like_readline - -from IPython.utils.decorators import undoc - -@Condition -def cursor_in_leading_ws(cli): - before = cli.application.buffer.document.current_line_before_cursor - return (not before) or before.isspace() - -def register_ipython_shortcuts(registry, shell): - """Set up the prompt_toolkit keyboard shortcuts for IPython""" - insert_mode = ViInsertMode() | EmacsInsertMode() - - # Ctrl+J == Enter, seemingly - registry.add_binding(Keys.ControlJ, - filter=(HasFocus(DEFAULT_BUFFER) - & ~HasSelection() - & insert_mode - ))(newline_or_execute_outer(shell)) - - registry.add_binding(Keys.ControlBackslash)(force_exit) - - registry.add_binding(Keys.ControlP, - filter=(ViInsertMode() & HasFocus(DEFAULT_BUFFER) - ))(previous_history_or_previous_completion) - - registry.add_binding(Keys.ControlN, - filter=(ViInsertMode() & HasFocus(DEFAULT_BUFFER) - ))(next_history_or_next_completion) - - registry.add_binding(Keys.ControlG, - filter=(HasFocus(DEFAULT_BUFFER) & HasCompletions() - ))(dismiss_completion) - - registry.add_binding(Keys.ControlC, filter=HasFocus(DEFAULT_BUFFER) - )(reset_buffer) - - registry.add_binding(Keys.ControlC, filter=HasFocus(SEARCH_BUFFER) - )(reset_search_buffer) - - supports_suspend = Condition(lambda cli: hasattr(signal, 'SIGTSTP')) - registry.add_binding(Keys.ControlZ, filter=supports_suspend - )(suspend_to_bg) - - # Ctrl+I == Tab - registry.add_binding(Keys.ControlI, - filter=(HasFocus(DEFAULT_BUFFER) - & ~HasSelection() - & insert_mode - & cursor_in_leading_ws - ))(indent_buffer) - - registry.add_binding(Keys.ControlO, - filter=(HasFocus(DEFAULT_BUFFER) - & EmacsInsertMode()))(newline_with_copy_margin) - +import signal +import sys + +from prompt_toolkit.enums import DEFAULT_BUFFER, SEARCH_BUFFER +from prompt_toolkit.filters import (HasFocus, HasSelection, Condition, + ViInsertMode, EmacsInsertMode, HasCompletions) +from prompt_toolkit.filters.cli import ViMode +from prompt_toolkit.keys import Keys +from prompt_toolkit.key_binding.bindings.completion import display_completions_like_readline + +from IPython.utils.decorators import undoc + +@Condition +def cursor_in_leading_ws(cli): + before = cli.application.buffer.document.current_line_before_cursor + return (not before) or before.isspace() + +def register_ipython_shortcuts(registry, shell): + """Set up the prompt_toolkit keyboard shortcuts for IPython""" + insert_mode = ViInsertMode() | EmacsInsertMode() + + # Ctrl+J == Enter, seemingly + registry.add_binding(Keys.ControlJ, + filter=(HasFocus(DEFAULT_BUFFER) + & ~HasSelection() + & insert_mode + ))(newline_or_execute_outer(shell)) + + registry.add_binding(Keys.ControlBackslash)(force_exit) + + registry.add_binding(Keys.ControlP, + filter=(ViInsertMode() & HasFocus(DEFAULT_BUFFER) + ))(previous_history_or_previous_completion) + + registry.add_binding(Keys.ControlN, + filter=(ViInsertMode() & HasFocus(DEFAULT_BUFFER) + ))(next_history_or_next_completion) + + registry.add_binding(Keys.ControlG, + filter=(HasFocus(DEFAULT_BUFFER) & HasCompletions() + ))(dismiss_completion) + + registry.add_binding(Keys.ControlC, filter=HasFocus(DEFAULT_BUFFER) + )(reset_buffer) + + registry.add_binding(Keys.ControlC, filter=HasFocus(SEARCH_BUFFER) + )(reset_search_buffer) + + supports_suspend = Condition(lambda cli: hasattr(signal, 'SIGTSTP')) + registry.add_binding(Keys.ControlZ, filter=supports_suspend + )(suspend_to_bg) + + # Ctrl+I == Tab + registry.add_binding(Keys.ControlI, + filter=(HasFocus(DEFAULT_BUFFER) + & ~HasSelection() + & insert_mode + & cursor_in_leading_ws + ))(indent_buffer) + + registry.add_binding(Keys.ControlO, + filter=(HasFocus(DEFAULT_BUFFER) + & EmacsInsertMode()))(newline_with_copy_margin) + registry.add_binding(Keys.F2, filter=HasFocus(DEFAULT_BUFFER) )(open_input_in_editor) - if shell.display_completions == 'readlinelike': - registry.add_binding(Keys.ControlI, - filter=(HasFocus(DEFAULT_BUFFER) - & ~HasSelection() - & insert_mode - & ~cursor_in_leading_ws - ))(display_completions_like_readline) - - if sys.platform == 'win32': - registry.add_binding(Keys.ControlV, - filter=( - HasFocus( - DEFAULT_BUFFER) & ~ViMode() - ))(win_paste) - - -def newline_or_execute_outer(shell): - def newline_or_execute(event): - """When the user presses return, insert a newline or execute the code.""" - b = event.current_buffer - d = b.document - - if b.complete_state: - cc = b.complete_state.current_completion - if cc: - b.apply_completion(cc) - else: - b.cancel_completion() - return - + if shell.display_completions == 'readlinelike': + registry.add_binding(Keys.ControlI, + filter=(HasFocus(DEFAULT_BUFFER) + & ~HasSelection() + & insert_mode + & ~cursor_in_leading_ws + ))(display_completions_like_readline) + + if sys.platform == 'win32': + registry.add_binding(Keys.ControlV, + filter=( + HasFocus( + DEFAULT_BUFFER) & ~ViMode() + ))(win_paste) + + +def newline_or_execute_outer(shell): + def newline_or_execute(event): + """When the user presses return, insert a newline or execute the code.""" + b = event.current_buffer + d = b.document + + if b.complete_state: + cc = b.complete_state.current_completion + if cc: + b.apply_completion(cc) + else: + b.cancel_completion() + return + # If there's only one line, treat it as if the cursor is at the end. # See https://github.com/ipython/ipython/issues/10425 if d.line_count == 1: @@ -108,99 +108,99 @@ def newline_or_execute_outer(shell): d.cursor_position_row >= d.line_count - d.empty_line_count_at_the_end() ): b.insert_text('\n' + (' ' * (indent or 0))) - return - - if (status != 'incomplete') and b.accept_action.is_returnable: - b.accept_action.validate_and_handle(event.cli, b) - else: - b.insert_text('\n' + (' ' * (indent or 0))) - return newline_or_execute - - -def previous_history_or_previous_completion(event): - """ - Control-P in vi edit mode on readline is history next, unlike default prompt toolkit. - - If completer is open this still select previous completion. - """ - event.current_buffer.auto_up() - - -def next_history_or_next_completion(event): - """ - Control-N in vi edit mode on readline is history previous, unlike default prompt toolkit. - - If completer is open this still select next completion. - """ - event.current_buffer.auto_down() - - -def dismiss_completion(event): - b = event.current_buffer - if b.complete_state: - b.cancel_completion() - - -def reset_buffer(event): - b = event.current_buffer - if b.complete_state: - b.cancel_completion() - else: - b.reset() - - -def reset_search_buffer(event): - if event.current_buffer.document.text: - event.current_buffer.reset() - else: - event.cli.push_focus(DEFAULT_BUFFER) - -def suspend_to_bg(event): - event.cli.suspend_to_background() - -def force_exit(event): - """ - Force exit (with a non-zero return value) - """ - sys.exit("Quit") - -def indent_buffer(event): - event.current_buffer.insert_text(' ' * 4) - -def newline_with_copy_margin(event): - """ - Preserve margin and cursor position when using - Control-O to insert a newline in EMACS mode - """ - b = event.current_buffer - cursor_start_pos = b.document.cursor_position_col - b.newline(copy_margin=True) - b.cursor_up(count=1) - cursor_end_pos = b.document.cursor_position_col - if cursor_start_pos != cursor_end_pos: - pos_diff = cursor_start_pos - cursor_end_pos - b.cursor_right(count=pos_diff) - + return + + if (status != 'incomplete') and b.accept_action.is_returnable: + b.accept_action.validate_and_handle(event.cli, b) + else: + b.insert_text('\n' + (' ' * (indent or 0))) + return newline_or_execute + + +def previous_history_or_previous_completion(event): + """ + Control-P in vi edit mode on readline is history next, unlike default prompt toolkit. + + If completer is open this still select previous completion. + """ + event.current_buffer.auto_up() + + +def next_history_or_next_completion(event): + """ + Control-N in vi edit mode on readline is history previous, unlike default prompt toolkit. + + If completer is open this still select next completion. + """ + event.current_buffer.auto_down() + + +def dismiss_completion(event): + b = event.current_buffer + if b.complete_state: + b.cancel_completion() + + +def reset_buffer(event): + b = event.current_buffer + if b.complete_state: + b.cancel_completion() + else: + b.reset() + + +def reset_search_buffer(event): + if event.current_buffer.document.text: + event.current_buffer.reset() + else: + event.cli.push_focus(DEFAULT_BUFFER) + +def suspend_to_bg(event): + event.cli.suspend_to_background() + +def force_exit(event): + """ + Force exit (with a non-zero return value) + """ + sys.exit("Quit") + +def indent_buffer(event): + event.current_buffer.insert_text(' ' * 4) + +def newline_with_copy_margin(event): + """ + Preserve margin and cursor position when using + Control-O to insert a newline in EMACS mode + """ + b = event.current_buffer + cursor_start_pos = b.document.cursor_position_col + b.newline(copy_margin=True) + b.cursor_up(count=1) + cursor_end_pos = b.document.cursor_position_col + if cursor_start_pos != cursor_end_pos: + pos_diff = cursor_start_pos - cursor_end_pos + b.cursor_right(count=pos_diff) + def open_input_in_editor(event): event.cli.current_buffer.tempfile_suffix = ".py" event.cli.current_buffer.open_in_editor(event.cli) - - -if sys.platform == 'win32': - from IPython.core.error import TryNext - from IPython.lib.clipboard import (ClipboardEmpty, - win32_clipboard_get, - tkinter_clipboard_get) - - @undoc - def win_paste(event): - try: - text = win32_clipboard_get() - except TryNext: - try: - text = tkinter_clipboard_get() - except (TryNext, ClipboardEmpty): - return - except ClipboardEmpty: - return - event.current_buffer.insert_text(text.replace('\t', ' ' * 4)) + + +if sys.platform == 'win32': + from IPython.core.error import TryNext + from IPython.lib.clipboard import (ClipboardEmpty, + win32_clipboard_get, + tkinter_clipboard_get) + + @undoc + def win_paste(event): + try: + text = win32_clipboard_get() + except TryNext: + try: + text = tkinter_clipboard_get() + except (TryNext, ClipboardEmpty): + return + except ClipboardEmpty: + return + event.current_buffer.insert_text(text.replace('\t', ' ' * 4)) diff --git a/contrib/python/ipython/py2/IPython/testing/decorators.py b/contrib/python/ipython/py2/IPython/testing/decorators.py index c9807ce70e..26c6478f9e 100644 --- a/contrib/python/ipython/py2/IPython/testing/decorators.py +++ b/contrib/python/ipython/py2/IPython/testing/decorators.py @@ -48,7 +48,7 @@ from .ipunittest import ipdoctest, ipdocstring from IPython.external.decorators import * # For onlyif_cmd_exists decorator -from IPython.utils.py3compat import string_types, which, PY2, PY3, PYPY +from IPython.utils.py3compat import string_types, which, PY2, PY3, PYPY #----------------------------------------------------------------------------- # Classes and functions @@ -339,7 +339,7 @@ skip_known_failure = knownfailureif(True,'This test is known to fail') known_failure_py3 = knownfailureif(sys.version_info[0] >= 3, 'This test is known to fail on Python 3.') -cpython2_only = skipif(PY3 or PYPY, "This test only runs on CPython 2.") +cpython2_only = skipif(PY3 or PYPY, "This test only runs on CPython 2.") py2_only = skipif(PY3, "This test only runs on Python 2.") py3_only = skipif(PY2, "This test only runs on Python 3.") diff --git a/contrib/python/ipython/py2/IPython/testing/globalipapp.py b/contrib/python/ipython/py2/IPython/testing/globalipapp.py index 3983393112..adcb1dd587 100644 --- a/contrib/python/ipython/py2/IPython/testing/globalipapp.py +++ b/contrib/python/ipython/py2/IPython/testing/globalipapp.py @@ -8,11 +8,11 @@ done. from __future__ import absolute_import from __future__ import print_function -# Copyright (c) IPython Development Team. -# Distributed under the terms of the Modified BSD License. +# Copyright (c) IPython Development Team. +# Distributed under the terms of the Modified BSD License. import sys -import warnings +import warnings from . import tools @@ -34,9 +34,9 @@ class StreamProxy(io.IOStream): """ def __init__(self, name): - warnings.warn("StreamProxy is deprecated and unused as of IPython 5", DeprecationWarning, - stacklevel=2, - ) + warnings.warn("StreamProxy is deprecated and unused as of IPython 5", DeprecationWarning, + stacklevel=2, + ) self.name=name @property @@ -88,7 +88,7 @@ def start_ipython(): # Create custom argv and namespaces for our IPython to be test-friendly config = tools.default_config() - config.TerminalInteractiveShell.simple_prompt = True + config.TerminalInteractiveShell.simple_prompt = True # Create and initialize our test-friendly IPython instance. shell = TerminalInteractiveShell.instance(config=config, @@ -128,8 +128,8 @@ def start_ipython(): # Override paging, so we don't require user interaction during the tests. def nopage(strng, start=0, screen_lines=0, pager_cmd=None): - if isinstance(strng, dict): - strng = strng.get('text/plain', '') + if isinstance(strng, dict): + strng = strng.get('text/plain', '') print(strng) page.orig_page = page.pager_page diff --git a/contrib/python/ipython/py2/IPython/testing/iptest.py b/contrib/python/ipython/py2/IPython/testing/iptest.py index 4018264125..10d08b9e5a 100644 --- a/contrib/python/ipython/py2/IPython/testing/iptest.py +++ b/contrib/python/ipython/py2/IPython/testing/iptest.py @@ -44,10 +44,10 @@ pjoin = path.join # Enable printing all warnings raise by IPython's modules -warnings.filterwarnings('ignore', message='.*Matplotlib is building the font cache.*', category=UserWarning, module='.*') -if sys.version_info > (3,0): - warnings.filterwarnings('error', message='.*', category=ResourceWarning, module='.*') -warnings.filterwarnings('error', message=".*{'config': True}.*", category=DeprecationWarning, module='IPy.*') +warnings.filterwarnings('ignore', message='.*Matplotlib is building the font cache.*', category=UserWarning, module='.*') +if sys.version_info > (3,0): + warnings.filterwarnings('error', message='.*', category=ResourceWarning, module='.*') +warnings.filterwarnings('error', message=".*{'config': True}.*", category=DeprecationWarning, module='IPy.*') warnings.filterwarnings('default', message='.*', category=Warning, module='IPy.*') warnings.filterwarnings('error', message='.*apply_wrapper.*', category=DeprecationWarning, module='.*') @@ -217,7 +217,7 @@ test_group_names.append('autoreload') def check_exclusions_exist(): from IPython.paths import get_ipython_package_dir - from warnings import warn + from warnings import warn parent = os.path.dirname(get_ipython_package_dir()) for sec in test_sections: for pattern in sec.exclusions: diff --git a/contrib/python/ipython/py2/IPython/testing/plugin/ipdoctest.py b/contrib/python/ipython/py2/IPython/testing/plugin/ipdoctest.py index bc750e0efd..8eec1231a9 100644 --- a/contrib/python/ipython/py2/IPython/testing/plugin/ipdoctest.py +++ b/contrib/python/ipython/py2/IPython/testing/plugin/ipdoctest.py @@ -26,8 +26,8 @@ import os import re import sys -from testpath import modified_env - +from testpath import modified_env + from inspect import getmodule # We are overriding the default doctest runner, so we need to import a few @@ -41,7 +41,7 @@ from doctest import (REPORTING_FLAGS, REPORT_ONLY_FIRST_FAILURE, # Third-party modules from nose.plugins import doctests, Plugin -from nose.util import anyp, tolist +from nose.util import anyp, tolist # Our own imports from IPython.utils.py3compat import builtin_mod, PY3, getcwd @@ -140,7 +140,7 @@ class DocTestFinder(doctest.DocTestFinder): # doctests in extension modules. # Local shorthands - from inspect import isroutine, isclass + from inspect import isroutine, isclass # Look for tests in a module's contained objects. if inspect.ismodule(obj) and self._recurse: @@ -586,10 +586,10 @@ class IPDocTestRunner(doctest.DocTestRunner,object): test.globs.update(_ip.user_ns) - # Override terminal size to standardise traceback format - with modified_env({'COLUMNS': '80', 'LINES': '24'}): - return super(IPDocTestRunner,self).run(test, - compileflags,out,clear_globs) + # Override terminal size to standardise traceback format + with modified_env({'COLUMNS': '80', 'LINES': '24'}): + return super(IPDocTestRunner,self).run(test, + compileflags,out,clear_globs) class DocFileCase(doctest.DocFileCase): diff --git a/contrib/python/ipython/py2/IPython/testing/skipdoctest.py b/contrib/python/ipython/py2/IPython/testing/skipdoctest.py index 564ca54027..499ce28e07 100644 --- a/contrib/python/ipython/py2/IPython/testing/skipdoctest.py +++ b/contrib/python/ipython/py2/IPython/testing/skipdoctest.py @@ -36,8 +36,8 @@ def skip_doctest_py3(f): """Decorator - skip the doctest under Python 3.""" f.skip_doctest = (sys.version_info[0] >= 3) return f - -def skip_doctest_py2(f): - """Decorator - skip the doctest under Python 3.""" - f.skip_doctest = (sys.version_info[0] < 3) - return f + +def skip_doctest_py2(f): + """Decorator - skip the doctest under Python 3.""" + f.skip_doctest = (sys.version_info[0] < 3) + return f diff --git a/contrib/python/ipython/py2/IPython/testing/tools.py b/contrib/python/ipython/py2/IPython/testing/tools.py index 23bf6a68cb..fbe91abcca 100644 --- a/contrib/python/ipython/py2/IPython/testing/tools.py +++ b/contrib/python/ipython/py2/IPython/testing/tools.py @@ -196,7 +196,7 @@ def ipexec(fname, options=None, commands=()): """ if options is None: options = [] - cmdargs = default_argv() + options + cmdargs = default_argv() + options test_dir = os.path.dirname(__file__) @@ -291,13 +291,13 @@ class TempFileMixin(object): # delete it. I have no clue why pass - def __enter__(self): - return self - - def __exit__(self, exc_type, exc_value, traceback): - self.tearDown() - - + def __enter__(self): + return self + + def __exit__(self, exc_type, exc_value, traceback): + self.tearDown() + + pair_fail_msg = ("Testing {0}\n\n" "In:\n" " {1!r}\n" diff --git a/contrib/python/ipython/py2/IPython/utils/PyColorize.py b/contrib/python/ipython/py2/IPython/utils/PyColorize.py index 124eb2d4e3..66d52f34dd 100644 --- a/contrib/python/ipython/py2/IPython/utils/PyColorize.py +++ b/contrib/python/ipython/py2/IPython/utils/PyColorize.py @@ -54,8 +54,8 @@ except AttributeError: from IPython.utils.coloransi import TermColors, InputTermColors ,ColorScheme, ColorSchemeTable from IPython.utils.py3compat import PY3 -from .colorable import Colorable - +from .colorable import Colorable + if PY3: from io import StringIO else: @@ -122,40 +122,40 @@ LinuxColors = ColorScheme( 'normal' : Colors.Normal # color off (usu. Colors.Normal) } ) -NeutralColors = ColorScheme( - 'Neutral',{ - 'header' : Colors.Red, - token.NUMBER : Colors.Cyan, - token.OP : Colors.Blue, - token.STRING : Colors.Blue, - tokenize.COMMENT : Colors.Red, - token.NAME : Colors.Normal, - token.ERRORTOKEN : Colors.Red, - - _KEYWORD : Colors.Green, - _TEXT : Colors.Blue, - - 'in_prompt' : InputTermColors.Blue, - 'in_number' : InputTermColors.LightBlue, - 'in_prompt2' : InputTermColors.Blue, - 'in_normal' : InputTermColors.Normal, # color off (usu. Colors.Normal) - - 'out_prompt' : Colors.Red, - 'out_number' : Colors.LightRed, - - 'normal' : Colors.Normal # color off (usu. Colors.Normal) - } ) - -# Hack: the 'neutral' colours are not very visible on a dark background on -# Windows. Since Windows command prompts have a dark background by default, and -# relatively few users are likely to alter that, we will use the 'Linux' colours, -# designed for a dark background, as the default on Windows. Changing it here -# avoids affecting the prompt colours rendered by prompt_toolkit, where the -# neutral defaults do work OK. - -if os.name == 'nt': - NeutralColors = LinuxColors.copy(name='Neutral') - +NeutralColors = ColorScheme( + 'Neutral',{ + 'header' : Colors.Red, + token.NUMBER : Colors.Cyan, + token.OP : Colors.Blue, + token.STRING : Colors.Blue, + tokenize.COMMENT : Colors.Red, + token.NAME : Colors.Normal, + token.ERRORTOKEN : Colors.Red, + + _KEYWORD : Colors.Green, + _TEXT : Colors.Blue, + + 'in_prompt' : InputTermColors.Blue, + 'in_number' : InputTermColors.LightBlue, + 'in_prompt2' : InputTermColors.Blue, + 'in_normal' : InputTermColors.Normal, # color off (usu. Colors.Normal) + + 'out_prompt' : Colors.Red, + 'out_number' : Colors.LightRed, + + 'normal' : Colors.Normal # color off (usu. Colors.Normal) + } ) + +# Hack: the 'neutral' colours are not very visible on a dark background on +# Windows. Since Windows command prompts have a dark background by default, and +# relatively few users are likely to alter that, we will use the 'Linux' colours, +# designed for a dark background, as the default on Windows. Changing it here +# avoids affecting the prompt colours rendered by prompt_toolkit, where the +# neutral defaults do work OK. + +if os.name == 'nt': + NeutralColors = LinuxColors.copy(name='Neutral') + LightBGColors = ColorScheme( 'LightBG',{ 'header' : Colors.Red, @@ -166,7 +166,7 @@ LightBGColors = ColorScheme( token.NAME : Colors.Normal, token.ERRORTOKEN : Colors.Red, - + _KEYWORD : Colors.Green, _TEXT : Colors.Blue, @@ -182,21 +182,21 @@ LightBGColors = ColorScheme( } ) # Build table of color schemes (needed by the parser) -ANSICodeColors = ColorSchemeTable([NoColor,LinuxColors,LightBGColors, NeutralColors], +ANSICodeColors = ColorSchemeTable([NoColor,LinuxColors,LightBGColors, NeutralColors], _scheme_default) -class Parser(Colorable): +class Parser(Colorable): """ Format colored Python source. """ - def __init__(self, color_table=None, out = sys.stdout, parent=None, style=None): + def __init__(self, color_table=None, out = sys.stdout, parent=None, style=None): """ Create a parser with a specified color table and output channel. Call format() to process code. """ - - super(Parser, self).__init__(parent=parent) - + + super(Parser, self).__init__(parent=parent) + self.color_table = color_table and color_table or ANSICodeColors self.out = out diff --git a/contrib/python/ipython/py2/IPython/utils/_process_common.py b/contrib/python/ipython/py2/IPython/utils/_process_common.py index 9ede30d3f8..e1b305f734 100644 --- a/contrib/python/ipython/py2/IPython/utils/_process_common.py +++ b/contrib/python/ipython/py2/IPython/utils/_process_common.py @@ -17,7 +17,7 @@ of subprocess utilities, and it contains tools that are common to all of them. import subprocess import shlex import sys -import os +import os from IPython.utils import py3compat @@ -70,14 +70,14 @@ def process_handler(cmd, callback, stderr=subprocess.PIPE): sys.stderr.flush() # On win32, close_fds can't be true when using pipes for stdin/out/err close_fds = sys.platform != 'win32' - # Determine if cmd should be run with system shell. - shell = isinstance(cmd, py3compat.string_types) - # On POSIX systems run shell commands with user-preferred shell. - executable = None - if shell and os.name == 'posix' and 'SHELL' in os.environ: - executable = os.environ['SHELL'] - p = subprocess.Popen(cmd, shell=shell, - executable=executable, + # Determine if cmd should be run with system shell. + shell = isinstance(cmd, py3compat.string_types) + # On POSIX systems run shell commands with user-preferred shell. + executable = None + if shell and os.name == 'posix' and 'SHELL' in os.environ: + executable = os.environ['SHELL'] + p = subprocess.Popen(cmd, shell=shell, + executable=executable, stdin=subprocess.PIPE, stdout=subprocess.PIPE, stderr=stderr, diff --git a/contrib/python/ipython/py2/IPython/utils/colorable.py b/contrib/python/ipython/py2/IPython/utils/colorable.py index 9f7c5ac213..1d5b6b4abe 100644 --- a/contrib/python/ipython/py2/IPython/utils/colorable.py +++ b/contrib/python/ipython/py2/IPython/utils/colorable.py @@ -1,26 +1,26 @@ -#***************************************************************************** -# Copyright (C) 2016 The IPython Team <ipython-dev@scipy.org> -# -# Distributed under the terms of the BSD License. The full license is in -# the file COPYING, distributed as part of this software. -#***************************************************************************** -from __future__ import absolute_import - -""" -Color managing related utilities -""" - -import pygments - -from traitlets.config import Configurable -from traitlets import Unicode - - -available_themes = lambda : [s for s in pygments.styles.get_all_styles()]+['NoColor','LightBG','Linux', 'Neutral'] - -class Colorable(Configurable): - """ - A subclass of configurable for all the classes that have a `default_scheme` - """ - default_style=Unicode('lightbg').tag(config=True) - +#***************************************************************************** +# Copyright (C) 2016 The IPython Team <ipython-dev@scipy.org> +# +# Distributed under the terms of the BSD License. The full license is in +# the file COPYING, distributed as part of this software. +#***************************************************************************** +from __future__ import absolute_import + +""" +Color managing related utilities +""" + +import pygments + +from traitlets.config import Configurable +from traitlets import Unicode + + +available_themes = lambda : [s for s in pygments.styles.get_all_styles()]+['NoColor','LightBG','Linux', 'Neutral'] + +class Colorable(Configurable): + """ + A subclass of configurable for all the classes that have a `default_scheme` + """ + default_style=Unicode('lightbg').tag(config=True) + diff --git a/contrib/python/ipython/py2/IPython/utils/contexts.py b/contrib/python/ipython/py2/IPython/utils/contexts.py index 4d379b0eda..14f4b47ba6 100644 --- a/contrib/python/ipython/py2/IPython/utils/contexts.py +++ b/contrib/python/ipython/py2/IPython/utils/contexts.py @@ -2,8 +2,8 @@ """Miscellaneous context managers. """ -import warnings - +import warnings + # Copyright (c) IPython Development Team. # Distributed under the terms of the Modified BSD License. @@ -61,14 +61,14 @@ class preserve_keys(object): class NoOpContext(object): - """ - Deprecated - - Context manager that does nothing.""" - - def __init__(self): - warnings.warn("""NoOpContext is deprecated since IPython 5.0 """, - DeprecationWarning, stacklevel=2) - + """ + Deprecated + + Context manager that does nothing.""" + + def __init__(self): + warnings.warn("""NoOpContext is deprecated since IPython 5.0 """, + DeprecationWarning, stacklevel=2) + def __enter__(self): pass def __exit__(self, type, value, traceback): pass diff --git a/contrib/python/ipython/py2/IPython/utils/dir2.py b/contrib/python/ipython/py2/IPython/utils/dir2.py index f6f164f9b1..352c079178 100644 --- a/contrib/python/ipython/py2/IPython/utils/dir2.py +++ b/contrib/python/ipython/py2/IPython/utils/dir2.py @@ -2,10 +2,10 @@ """A fancy version of Python's builtin :func:`dir` function. """ -# Copyright (c) IPython Development Team. -# Distributed under the terms of the Modified BSD License. +# Copyright (c) IPython Development Team. +# Distributed under the terms of the Modified BSD License. -import inspect +import inspect from .py3compat import string_types @@ -46,36 +46,36 @@ def dir2(obj): words = [w for w in words if isinstance(w, string_types)] return sorted(words) - - -def get_real_method(obj, name): - """Like getattr, but with a few extra sanity checks: - - - If obj is a class, ignore its methods - - Check if obj is a proxy that claims to have all attributes - - Catch attribute access failing with any exception - - Check that the attribute is a callable object - - Returns the method or None. - """ - if inspect.isclass(obj): - return None - - try: - canary = getattr(obj, '_ipython_canary_method_should_not_exist_', None) - except Exception: - return None - - if canary is not None: - # It claimed to have an attribute it should never have - return None - - try: - m = getattr(obj, name, None) - except Exception: - return None - - if callable(m): - return m - - return None + + +def get_real_method(obj, name): + """Like getattr, but with a few extra sanity checks: + + - If obj is a class, ignore its methods + - Check if obj is a proxy that claims to have all attributes + - Catch attribute access failing with any exception + - Check that the attribute is a callable object + + Returns the method or None. + """ + if inspect.isclass(obj): + return None + + try: + canary = getattr(obj, '_ipython_canary_method_should_not_exist_', None) + except Exception: + return None + + if canary is not None: + # It claimed to have an attribute it should never have + return None + + try: + m = getattr(obj, name, None) + except Exception: + return None + + if callable(m): + return m + + return None diff --git a/contrib/python/ipython/py2/IPython/utils/io.py b/contrib/python/ipython/py2/IPython/utils/io.py index 036d6e3926..817ecff278 100644 --- a/contrib/python/ipython/py2/IPython/utils/io.py +++ b/contrib/python/ipython/py2/IPython/utils/io.py @@ -14,19 +14,19 @@ import atexit import os import sys import tempfile -import warnings +import warnings from warnings import warn - -from IPython.utils.decorators import undoc + +from IPython.utils.decorators import undoc from .capture import CapturedIO, capture_output from .py3compat import string_types, input, PY3 -@undoc +@undoc class IOStream: - def __init__(self, stream, fallback=None): - warn('IOStream is deprecated since IPython 5.0, use sys.{stdin,stdout,stderr} instead', - DeprecationWarning, stacklevel=2) + def __init__(self, stream, fallback=None): + warn('IOStream is deprecated since IPython 5.0, use sys.{stdin,stdout,stderr} instead', + DeprecationWarning, stacklevel=2) if not hasattr(stream,'write') or not hasattr(stream,'flush'): if fallback is not None: stream = fallback @@ -52,8 +52,8 @@ class IOStream: return tpl.format(mod=cls.__module__, cls=cls.__name__, args=self.stream) def write(self,data): - warn('IOStream is deprecated since IPython 5.0, use sys.{stdin,stdout,stderr} instead', - DeprecationWarning, stacklevel=2) + warn('IOStream is deprecated since IPython 5.0, use sys.{stdin,stdout,stderr} instead', + DeprecationWarning, stacklevel=2) try: self._swrite(data) except: @@ -68,8 +68,8 @@ class IOStream: file=sys.stderr) def writelines(self, lines): - warn('IOStream is deprecated since IPython 5.0, use sys.{stdin,stdout,stderr} instead', - DeprecationWarning, stacklevel=2) + warn('IOStream is deprecated since IPython 5.0, use sys.{stdin,stdout,stderr} instead', + DeprecationWarning, stacklevel=2) if isinstance(lines, string_types): lines = [lines] for line in lines: @@ -87,17 +87,17 @@ class IOStream: pass # setup stdin/stdout/stderr to sys.stdin/sys.stdout/sys.stderr -devnull = open(os.devnull, 'w') +devnull = open(os.devnull, 'w') atexit.register(devnull.close) -# 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) - stdin = IOStream(sys.stdin, fallback=devnull) - stdout = IOStream(sys.stdout, fallback=devnull) - stderr = IOStream(sys.stderr, fallback=devnull) - +# 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) + stdin = IOStream(sys.stdin, fallback=devnull) + stdout = IOStream(sys.stdout, fallback=devnull) + stderr = IOStream(sys.stderr, fallback=devnull) + class Tee(object): """A class to duplicate an output stream to stdout/err. diff --git a/contrib/python/ipython/py2/IPython/utils/path.py b/contrib/python/ipython/py2/IPython/utils/path.py index fa850812c7..f7b7666642 100644 --- a/contrib/python/ipython/py2/IPython/utils/path.py +++ b/contrib/python/ipython/py2/IPython/utils/path.py @@ -72,21 +72,21 @@ def get_long_path_name(path): def unquote_filename(name, win32=(sys.platform=='win32')): """ On Windows, remove leading and trailing quotes from filenames. - - This function has been deprecated and should not be used any more: - unquoting is now taken care of by :func:`IPython.utils.process.arg_split`. + + This function has been deprecated and should not be used any more: + unquoting is now taken care of by :func:`IPython.utils.process.arg_split`. """ - warn("'unquote_filename' is deprecated since IPython 5.0 and should not " + warn("'unquote_filename' is deprecated since IPython 5.0 and should not " "be used anymore", DeprecationWarning, stacklevel=2) if win32: if name.startswith(("'", '"')) and name.endswith(("'", '"')): name = name[1:-1] return name - + def compress_user(path): """Reverse of :func:`os.path.expanduser` - """ + """ path = py3compat.unicode_to_str(path, sys.getfilesystemencoding()) home = os.path.expanduser('~') if path.startswith(home): @@ -101,9 +101,9 @@ def get_py_filename(name, force_win32=None): """ name = os.path.expanduser(name) - if force_win32 is not None: - warn("The 'force_win32' argument to 'get_py_filename' is deprecated " - "since IPython 5.0 and should not be used anymore", + if force_win32 is not None: + warn("The 'force_win32' argument to 'get_py_filename' is deprecated " + "since IPython 5.0 and should not be used anymore", DeprecationWarning, stacklevel=2) if not os.path.isfile(name) and not name.endswith('.py'): name += '.py' diff --git a/contrib/python/ipython/py2/IPython/utils/py3compat.py b/contrib/python/ipython/py2/IPython/utils/py3compat.py index 88602e5342..4d37054559 100644 --- a/contrib/python/ipython/py2/IPython/utils/py3compat.py +++ b/contrib/python/ipython/py2/IPython/utils/py3compat.py @@ -6,7 +6,7 @@ import sys import re import shutil import types -import platform +import platform from .encoding import DEFAULT_ENCODING @@ -293,7 +293,7 @@ else: PY2 = not PY3 -PYPY = platform.python_implementation() == "PyPy" +PYPY = platform.python_implementation() == "PyPy" def annotate(**kwargs): diff --git a/contrib/python/ipython/py2/IPython/utils/terminal.py b/contrib/python/ipython/py2/IPython/utils/terminal.py index e92c410c79..397a3e86fb 100644 --- a/contrib/python/ipython/py2/IPython/utils/terminal.py +++ b/contrib/python/ipython/py2/IPython/utils/terminal.py @@ -11,16 +11,16 @@ Authors: from __future__ import absolute_import -# Copyright (c) IPython Development Team. -# Distributed under the terms of the Modified BSD License. +# Copyright (c) IPython Development Team. +# Distributed under the terms of the Modified BSD License. import os import sys import warnings -try: - from shutil import get_terminal_size as _get_terminal_size -except ImportError: - # use backport on Python 2 +try: + from shutil import get_terminal_size as _get_terminal_size +except ImportError: + # use backport on Python 2 try: from backports.shutil_get_terminal_size import get_terminal_size as _get_terminal_size except ImportError: @@ -121,5 +121,5 @@ def freeze_term_title(): ignore_termtitle = True -def get_terminal_size(defaultx=80, defaulty=25): - return _get_terminal_size((defaultx, defaulty)) +def get_terminal_size(defaultx=80, defaulty=25): + return _get_terminal_size((defaultx, defaulty)) diff --git a/contrib/python/ipython/py2/IPython/utils/text.py b/contrib/python/ipython/py2/IPython/utils/text.py index 5ed1a845e3..63588fb322 100644 --- a/contrib/python/ipython/py2/IPython/utils/text.py +++ b/contrib/python/ipython/py2/IPython/utils/text.py @@ -14,11 +14,11 @@ import re import sys import textwrap from string import Formatter -try: - from pathlib import Path -except ImportError: - # Python 2 backport - from pathlib2 import Path +try: + from pathlib import Path +except ImportError: + # Python 2 backport + from pathlib2 import Path from IPython.testing.skipdoctest import skip_doctest_py3, skip_doctest from IPython.utils import py3compat @@ -72,7 +72,7 @@ class LSString(str): try: return self.__paths except AttributeError: - self.__paths = [Path(p) for p in self.split('\n') if os.path.exists(p)] + self.__paths = [Path(p) for p in self.split('\n') if os.path.exists(p)] return self.__paths p = paths = property(get_paths) @@ -130,7 +130,7 @@ class SList(list): try: return self.__paths except AttributeError: - self.__paths = [Path(p) for p in self if os.path.exists(p)] + self.__paths = [Path(p) for p in self if os.path.exists(p)] return self.__paths p = paths = property(get_paths) diff --git a/contrib/python/ipython/py2/IPython/utils/tokenutil.py b/contrib/python/ipython/py2/IPython/utils/tokenutil.py index f52d3b7658..e01f5e7b32 100644 --- a/contrib/python/ipython/py2/IPython/utils/tokenutil.py +++ b/contrib/python/ipython/py2/IPython/utils/tokenutil.py @@ -31,7 +31,7 @@ def line_at_cursor(cell, cursor_pos=0): Parameters ---------- - cell: str + cell: str multiline block of text cursor_pos: integer the cursor position diff --git a/contrib/python/ipython/py2/IPython/utils/warn.py b/contrib/python/ipython/py2/IPython/utils/warn.py index dd4852227b..ae5424a038 100644 --- a/contrib/python/ipython/py2/IPython/utils/warn.py +++ b/contrib/python/ipython/py2/IPython/utils/warn.py @@ -9,17 +9,17 @@ Utilities for warnings. Shoudn't we just use the built in warnings module. from __future__ import print_function import sys -import warnings +import warnings -warnings.warn("The module IPython.utils.warn is deprecated since IPython 4.0, use the standard warnings module instead", DeprecationWarning) +warnings.warn("The module IPython.utils.warn is deprecated since IPython 4.0, use the standard warnings module instead", DeprecationWarning) def warn(msg,level=2,exit_val=1): - """Deprecated - - Standard warning printer. Gives formatting consistency. + """Deprecated - Output is sent to sys.stderr. + Standard warning printer. Gives formatting consistency. + Output is sent to sys.stderr. + Options: -level(2): allows finer control: @@ -31,35 +31,35 @@ def warn(msg,level=2,exit_val=1): -exit_val (1): exit value returned by sys.exit() for a level 4 warning. Ignored for all other levels.""" - - warnings.warn("The module IPython.utils.warn is deprecated since IPython 4.0, use the standard warnings module instead", DeprecationWarning) + + warnings.warn("The module IPython.utils.warn is deprecated since IPython 4.0, use the standard warnings module instead", DeprecationWarning) if level>0: header = ['','','WARNING: ','ERROR: ','FATAL ERROR: '] - print(header[level], msg, sep='', file=sys.stderr) + print(header[level], msg, sep='', file=sys.stderr) if level == 4: - print('Exiting.\n', file=sys.stderr) + print('Exiting.\n', file=sys.stderr) sys.exit(exit_val) def info(msg): - """Deprecated - - Equivalent to warn(msg,level=1).""" + """Deprecated + + Equivalent to warn(msg,level=1).""" warn(msg,level=1) def error(msg): - """Deprecated - - Equivalent to warn(msg,level=3).""" + """Deprecated + + Equivalent to warn(msg,level=3).""" warn(msg,level=3) def fatal(msg,exit_val=1): - """Deprecated - - Equivalent to warn(msg,exit_val=exit_val,level=4).""" + """Deprecated + + Equivalent to warn(msg,exit_val=exit_val,level=4).""" warn(msg,exit_val=exit_val,level=4) diff --git a/contrib/python/ipython/ya.make b/contrib/python/ipython/ya.make index b1dd8c5e23..3809a3103a 100644 --- a/contrib/python/ipython/ya.make +++ b/contrib/python/ipython/ya.make @@ -3,7 +3,7 @@ PY23_LIBRARY() LICENSE(Service-Py23-Proxy) OWNER(g:python-contrib) - + IF (PYTHON2) PEERDIR(contrib/python/ipython/py2) ELSE() diff --git a/contrib/python/jedi/ya.make b/contrib/python/jedi/ya.make index eff2fef2a7..13a87aa8ae 100644 --- a/contrib/python/jedi/ya.make +++ b/contrib/python/jedi/ya.make @@ -5,7 +5,7 @@ LICENSE(MIT) OWNER(g:python-contrib borman) VERSION(0.13.3) - + PEERDIR( contrib/python/parso contrib/python/setuptools diff --git a/contrib/python/pexpect/ya.make b/contrib/python/pexpect/ya.make index a5bb92fcac..437dd443ea 100644 --- a/contrib/python/pexpect/ya.make +++ b/contrib/python/pexpect/ya.make @@ -3,11 +3,11 @@ PY23_LIBRARY() LICENSE(ISC) OWNER(g:python-contrib borman) - + VERSION(4.8.0) PEERDIR( - contrib/python/ptyprocess + contrib/python/ptyprocess ) NO_LINT() diff --git a/contrib/python/pickleshare/ya.make b/contrib/python/pickleshare/ya.make index e24c2cdad7..cbb2c17737 100644 --- a/contrib/python/pickleshare/ya.make +++ b/contrib/python/pickleshare/ya.make @@ -5,7 +5,7 @@ PY23_LIBRARY() OWNER(borman g:python-contrib) VERSION(0.7.5) - + LICENSE(MIT) IF (PYTHON2) diff --git a/contrib/python/prompt-toolkit/py2/prompt_toolkit/__init__.py b/contrib/python/prompt-toolkit/py2/prompt_toolkit/__init__.py index 6478ba4f9a..bc2bec7eb5 100644 --- a/contrib/python/prompt-toolkit/py2/prompt_toolkit/__init__.py +++ b/contrib/python/prompt-toolkit/py2/prompt_toolkit/__init__.py @@ -15,8 +15,8 @@ Probably, to get started, you meight also want to have a look at """ from .interface import CommandLineInterface from .application import AbortAction, Application -from .shortcuts import prompt, prompt_async +from .shortcuts import prompt, prompt_async -# Don't forget to update in `docs/conf.py`! +# Don't forget to update in `docs/conf.py`! __version__ = '1.0.18' diff --git a/contrib/python/prompt-toolkit/py2/prompt_toolkit/application.py b/contrib/python/prompt-toolkit/py2/prompt_toolkit/application.py index 272d8bbcbb..7a7afa3074 100644 --- a/contrib/python/prompt-toolkit/py2/prompt_toolkit/application.py +++ b/contrib/python/prompt-toolkit/py2/prompt_toolkit/application.py @@ -3,18 +3,18 @@ from __future__ import unicode_literals from .buffer import Buffer, AcceptAction from .buffer_mapping import BufferMapping from .clipboard import Clipboard, InMemoryClipboard -from .enums import DEFAULT_BUFFER, EditingMode +from .enums import DEFAULT_BUFFER, EditingMode from .filters import CLIFilter, to_cli_filter from .key_binding.bindings.basic import load_basic_bindings from .key_binding.bindings.emacs import load_emacs_bindings -from .key_binding.bindings.vi import load_vi_bindings +from .key_binding.bindings.vi import load_vi_bindings from .key_binding.registry import BaseRegistry from .key_binding.defaults import load_key_bindings from .layout import Window from .layout.containers import Container from .layout.controls import BufferControl from .styles import DEFAULT_STYLE, Style -import six +import six __all__ = ( 'AbortAction', @@ -57,7 +57,7 @@ class Application(object): :param on_exit: What to do when Control-D is pressed. :param use_alternate_screen: When True, run the application on the alternate screen buffer. :param get_title: Callable that returns the current title to be displayed in the terminal. - :param erase_when_done: (bool) Clear the application output when it finishes. + :param erase_when_done: (bool) Clear the application output when it finishes. :param reverse_vi_search_direction: Normally, in Vi mode, a '/' searches forward and a '?' searches backward. In readline mode, this is usually reversed. @@ -68,10 +68,10 @@ class Application(object): boolean). When True, enable mouse support. :param paste_mode: :class:`~prompt_toolkit.filters.CLIFilter` or boolean. :param ignore_case: :class:`~prompt_toolkit.filters.CLIFilter` or boolean. - :param editing_mode: :class:`~prompt_toolkit.enums.EditingMode`. + :param editing_mode: :class:`~prompt_toolkit.enums.EditingMode`. - Callbacks (all of these should accept a - :class:`~prompt_toolkit.interface.CommandLineInterface` object as input.) + Callbacks (all of these should accept a + :class:`~prompt_toolkit.interface.CommandLineInterface` object as input.) :param on_input_timeout: Called when there is no input for x seconds. (Fired when any eventloop.onInputTimeout is fired.) @@ -81,8 +81,8 @@ class Application(object): :param on_buffer_changed: Called when the content of a buffer has been changed. :param on_initialize: Called after the :class:`~prompt_toolkit.interface.CommandLineInterface` initializes. - :param on_render: Called right after rendering. - :param on_invalidate: Called when the UI has been invalidated. + :param on_render: Called right after rendering. + :param on_invalidate: Called when the UI has been invalidated. """ def __init__(self, layout=None, buffer=None, buffers=None, initial_focussed_buffer=DEFAULT_BUFFER, @@ -92,13 +92,13 @@ class Application(object): use_alternate_screen=False, mouse_support=False, get_title=None, - paste_mode=False, ignore_case=False, editing_mode=EditingMode.EMACS, - erase_when_done=False, + paste_mode=False, ignore_case=False, editing_mode=EditingMode.EMACS, + erase_when_done=False, reverse_vi_search_direction=False, on_input_timeout=None, on_start=None, on_stop=None, - on_reset=None, on_initialize=None, on_buffer_changed=None, - on_render=None, on_invalidate=None): + on_reset=None, on_initialize=None, on_buffer_changed=None, + on_render=None, on_invalidate=None): paste_mode = to_cli_filter(paste_mode) ignore_case = to_cli_filter(ignore_case) @@ -116,28 +116,28 @@ class Application(object): assert get_title is None or callable(get_title) assert isinstance(paste_mode, CLIFilter) assert isinstance(ignore_case, CLIFilter) - assert isinstance(editing_mode, six.string_types) - assert on_input_timeout is None or callable(on_input_timeout) + assert isinstance(editing_mode, six.string_types) + assert on_input_timeout is None or callable(on_input_timeout) assert style is None or isinstance(style, Style) - assert isinstance(erase_when_done, bool) - - assert on_start is None or callable(on_start) - assert on_stop is None or callable(on_stop) - assert on_reset is None or callable(on_reset) - assert on_buffer_changed is None or callable(on_buffer_changed) - assert on_initialize is None or callable(on_initialize) - assert on_render is None or callable(on_render) - assert on_invalidate is None or callable(on_invalidate) - + assert isinstance(erase_when_done, bool) + + assert on_start is None or callable(on_start) + assert on_stop is None or callable(on_stop) + assert on_reset is None or callable(on_reset) + assert on_buffer_changed is None or callable(on_buffer_changed) + assert on_initialize is None or callable(on_initialize) + assert on_render is None or callable(on_render) + assert on_invalidate is None or callable(on_invalidate) + self.layout = layout or Window(BufferControl()) # Make sure that the 'buffers' dictionary is a BufferMapping. - # NOTE: If no buffer is given, we create a default Buffer, with IGNORE as - # default accept_action. This is what makes sense for most users - # creating full screen applications. Doing nothing is the obvious - # default. Those creating a REPL would use the shortcuts module that - # passes in RETURN_DOCUMENT. - self.buffer = buffer or Buffer(accept_action=AcceptAction.IGNORE) + # NOTE: If no buffer is given, we create a default Buffer, with IGNORE as + # default accept_action. This is what makes sense for most users + # creating full screen applications. Doing nothing is the obvious + # default. Those creating a REPL would use the shortcuts module that + # passes in RETURN_DOCUMENT. + self.buffer = buffer or Buffer(accept_action=AcceptAction.IGNORE) if not buffers or not isinstance(buffers, BufferMapping): self.buffers = BufferMapping(buffers, initial=initial_focussed_buffer) else: @@ -166,21 +166,21 @@ class Application(object): self.paste_mode = paste_mode self.ignore_case = ignore_case - self.editing_mode = editing_mode - self.erase_when_done = erase_when_done + self.editing_mode = editing_mode + self.erase_when_done = erase_when_done self.reverse_vi_search_direction = reverse_vi_search_direction - def dummy_handler(cli): - " Dummy event handler. " - - self.on_input_timeout = on_input_timeout or dummy_handler - self.on_start = on_start or dummy_handler - self.on_stop = on_stop or dummy_handler - self.on_reset = on_reset or dummy_handler - self.on_initialize = on_initialize or dummy_handler - self.on_buffer_changed = on_buffer_changed or dummy_handler - self.on_render = on_render or dummy_handler - self.on_invalidate = on_invalidate or dummy_handler + def dummy_handler(cli): + " Dummy event handler. " + + self.on_input_timeout = on_input_timeout or dummy_handler + self.on_start = on_start or dummy_handler + self.on_stop = on_stop or dummy_handler + self.on_reset = on_reset or dummy_handler + self.on_initialize = on_initialize or dummy_handler + self.on_buffer_changed = on_buffer_changed or dummy_handler + self.on_render = on_render or dummy_handler + self.on_invalidate = on_invalidate or dummy_handler # List of 'extra' functions to execute before a CommandLineInterface.run. # Note: It's important to keep this here, and not in the diff --git a/contrib/python/prompt-toolkit/py2/prompt_toolkit/buffer.py b/contrib/python/prompt-toolkit/py2/prompt_toolkit/buffer.py index f5df289827..f0332d939d 100644 --- a/contrib/python/prompt-toolkit/py2/prompt_toolkit/buffer.py +++ b/contrib/python/prompt-toolkit/py2/prompt_toolkit/buffer.py @@ -13,14 +13,14 @@ from .filters import to_simple_filter from .history import History, InMemoryHistory from .search_state import SearchState from .selection import SelectionType, SelectionState, PasteMode -from .utils import Event -from .cache import FastDictCache +from .utils import Event +from .cache import FastDictCache from .validation import ValidationError -from six.moves import range - +from six.moves import range + import os -import re +import re import shlex import six import subprocess @@ -32,10 +32,10 @@ __all__ = ( 'Buffer', 'indent', 'unindent', - 'reshape_text', + 'reshape_text', ) - + class EditReadOnlyBuffer(Exception): " Attempt editing of read-only :class:`.Buffer`. " @@ -165,24 +165,24 @@ class CompletionState(object): return self.current_completions[self.complete_index] -_QUOTED_WORDS_RE = re.compile(r"""(\s+|".*?"|'.*?')""") - - -class YankNthArgState(object): - """ - For yank-last-arg/yank-nth-arg: Keep track of where we are in the history. - """ - def __init__(self, history_position=0, n=-1, previous_inserted_word=''): - self.history_position = history_position - self.previous_inserted_word = previous_inserted_word - self.n = n - - def __repr__(self): - return '%s(history_position=%r, n=%r, previous_inserted_word=%r)' % ( - self.__class__.__name__, self.history_position, self.n, - self.previous_inserted_word) - - +_QUOTED_WORDS_RE = re.compile(r"""(\s+|".*?"|'.*?')""") + + +class YankNthArgState(object): + """ + For yank-last-arg/yank-nth-arg: Keep track of where we are in the history. + """ + def __init__(self, history_position=0, n=-1, previous_inserted_word=''): + self.history_position = history_position + self.previous_inserted_word = previous_inserted_word + self.n = n + + def __repr__(self): + return '%s(history_position=%r, n=%r, previous_inserted_word=%r)' % ( + self.__class__.__name__, self.history_position, self.n, + self.previous_inserted_word) + + class Buffer(object): """ The core data structure that holds the text and cursor position of the @@ -196,9 +196,9 @@ class Buffer(object): Events: - :param on_text_changed: When the buffer text changes. (Callable on None.) - :param on_text_insert: When new text is inserted. (Callable on None.) - :param on_cursor_position_changed: When the cursor moves. (Callable on None.) + :param on_text_changed: When the buffer text changes. (Callable on None.) + :param on_text_insert: When new text is inserted. (Callable on None.) + :param on_cursor_position_changed: When the cursor moves. (Callable on None.) Filters: @@ -234,9 +234,9 @@ class Buffer(object): assert completer is None or isinstance(completer, Completer) assert auto_suggest is None or isinstance(auto_suggest, AutoSuggest) assert history is None or isinstance(history, History) - assert on_text_changed is None or callable(on_text_changed) - assert on_text_insert is None or callable(on_text_insert) - assert on_cursor_position_changed is None or callable(on_cursor_position_changed) + assert on_text_changed is None or callable(on_text_changed) + assert on_text_insert is None or callable(on_text_insert) + assert on_cursor_position_changed is None or callable(on_cursor_position_changed) self.completer = completer self.auto_suggest = auto_suggest @@ -250,9 +250,9 @@ class Buffer(object): self.enable_history_search = enable_history_search self.read_only = read_only - # Text width. (For wrapping, used by the Vi 'gq' operator.) - self.text_width = 0 - + # Text width. (For wrapping, used by the Vi 'gq' operator.) + self.text_width = 0 + #: The command buffer history. # Note that we shouldn't use a lazy 'or' here. bool(history) could be # False when empty. @@ -261,13 +261,13 @@ class Buffer(object): self.__cursor_position = 0 # Events - self.on_text_changed = Event(self, on_text_changed) - self.on_text_insert = Event(self, on_text_insert) - self.on_cursor_position_changed = Event(self, on_cursor_position_changed) - - # Document cache. (Avoid creating new Document instances.) - self._document_cache = FastDictCache(Document, size=10) + self.on_text_changed = Event(self, on_text_changed) + self.on_text_insert = Event(self, on_text_insert) + self.on_cursor_position_changed = Event(self, on_cursor_position_changed) + # Document cache. (Avoid creating new Document instances.) + self._document_cache = FastDictCache(Document, size=10) + self.reset(initial_document=initial_document) def reset(self, initial_document=None, append_to_history=False): @@ -290,20 +290,20 @@ class Buffer(object): # State of the selection. self.selection_state = None - # Multiple cursor mode. (When we press 'I' or 'A' in visual-block mode, - # we can insert text on multiple lines at once. This is implemented by - # using multiple cursors.) - self.multiple_cursor_positions = [] - - # When doing consecutive up/down movements, prefer to stay at this column. - self.preferred_column = None - + # Multiple cursor mode. (When we press 'I' or 'A' in visual-block mode, + # we can insert text on multiple lines at once. This is implemented by + # using multiple cursors.) + self.multiple_cursor_positions = [] + + # When doing consecutive up/down movements, prefer to stay at this column. + self.preferred_column = None + # State of complete browser self.complete_state = None # For interactive completion through Ctrl-N/Ctrl-P. - # State of Emacs yank-nth-arg completion. - self.yank_nth_arg_state = None # for yank-nth-arg. - + # State of Emacs yank-nth-arg completion. + self.yank_nth_arg_state = None # for yank-nth-arg. + # Remember the document that we had *right before* the last paste # operation. This is used for rotating through the kill ring. self.document_before_paste = None @@ -332,24 +332,24 @@ class Buffer(object): def _set_text(self, value): """ set text at current working_index. Return whether it changed. """ - working_index = self.working_index - working_lines = self._working_lines - - original_value = working_lines[working_index] - working_lines[working_index] = value - - # Return True when this text has been changed. - if len(value) != len(original_value): - # For Python 2, it seems that when two strings have a different - # length and one is a prefix of the other, Python still scans - # character by character to see whether the strings are different. - # (Some benchmarking showed significant differences for big - # documents. >100,000 of lines.) - return True - elif value != original_value: - return True - return False - + working_index = self.working_index + working_lines = self._working_lines + + original_value = working_lines[working_index] + working_lines[working_index] = value + + # Return True when this text has been changed. + if len(value) != len(original_value): + # For Python 2, it seems that when two strings have a different + # length and one is a prefix of the other, Python still scans + # character by character to see whether the strings are different. + # (Some benchmarking showed significant differences for big + # documents. >100,000 of lines.) + return True + elif value != original_value: + return True + return False + def _set_cursor_position(self, value): """ Set cursor position. Return whether it changed. """ original_position = self.__cursor_position @@ -415,11 +415,11 @@ class Buffer(object): self.validation_error = None self.validation_state = ValidationState.UNKNOWN self.complete_state = None - self.yank_nth_arg_state = None + self.yank_nth_arg_state = None self.document_before_paste = None self.selection_state = None self.suggestion = None - self.preferred_column = None + self.preferred_column = None # fire 'on_text_changed' event. self.on_text_changed.fire() @@ -429,13 +429,13 @@ class Buffer(object): self.validation_error = None self.validation_state = ValidationState.UNKNOWN self.complete_state = None - self.yank_nth_arg_state = None + self.yank_nth_arg_state = None self.document_before_paste = None - # Unset preferred_column. (Will be set after the cursor movement, if - # required.) - self.preferred_column = None - + # Unset preferred_column. (Will be set after the cursor movement, if + # required.) + self.preferred_column = None + # Note that the cursor position can change if we have a selection the # new position of the cursor determines the end of the selection. @@ -446,10 +446,10 @@ class Buffer(object): def document(self): """ Return :class:`~prompt_toolkit.document.Document` instance from the - current text, cursor position and selection state. + current text, cursor position and selection state. """ - return self._document_cache[ - self.text, self.cursor_position, self.selection_state] + return self._document_cache[ + self.text, self.cursor_position, self.selection_state] @document.setter def document(self, value): @@ -534,20 +534,20 @@ class Buffer(object): return '\n'.join(lines) - def transform_current_line(self, transform_callback): - """ - Apply the given transformation function to the current line. - - :param transform_callback: callable that takes a string and return a new string. - """ - document = self.document - a = document.cursor_position + document.get_start_of_line_position() - b = document.cursor_position + document.get_end_of_line_position() - self.text = ( - document.text[:a] + - transform_callback(document.text[a:b]) + - document.text[b:]) - + def transform_current_line(self, transform_callback): + """ + Apply the given transformation function to the current line. + + :param transform_callback: callable that takes a string and return a new string. + """ + document = self.document + a = document.cursor_position + document.get_start_of_line_position() + b = document.cursor_position + document.get_end_of_line_position() + self.text = ( + document.text[:a] + + transform_callback(document.text[a:b]) + + document.text[b:]) + def transform_region(self, from_, to, transform_callback): """ Transform a part of the input string. @@ -573,23 +573,23 @@ class Buffer(object): def cursor_up(self, count=1): """ (for multiline edit). Move cursor to the previous line. """ - original_column = self.preferred_column or self.document.cursor_position_col - self.cursor_position += self.document.get_cursor_up_position( - count=count, preferred_column=original_column) - - # Remember the original column for the next up/down movement. - self.preferred_column = original_column + original_column = self.preferred_column or self.document.cursor_position_col + self.cursor_position += self.document.get_cursor_up_position( + count=count, preferred_column=original_column) + # Remember the original column for the next up/down movement. + self.preferred_column = original_column + def cursor_down(self, count=1): """ (for multiline edit). Move cursor to the next line. """ - original_column = self.preferred_column or self.document.cursor_position_col - self.cursor_position += self.document.get_cursor_down_position( - count=count, preferred_column=original_column) - - # Remember the original column for the next up/down movement. - self.preferred_column = original_column + original_column = self.preferred_column or self.document.cursor_position_col + self.cursor_position += self.document.get_cursor_down_position( + count=count, preferred_column=original_column) - def auto_up(self, count=1, go_to_start_of_line_if_history_changes=False): + # Remember the original column for the next up/down movement. + self.preferred_column = original_column + + def auto_up(self, count=1, go_to_start_of_line_if_history_changes=False): """ If we're not on the first line (of a multiline input) go a line up, otherwise go back in history. (If nothing is selected.) @@ -597,15 +597,15 @@ class Buffer(object): if self.complete_state: self.complete_previous(count=count) elif self.document.cursor_position_row > 0: - self.cursor_up(count=count) + self.cursor_up(count=count) elif not self.selection_state: self.history_backward(count=count) - # Go to the start of the line? - if go_to_start_of_line_if_history_changes: - self.cursor_position += self.document.get_start_of_line_position() - - def auto_down(self, count=1, go_to_start_of_line_if_history_changes=False): + # Go to the start of the line? + if go_to_start_of_line_if_history_changes: + self.cursor_position += self.document.get_start_of_line_position() + + def auto_down(self, count=1, go_to_start_of_line_if_history_changes=False): """ If we're not on the last line (of a multiline input) go a line down, otherwise go forward in history. (If nothing is selected.) @@ -613,18 +613,18 @@ class Buffer(object): if self.complete_state: self.complete_next(count=count) elif self.document.cursor_position_row < self.document.line_count - 1: - self.cursor_down(count=count) + self.cursor_down(count=count) elif not self.selection_state: self.history_forward(count=count) - # Go to the start of the line? - if go_to_start_of_line_if_history_changes: - self.cursor_position += self.document.get_start_of_line_position() - + # Go to the start of the line? + if go_to_start_of_line_if_history_changes: + self.cursor_position += self.document.get_start_of_line_position() + def delete_before_cursor(self, count=1): """ - Delete specified number of characters before cursor and return the - deleted text. + Delete specified number of characters before cursor and return the + deleted text. """ assert count >= 0 deleted = '' @@ -642,7 +642,7 @@ class Buffer(object): def delete(self, count=1): """ - Delete specified number of characters and Return the deleted text. + Delete specified number of characters and Return the deleted text. """ if self.cursor_position < len(self.text): deleted = self.document.text_after_cursor[:count] @@ -652,7 +652,7 @@ class Buffer(object): else: return '' - def join_next_line(self, separator=' '): + def join_next_line(self, separator=' '): """ Join the next line to the current one by deleting the line ending after the current line. @@ -662,10 +662,10 @@ class Buffer(object): self.delete() # Remove spaces. - self.text = (self.document.text_before_cursor + separator + + self.text = (self.document.text_before_cursor + separator + self.document.text_after_cursor.lstrip(' ')) - def join_selected_lines(self, separator=' '): + def join_selected_lines(self, separator=' '): """ Join the selected lines. """ @@ -679,7 +679,7 @@ class Buffer(object): after = self.text[to:] # Replace leading spaces with just one space. - lines = [l.lstrip(' ') + separator for l in lines] + lines = [l.lstrip(' ') + separator for l in lines] # Set new document. self.document = Document(text=before + ''.join(lines) + after, @@ -906,63 +906,63 @@ class Buffer(object): if found_something: self.cursor_position = len(self.text) - def yank_nth_arg(self, n=None, _yank_last_arg=False): - """ - Pick nth word from previous history entry (depending on current - `yank_nth_arg_state`) and insert it at current position. Rotate through - history if called repeatedly. If no `n` has been given, take the first - argument. (The second word.) - - :param n: (None or int), The index of the word from the previous line - to take. - """ - assert n is None or isinstance(n, int) - - if not len(self.history): - return - - # Make sure we have a `YankNthArgState`. - if self.yank_nth_arg_state is None: - state = YankNthArgState(n=-1 if _yank_last_arg else 1) - else: - state = self.yank_nth_arg_state - - if n is not None: - state.n = n - - # Get new history position. - new_pos = state.history_position - 1 - if -new_pos > len(self.history): - new_pos = -1 - - # Take argument from line. - line = self.history[new_pos] - - words = [w.strip() for w in _QUOTED_WORDS_RE.split(line)] - words = [w for w in words if w] - try: - word = words[state.n] - except IndexError: - word = '' - - # Insert new argument. - if state.previous_inserted_word: - self.delete_before_cursor(len(state.previous_inserted_word)) - self.insert_text(word) - - # Save state again for next completion. (Note that the 'insert' - # operation from above clears `self.yank_nth_arg_state`.) - state.previous_inserted_word = word - state.history_position = new_pos - self.yank_nth_arg_state = state - - def yank_last_arg(self, n=None): - """ - Like `yank_nth_arg`, but if no argument has been given, yank the last - word by default. - """ - self.yank_nth_arg(n=n, _yank_last_arg=True) - + def yank_nth_arg(self, n=None, _yank_last_arg=False): + """ + Pick nth word from previous history entry (depending on current + `yank_nth_arg_state`) and insert it at current position. Rotate through + history if called repeatedly. If no `n` has been given, take the first + argument. (The second word.) + + :param n: (None or int), The index of the word from the previous line + to take. + """ + assert n is None or isinstance(n, int) + + if not len(self.history): + return + + # Make sure we have a `YankNthArgState`. + if self.yank_nth_arg_state is None: + state = YankNthArgState(n=-1 if _yank_last_arg else 1) + else: + state = self.yank_nth_arg_state + + if n is not None: + state.n = n + + # Get new history position. + new_pos = state.history_position - 1 + if -new_pos > len(self.history): + new_pos = -1 + + # Take argument from line. + line = self.history[new_pos] + + words = [w.strip() for w in _QUOTED_WORDS_RE.split(line)] + words = [w for w in words if w] + try: + word = words[state.n] + except IndexError: + word = '' + + # Insert new argument. + if state.previous_inserted_word: + self.delete_before_cursor(len(state.previous_inserted_word)) + self.insert_text(word) + + # Save state again for next completion. (Note that the 'insert' + # operation from above clears `self.yank_nth_arg_state`.) + state.previous_inserted_word = word + state.history_position = new_pos + self.yank_nth_arg_state = state + + def yank_last_arg(self, n=None): + """ + Like `yank_nth_arg`, but if no argument has been given, yank the last + word by default. + """ + self.yank_nth_arg(n=n, _yank_last_arg=True) + def start_selection(self, selection_type=SelectionType.CHARACTERS): """ Take the current cursor position as the start of this selection. @@ -1041,21 +1041,21 @@ class Buffer(object): :param fire_event: Fire `on_text_insert` event. This is mainly used to trigger autocompletion while typing. """ - # Original text & cursor position. - otext = self.text - ocpos = self.cursor_position - + # Original text & cursor position. + otext = self.text + ocpos = self.cursor_position + # In insert/text mode. if overwrite: - # Don't overwrite the newline itself. Just before the line ending, - # it should act like insert mode. - overwritten_text = otext[ocpos:ocpos + len(data)] + # Don't overwrite the newline itself. Just before the line ending, + # it should act like insert mode. + overwritten_text = otext[ocpos:ocpos + len(data)] if '\n' in overwritten_text: overwritten_text = overwritten_text[:overwritten_text.find('\n')] - self.text = otext[:ocpos] + data + otext[ocpos + len(overwritten_text):] + self.text = otext[:ocpos] + data + otext[ocpos + len(overwritten_text):] else: - self.text = otext[:ocpos] + data + otext[ocpos:] + self.text = otext[:ocpos] + data + otext[ocpos:] if move_cursor: self.cursor_position += len(data) @@ -1192,7 +1192,7 @@ class Buffer(object): for _ in range(count): result = search_once(working_index, document) if result is None: - return # Nothing found. + return # Nothing found. else: working_index, document = result @@ -1201,10 +1201,10 @@ class Buffer(object): def document_for_search(self, search_state): """ Return a :class:`~prompt_toolkit.document.Document` instance that has - the text/cursor position for this search, if we would apply it. This - will be used in the - :class:`~prompt_toolkit.layout.controls.BufferControl` to display - feedback while searching. + the text/cursor position for this search, if we would apply it. This + will be used in the + :class:`~prompt_toolkit.layout.controls.BufferControl` to display + feedback while searching. """ search_result = self._search(search_state, include_current_position=True) @@ -1213,37 +1213,37 @@ class Buffer(object): else: working_index, cursor_position = search_result - # Keep selection, when `working_index` was not changed. - if working_index == self.working_index: - selection = self.selection_state - else: - selection = None - - return Document(self._working_lines[working_index], - cursor_position, selection=selection) - - def get_search_position(self, search_state, include_current_position=True, count=1): - """ - Get the cursor position for this search. - (This operation won't change the `working_index`. It's won't go through - the history. Vi text objects can't span multiple items.) - """ - search_result = self._search( - search_state, include_current_position=include_current_position, count=count) - - if search_result is None: - return self.cursor_position - else: - working_index, cursor_position = search_result - return cursor_position - + # Keep selection, when `working_index` was not changed. + if working_index == self.working_index: + selection = self.selection_state + else: + selection = None + + return Document(self._working_lines[working_index], + cursor_position, selection=selection) + + def get_search_position(self, search_state, include_current_position=True, count=1): + """ + Get the cursor position for this search. + (This operation won't change the `working_index`. It's won't go through + the history. Vi text objects can't span multiple items.) + """ + search_result = self._search( + search_state, include_current_position=include_current_position, count=count) + + if search_result is None: + return self.cursor_position + else: + working_index, cursor_position = search_result + return cursor_position + def apply_search(self, search_state, include_current_position=True, count=1): """ Apply search. If something is found, set `working_index` and `cursor_position`. """ - search_result = self._search( - search_state, include_current_position=include_current_position, count=count) + search_result = self._search( + search_state, include_current_position=include_current_position, count=count) if search_result is not None: working_index, cursor_position = search_result @@ -1368,48 +1368,48 @@ def unindent(buffer, from_row, to_row, count=1): # Go to the start of the line. buffer.cursor_position += buffer.document.get_start_of_line_position(after_whitespace=True) - - -def reshape_text(buffer, from_row, to_row): - """ - Reformat text, taking the width into account. - `to_row` is included. - (Vi 'gq' operator.) - """ - lines = buffer.text.splitlines(True) - lines_before = lines[:from_row] - lines_after = lines[to_row + 1:] - lines_to_reformat = lines[from_row:to_row + 1] - - if lines_to_reformat: - # Take indentation from the first line. - length = re.search(r'^\s*', lines_to_reformat[0]).end() - indent = lines_to_reformat[0][:length].replace('\n', '') - - # Now, take all the 'words' from the lines to be reshaped. - words = ''.join(lines_to_reformat).split() - - # And reshape. - width = (buffer.text_width or 80) - len(indent) - reshaped_text = [indent] - current_width = 0 - for w in words: - if current_width: - if len(w) + current_width + 1 > width: - reshaped_text.append('\n') - reshaped_text.append(indent) - current_width = 0 - else: - reshaped_text.append(' ') - current_width += 1 - - reshaped_text.append(w) - current_width += len(w) - - if reshaped_text[-1] != '\n': - reshaped_text.append('\n') - - # Apply result. - buffer.document = Document( - text=''.join(lines_before + reshaped_text + lines_after), - cursor_position=len(''.join(lines_before + reshaped_text))) + + +def reshape_text(buffer, from_row, to_row): + """ + Reformat text, taking the width into account. + `to_row` is included. + (Vi 'gq' operator.) + """ + lines = buffer.text.splitlines(True) + lines_before = lines[:from_row] + lines_after = lines[to_row + 1:] + lines_to_reformat = lines[from_row:to_row + 1] + + if lines_to_reformat: + # Take indentation from the first line. + length = re.search(r'^\s*', lines_to_reformat[0]).end() + indent = lines_to_reformat[0][:length].replace('\n', '') + + # Now, take all the 'words' from the lines to be reshaped. + words = ''.join(lines_to_reformat).split() + + # And reshape. + width = (buffer.text_width or 80) - len(indent) + reshaped_text = [indent] + current_width = 0 + for w in words: + if current_width: + if len(w) + current_width + 1 > width: + reshaped_text.append('\n') + reshaped_text.append(indent) + current_width = 0 + else: + reshaped_text.append(' ') + current_width += 1 + + reshaped_text.append(w) + current_width += len(w) + + if reshaped_text[-1] != '\n': + reshaped_text.append('\n') + + # Apply result. + buffer.document = Document( + text=''.join(lines_before + reshaped_text + lines_after), + cursor_position=len(''.join(lines_before + reshaped_text))) diff --git a/contrib/python/prompt-toolkit/py2/prompt_toolkit/cache.py b/contrib/python/prompt-toolkit/py2/prompt_toolkit/cache.py index 55c7369c9c..5fe397a75b 100644 --- a/contrib/python/prompt-toolkit/py2/prompt_toolkit/cache.py +++ b/contrib/python/prompt-toolkit/py2/prompt_toolkit/cache.py @@ -1,111 +1,111 @@ -from __future__ import unicode_literals -from collections import deque -from functools import wraps - -__all__ = ( - 'SimpleCache', - 'FastDictCache', - 'memoized', -) - - -class SimpleCache(object): - """ - Very simple cache that discards the oldest item when the cache size is - exceeded. - - :param maxsize: Maximum size of the cache. (Don't make it too big.) - """ - def __init__(self, maxsize=8): - assert isinstance(maxsize, int) and maxsize > 0 - - self._data = {} - self._keys = deque() - self.maxsize = maxsize - - def get(self, key, getter_func): - """ - Get object from the cache. - If not found, call `getter_func` to resolve it, and put that on the top - of the cache instead. - """ - # Look in cache first. - try: - return self._data[key] - except KeyError: - # Not found? Get it. - value = getter_func() - self._data[key] = value - self._keys.append(key) - - # Remove the oldest key when the size is exceeded. - if len(self._data) > self.maxsize: - key_to_remove = self._keys.popleft() - if key_to_remove in self._data: - del self._data[key_to_remove] - - return value - - def clear(self): - " Clear cache. " - self._data = {} - self._keys = deque() - - -class FastDictCache(dict): - """ - Fast, lightweight cache which keeps at most `size` items. - It will discard the oldest items in the cache first. - - The cache is a dictionary, which doesn't keep track of access counts. - It is perfect to cache little immutable objects which are not expensive to - create, but where a dictionary lookup is still much faster than an object - instantiation. - - :param get_value: Callable that's called in case of a missing key. - """ - # NOTE: This cache is used to cache `prompt_toolkit.layout.screen.Char` and - # `prompt_toolkit.Document`. Make sure to keep this really lightweight. - # Accessing the cache should stay faster than instantiating new - # objects. - # (Dictionary lookups are really fast.) - # SimpleCache is still required for cases where the cache key is not - # the same as the arguments given to the function that creates the - # value.) - def __init__(self, get_value=None, size=1000000): - assert callable(get_value) - assert isinstance(size, int) and size > 0 - - self._keys = deque() - self.get_value = get_value - self.size = size - - def __missing__(self, key): - # Remove the oldest key when the size is exceeded. - if len(self) > self.size: - key_to_remove = self._keys.popleft() - if key_to_remove in self: - del self[key_to_remove] - - result = self.get_value(*key) - self[key] = result - self._keys.append(key) - return result - - -def memoized(maxsize=1024): - """ - Momoization decorator for immutable classes and pure functions. - """ - cache = SimpleCache(maxsize=maxsize) - - def decorator(obj): - @wraps(obj) - def new_callable(*a, **kw): - def create_new(): - return obj(*a, **kw) - - key = (a, tuple(kw.items())) - return cache.get(key, create_new) - return new_callable - return decorator +from __future__ import unicode_literals +from collections import deque +from functools import wraps + +__all__ = ( + 'SimpleCache', + 'FastDictCache', + 'memoized', +) + + +class SimpleCache(object): + """ + Very simple cache that discards the oldest item when the cache size is + exceeded. + + :param maxsize: Maximum size of the cache. (Don't make it too big.) + """ + def __init__(self, maxsize=8): + assert isinstance(maxsize, int) and maxsize > 0 + + self._data = {} + self._keys = deque() + self.maxsize = maxsize + + def get(self, key, getter_func): + """ + Get object from the cache. + If not found, call `getter_func` to resolve it, and put that on the top + of the cache instead. + """ + # Look in cache first. + try: + return self._data[key] + except KeyError: + # Not found? Get it. + value = getter_func() + self._data[key] = value + self._keys.append(key) + + # Remove the oldest key when the size is exceeded. + if len(self._data) > self.maxsize: + key_to_remove = self._keys.popleft() + if key_to_remove in self._data: + del self._data[key_to_remove] + + return value + + def clear(self): + " Clear cache. " + self._data = {} + self._keys = deque() + + +class FastDictCache(dict): + """ + Fast, lightweight cache which keeps at most `size` items. + It will discard the oldest items in the cache first. + + The cache is a dictionary, which doesn't keep track of access counts. + It is perfect to cache little immutable objects which are not expensive to + create, but where a dictionary lookup is still much faster than an object + instantiation. + + :param get_value: Callable that's called in case of a missing key. + """ + # NOTE: This cache is used to cache `prompt_toolkit.layout.screen.Char` and + # `prompt_toolkit.Document`. Make sure to keep this really lightweight. + # Accessing the cache should stay faster than instantiating new + # objects. + # (Dictionary lookups are really fast.) + # SimpleCache is still required for cases where the cache key is not + # the same as the arguments given to the function that creates the + # value.) + def __init__(self, get_value=None, size=1000000): + assert callable(get_value) + assert isinstance(size, int) and size > 0 + + self._keys = deque() + self.get_value = get_value + self.size = size + + def __missing__(self, key): + # Remove the oldest key when the size is exceeded. + if len(self) > self.size: + key_to_remove = self._keys.popleft() + if key_to_remove in self: + del self[key_to_remove] + + result = self.get_value(*key) + self[key] = result + self._keys.append(key) + return result + + +def memoized(maxsize=1024): + """ + Momoization decorator for immutable classes and pure functions. + """ + cache = SimpleCache(maxsize=maxsize) + + def decorator(obj): + @wraps(obj) + def new_callable(*a, **kw): + def create_new(): + return obj(*a, **kw) + + key = (a, tuple(kw.items())) + return cache.get(key, create_new) + return new_callable + return decorator diff --git a/contrib/python/prompt-toolkit/py2/prompt_toolkit/clipboard/in_memory.py b/contrib/python/prompt-toolkit/py2/prompt_toolkit/clipboard/in_memory.py index 081666ab80..cef6ea1300 100644 --- a/contrib/python/prompt-toolkit/py2/prompt_toolkit/clipboard/in_memory.py +++ b/contrib/python/prompt-toolkit/py2/prompt_toolkit/clipboard/in_memory.py @@ -15,7 +15,7 @@ class InMemoryClipboard(Clipboard): This implements a kill-ring, for Emacs mode. """ def __init__(self, data=None, max_size=60): - assert data is None or isinstance(data, ClipboardData) + assert data is None or isinstance(data, ClipboardData) assert max_size >= 1 self.max_size = max_size diff --git a/contrib/python/prompt-toolkit/py2/prompt_toolkit/completion.py b/contrib/python/prompt-toolkit/py2/prompt_toolkit/completion.py index 339738ab97..8807f7b34e 100644 --- a/contrib/python/prompt-toolkit/py2/prompt_toolkit/completion.py +++ b/contrib/python/prompt-toolkit/py2/prompt_toolkit/completion.py @@ -40,13 +40,13 @@ class Completion(object): assert self.start_position <= 0 def __repr__(self): - if self.display == self.text: - return '%s(text=%r, start_position=%r)' % ( - self.__class__.__name__, self.text, self.start_position) - else: - return '%s(text=%r, start_position=%r, display=%r)' % ( - self.__class__.__name__, self.text, self.start_position, - self.display) + if self.display == self.text: + return '%s(text=%r, start_position=%r)' % ( + self.__class__.__name__, self.text, self.start_position) + else: + return '%s(text=%r, start_position=%r, display=%r)' % ( + self.__class__.__name__, self.text, self.start_position, + self.display) def __eq__(self, other): return ( @@ -71,22 +71,22 @@ class Completion(object): else: return '' - def new_completion_from_position(self, position): - """ - (Only for internal use!) - Get a new completion by splitting this one. Used by - `CommandLineInterface` when it needs to have a list of new completions - after inserting the common prefix. - """ - assert isinstance(position, int) and position - self.start_position >= 0 - - return Completion( - text=self.text[position - self.start_position:], - display=self.display, - display_meta=self._display_meta, - get_display_meta=self._get_display_meta) - - + def new_completion_from_position(self, position): + """ + (Only for internal use!) + Get a new completion by splitting this one. Used by + `CommandLineInterface` when it needs to have a list of new completions + after inserting the common prefix. + """ + assert isinstance(position, int) and position - self.start_position >= 0 + + return Completion( + text=self.text[position - self.start_position:], + display=self.display, + display_meta=self._display_meta, + get_display_meta=self._get_display_meta) + + class CompleteEvent(object): """ Event that called the completer. @@ -140,18 +140,18 @@ def get_common_complete_suffix(document, completions): end = completion.text[:-completion.start_position] return document.text_before_cursor.endswith(end) - completions2 = [c for c in completions if doesnt_change_before_cursor(c)] - - # When there is at least one completion that changes the text before the - # cursor, don't return any common part. - if len(completions2) != len(completions): - return '' + completions2 = [c for c in completions if doesnt_change_before_cursor(c)] + # When there is at least one completion that changes the text before the + # cursor, don't return any common part. + if len(completions2) != len(completions): + return '' + # Return the common prefix. def get_suffix(completion): return completion.text[-completion.start_position:] - return _commonprefix([get_suffix(c) for c in completions2]) + return _commonprefix([get_suffix(c) for c in completions2]) def _commonprefix(strings): diff --git a/contrib/python/prompt-toolkit/py2/prompt_toolkit/contrib/completers/filesystem.py b/contrib/python/prompt-toolkit/py2/prompt_toolkit/contrib/completers/filesystem.py index cbd74d8fea..2b37b4e825 100644 --- a/contrib/python/prompt-toolkit/py2/prompt_toolkit/contrib/completers/filesystem.py +++ b/contrib/python/prompt-toolkit/py2/prompt_toolkit/contrib/completers/filesystem.py @@ -80,12 +80,12 @@ class PathCompleter(Completer): # (We don't add them to the `completion`. Users can type it # to trigger the autocompletion themself.) filename += '/' - elif self.only_directories: - continue - - if not self.file_filter(full_name): - continue + elif self.only_directories: + continue + if not self.file_filter(full_name): + continue + yield Completion(completion, 0, display=filename) except OSError: pass diff --git a/contrib/python/prompt-toolkit/py2/prompt_toolkit/contrib/regular_languages/compiler.py b/contrib/python/prompt-toolkit/py2/prompt_toolkit/contrib/regular_languages/compiler.py index 01476bf626..859002ed12 100644 --- a/contrib/python/prompt-toolkit/py2/prompt_toolkit/contrib/regular_languages/compiler.py +++ b/contrib/python/prompt-toolkit/py2/prompt_toolkit/contrib/regular_languages/compiler.py @@ -41,7 +41,7 @@ Partial matches are possible:: from __future__ import unicode_literals import re -from six.moves import range +from six.moves import range from .regex_parser import Any, Sequence, Regex, Variable, Repeat, Lookahead from .regex_parser import parse_regex, tokenize_regex diff --git a/contrib/python/prompt-toolkit/py2/prompt_toolkit/contrib/regular_languages/lexer.py b/contrib/python/prompt-toolkit/py2/prompt_toolkit/contrib/regular_languages/lexer.py index c166d84fd1..f78c9ca446 100644 --- a/contrib/python/prompt-toolkit/py2/prompt_toolkit/contrib/regular_languages/lexer.py +++ b/contrib/python/prompt-toolkit/py2/prompt_toolkit/contrib/regular_languages/lexer.py @@ -3,13 +3,13 @@ the input using a regular grammar with token annotations. """ from __future__ import unicode_literals -from prompt_toolkit.document import Document +from prompt_toolkit.document import Document from prompt_toolkit.layout.lexers import Lexer -from prompt_toolkit.layout.utils import split_lines -from prompt_toolkit.token import Token +from prompt_toolkit.layout.utils import split_lines +from prompt_toolkit.token import Token from .compiler import _CompiledGrammar -from six.moves import range +from six.moves import range __all__ = ( 'GrammarLexer', @@ -40,7 +40,7 @@ class GrammarLexer(Lexer): self.default_token = default_token or Token self.lexers = lexers or {} - def _get_tokens(self, cli, text): + def _get_tokens(self, cli, text): m = self.compiled_grammar.match_prefix(text) if m: @@ -52,15 +52,15 @@ class GrammarLexer(Lexer): lexer = self.lexers.get(v.varname) if lexer: - document = Document(text[v.start:v.stop]) - lexer_tokens_for_line = lexer.lex_document(cli, document) - lexer_tokens = [] - for i in range(len(document.lines)): - lexer_tokens.extend(lexer_tokens_for_line(i)) - lexer_tokens.append((Token, '\n')) - if lexer_tokens: - lexer_tokens.pop() - + document = Document(text[v.start:v.stop]) + lexer_tokens_for_line = lexer.lex_document(cli, document) + lexer_tokens = [] + for i in range(len(document.lines)): + lexer_tokens.extend(lexer_tokens_for_line(i)) + lexer_tokens.append((Token, '\n')) + if lexer_tokens: + lexer_tokens.pop() + i = v.start for t, s in lexer_tokens: for c in s: @@ -77,14 +77,14 @@ class GrammarLexer(Lexer): return characters else: return [(Token, text)] - - def lex_document(self, cli, document): - lines = list(split_lines(self._get_tokens(cli, document.text))) - - def get_line(lineno): - try: - return lines[lineno] - except IndexError: - return [] - - return get_line + + def lex_document(self, cli, document): + lines = list(split_lines(self._get_tokens(cli, document.text))) + + def get_line(lineno): + try: + return lines[lineno] + except IndexError: + return [] + + return get_line diff --git a/contrib/python/prompt-toolkit/py2/prompt_toolkit/contrib/regular_languages/validation.py b/contrib/python/prompt-toolkit/py2/prompt_toolkit/contrib/regular_languages/validation.py index d5f8cfccc6..947765f5b1 100644 --- a/contrib/python/prompt-toolkit/py2/prompt_toolkit/contrib/regular_languages/validation.py +++ b/contrib/python/prompt-toolkit/py2/prompt_toolkit/contrib/regular_languages/validation.py @@ -50,7 +50,7 @@ class GrammarValidator(Validator): validator.validate(inner_document) except ValidationError as e: raise ValidationError( - cursor_position=v.start + e.cursor_position, + cursor_position=v.start + e.cursor_position, message=e.message) else: raise ValidationError(cursor_position=len(document.text), diff --git a/contrib/python/prompt-toolkit/py2/prompt_toolkit/contrib/telnet/server.py b/contrib/python/prompt-toolkit/py2/prompt_toolkit/contrib/telnet/server.py index d75a9572eb..ad61453d17 100644 --- a/contrib/python/prompt-toolkit/py2/prompt_toolkit/contrib/telnet/server.py +++ b/contrib/python/prompt-toolkit/py2/prompt_toolkit/contrib/telnet/server.py @@ -121,7 +121,7 @@ class TelnetConnection(object): def get_size(): return self.size self.stdout = _ConnectionStdout(conn, encoding=encoding) - self.vt100_output = Vt100_Output(self.stdout, get_size, write_binary=False) + self.vt100_output = Vt100_Output(self.stdout, get_size, write_binary=False) # Create an eventloop (adaptor) for the CommandLineInterface. self.eventloop = _TelnetEventLoopInterface(server) diff --git a/contrib/python/prompt-toolkit/py2/prompt_toolkit/contrib/validators/base.py b/contrib/python/prompt-toolkit/py2/prompt_toolkit/contrib/validators/base.py index 16c1539c52..a81fb91e63 100644 --- a/contrib/python/prompt-toolkit/py2/prompt_toolkit/contrib/validators/base.py +++ b/contrib/python/prompt-toolkit/py2/prompt_toolkit/contrib/validators/base.py @@ -21,7 +21,7 @@ class SentenceValidator(Validator): self.move_cursor_to_end = move_cursor_to_end if ignore_case: - self.sentences = set([s.lower() for s in self.sentences]) + self.sentences = set([s.lower() for s in self.sentences]) def validate(self, document): if document.text not in self.sentences: @@ -30,5 +30,5 @@ class SentenceValidator(Validator): else: index = 0 - raise ValidationError(cursor_position=index, - message=self.error_message) + raise ValidationError(cursor_position=index, + message=self.error_message) diff --git a/contrib/python/prompt-toolkit/py2/prompt_toolkit/document.py b/contrib/python/prompt-toolkit/py2/prompt_toolkit/document.py index 25d817ddd0..60b4108a53 100644 --- a/contrib/python/prompt-toolkit/py2/prompt_toolkit/document.py +++ b/contrib/python/prompt-toolkit/py2/prompt_toolkit/document.py @@ -1,14 +1,14 @@ """ -The `Document` that implements all the text operations/querying. +The `Document` that implements all the text operations/querying. """ from __future__ import unicode_literals -import bisect +import bisect import re import six import string -import weakref -from six.moves import range, map +import weakref +from six.moves import range, map from .selection import SelectionType, SelectionState, PasteMode from .clipboard import ClipboardData @@ -30,41 +30,41 @@ _FIND_BIG_WORD_RE = re.compile(r'([^\s]+)') _FIND_CURRENT_BIG_WORD_RE = re.compile(r'^([^\s]+)') _FIND_CURRENT_BIG_WORD_INCLUDE_TRAILING_WHITESPACE_RE = re.compile(r'^([^\s]+\s*)') -# Share the Document._cache between all Document instances. -# (Document instances are considered immutable. That means that if another -# `Document` is constructed with the same text, it should have the same -# `_DocumentCache`.) -_text_to_document_cache = weakref.WeakValueDictionary() # Maps document.text to DocumentCache instance. - - -class _ImmutableLineList(list): - """ - Some protection for our 'lines' list, which is assumed to be immutable in the cache. - (Useful for detecting obvious bugs.) - """ - def _error(self, *a, **kw): - raise NotImplementedError('Attempt to modifiy an immutable list.') - - __setitem__ = _error - append = _error - clear = _error - extend = _error - insert = _error - pop = _error - remove = _error - reverse = _error - sort = _error - - -class _DocumentCache(object): - def __init__(self): - #: List of lines for the Document text. - self.lines = None - - #: List of index positions, pointing to the start of all the lines. - self.line_indexes = None - - +# Share the Document._cache between all Document instances. +# (Document instances are considered immutable. That means that if another +# `Document` is constructed with the same text, it should have the same +# `_DocumentCache`.) +_text_to_document_cache = weakref.WeakValueDictionary() # Maps document.text to DocumentCache instance. + + +class _ImmutableLineList(list): + """ + Some protection for our 'lines' list, which is assumed to be immutable in the cache. + (Useful for detecting obvious bugs.) + """ + def _error(self, *a, **kw): + raise NotImplementedError('Attempt to modifiy an immutable list.') + + __setitem__ = _error + append = _error + clear = _error + extend = _error + insert = _error + pop = _error + remove = _error + reverse = _error + sort = _error + + +class _DocumentCache(object): + def __init__(self): + #: List of lines for the Document text. + self.lines = None + + #: List of index positions, pointing to the start of all the lines. + self.line_indexes = None + + class Document(object): """ This is a immutable class around the text and cursor position, and contains @@ -77,7 +77,7 @@ class Document(object): :param cursor_position: int :param selection: :class:`.SelectionState` """ - __slots__ = ('_text', '_cursor_position', '_selection', '_cache') + __slots__ = ('_text', '_cursor_position', '_selection', '_cache') def __init__(self, text='', cursor_position=None, selection=None): assert isinstance(text, six.text_type), 'Got %r' % text @@ -94,46 +94,46 @@ class Document(object): if cursor_position is None: cursor_position = len(text) - # Keep these attributes private. A `Document` really has to be - # considered to be immutable, because otherwise the caching will break - # things. Because of that, we wrap these into read-only properties. - self._text = text - self._cursor_position = cursor_position - self._selection = selection - - # Cache for lines/indexes. (Shared with other Document instances that - # contain the same text. - try: - self._cache = _text_to_document_cache[self.text] - except KeyError: - self._cache = _DocumentCache() - _text_to_document_cache[self.text] = self._cache - - # XX: For some reason, above, we can't use 'WeakValueDictionary.setdefault'. - # This fails in Pypy3. `self._cache` becomes None, because that's what - # 'setdefault' returns. - # self._cache = _text_to_document_cache.setdefault(self.text, _DocumentCache()) - # assert self._cache - + # Keep these attributes private. A `Document` really has to be + # considered to be immutable, because otherwise the caching will break + # things. Because of that, we wrap these into read-only properties. + self._text = text + self._cursor_position = cursor_position + self._selection = selection + + # Cache for lines/indexes. (Shared with other Document instances that + # contain the same text. + try: + self._cache = _text_to_document_cache[self.text] + except KeyError: + self._cache = _DocumentCache() + _text_to_document_cache[self.text] = self._cache + + # XX: For some reason, above, we can't use 'WeakValueDictionary.setdefault'. + # This fails in Pypy3. `self._cache` becomes None, because that's what + # 'setdefault' returns. + # self._cache = _text_to_document_cache.setdefault(self.text, _DocumentCache()) + # assert self._cache + def __repr__(self): return '%s(%r, %r)' % (self.__class__.__name__, self.text, self.cursor_position) @property - def text(self): - " The document text. " - return self._text - - @property - def cursor_position(self): - " The document cursor position. " - return self._cursor_position - - @property - def selection(self): - " :class:`.SelectionState` object. " - return self._selection - - @property + def text(self): + " The document text. " + return self._text + + @property + def cursor_position(self): + " The document cursor position. " + return self._cursor_position + + @property + def selection(self): + " :class:`.SelectionState` object. " + return self._selection + + @property def current_char(self): """ Return character under cursor or an empty string. """ return self._get_char_relative_to_cursor(0) or '' @@ -154,55 +154,55 @@ class Document(object): @property def current_line_before_cursor(self): """ Text from the start of the line until the cursor. """ - _, _, text = self.text_before_cursor.rpartition('\n') - return text + _, _, text = self.text_before_cursor.rpartition('\n') + return text @property def current_line_after_cursor(self): """ Text from the cursor until the end of the line. """ - text, _, _ = self.text_after_cursor.partition('\n') - return text + text, _, _ = self.text_after_cursor.partition('\n') + return text @property def lines(self): - """ - Array of all the lines. - """ + """ + Array of all the lines. + """ # Cache, because this one is reused very often. - if self._cache.lines is None: - self._cache.lines = _ImmutableLineList(self.text.split('\n')) - - return self._cache.lines - - @property - def _line_start_indexes(self): - """ - Array pointing to the start indexes of all the lines. - """ - # Cache, because this is often reused. (If it is used, it's often used - # many times. And this has to be fast for editing big documents!) - if self._cache.line_indexes is None: - # Create list of line lengths. - line_lengths = map(len, self.lines) - - # Calculate cumulative sums. - indexes = [0] - append = indexes.append - pos = 0 + if self._cache.lines is None: + self._cache.lines = _ImmutableLineList(self.text.split('\n')) - for line_length in line_lengths: - pos += line_length + 1 - append(pos) - - # Remove the last item. (This is not a new line.) - if len(indexes) > 1: - indexes.pop() - - self._cache.line_indexes = indexes - - return self._cache.line_indexes + return self._cache.lines @property + def _line_start_indexes(self): + """ + Array pointing to the start indexes of all the lines. + """ + # Cache, because this is often reused. (If it is used, it's often used + # many times. And this has to be fast for editing big documents!) + if self._cache.line_indexes is None: + # Create list of line lengths. + line_lengths = map(len, self.lines) + + # Calculate cumulative sums. + indexes = [0] + append = indexes.append + pos = 0 + + for line_length in line_lengths: + pos += line_length + 1 + append(pos) + + # Remove the last item. (This is not a new line.) + if len(indexes) > 1: + indexes.pop() + + self._cache.line_indexes = indexes + + return self._cache.line_indexes + + @property def lines_from_current(self): """ Array of the lines starting from the current line, until the last line. @@ -256,64 +256,64 @@ class Document(object): """ Current row. (0-based.) """ - row, _ = self._find_line_start_index(self.cursor_position) - return row + row, _ = self._find_line_start_index(self.cursor_position) + return row @property def cursor_position_col(self): """ Current column. (0-based.) """ - # (Don't use self.text_before_cursor to calculate this. Creating - # substrings and doing rsplit is too expensive for getting the cursor - # position.) - _, line_start_index = self._find_line_start_index(self.cursor_position) - return self.cursor_position - line_start_index - - def _find_line_start_index(self, index): - """ - For the index of a character at a certain line, calculate the index of - the first character on that line. - - Return (row, index) tuple. - """ - indexes = self._line_start_indexes - - pos = bisect.bisect_right(indexes, index) - 1 - return pos, indexes[pos] - - def translate_index_to_position(self, index): - """ + # (Don't use self.text_before_cursor to calculate this. Creating + # substrings and doing rsplit is too expensive for getting the cursor + # position.) + _, line_start_index = self._find_line_start_index(self.cursor_position) + return self.cursor_position - line_start_index + + def _find_line_start_index(self, index): + """ + For the index of a character at a certain line, calculate the index of + the first character on that line. + + Return (row, index) tuple. + """ + indexes = self._line_start_indexes + + pos = bisect.bisect_right(indexes, index) - 1 + return pos, indexes[pos] + + def translate_index_to_position(self, index): + """ Given an index for the text, return the corresponding (row, col) tuple. (0-based. Returns (0, 0) for index=0.) """ - # Find start of this line. - row, row_index = self._find_line_start_index(index) - col = index - row_index + # Find start of this line. + row, row_index = self._find_line_start_index(index) + col = index - row_index return row, col - + def translate_row_col_to_index(self, row, col): """ Given a (row, col) tuple, return the corresponding index. (Row and col params are 0-based.) - - Negative row/col values are turned into zero. - """ - try: - result = self._line_start_indexes[row] - line = self.lines[row] - except IndexError: - if row < 0: - result = self._line_start_indexes[0] - line = self.lines[0] - else: - result = self._line_start_indexes[-1] - line = self.lines[-1] - - result += max(0, min(col, len(line))) - + + Negative row/col values are turned into zero. + """ + try: + result = self._line_start_indexes[row] + line = self.lines[row] + except IndexError: + if row < 0: + result = self._line_start_indexes[0] + line = self.lines[0] + else: + result = self._line_start_indexes[-1] + line = self.lines[-1] + + result += max(0, min(col, len(line))) + # Keep in range. (len(self.text) is included, because the cursor can be # right after the end of the text as well.) result = max(0, min(result, len(self.text))) @@ -327,16 +327,16 @@ class Document(object): @property def is_cursor_at_the_end_of_line(self): """ True when the cursor is at the end of this line. """ - return self.current_char in ('\n', '') + return self.current_char in ('\n', '') def has_match_at_current_position(self, sub): """ `True` when this substring is found at the cursor position. """ - return self.text.find(sub, self.cursor_position) == self.cursor_position + return self.text.find(sub, self.cursor_position) == self.cursor_position def find(self, sub, in_current_line=False, include_current_position=False, - ignore_case=False, count=1): + ignore_case=False, count=1): """ Find `text` after the cursor, return position relative to the cursor position. Return `None` if nothing was found. @@ -480,9 +480,9 @@ class Document(object): Return an index relative to the cursor position pointing to the start of the next word. Return `None` if nothing was found. """ - if count < 0: - return self.find_previous_word_beginning(count=-count, WORD=WORD) - + if count < 0: + return self.find_previous_word_beginning(count=-count, WORD=WORD) + regex = _FIND_BIG_WORD_RE if WORD else _FIND_WORD_RE iterator = regex.finditer(self.text_after_cursor) @@ -502,9 +502,9 @@ class Document(object): Return an index relative to the cursor position pointing to the end of the next word. Return `None` if nothing was found. """ - if count < 0: - return self.find_previous_word_ending(count=-count, WORD=WORD) - + if count < 0: + return self.find_previous_word_ending(count=-count, WORD=WORD) + if include_current_position: text = self.text_after_cursor else: @@ -529,11 +529,11 @@ class Document(object): def find_previous_word_beginning(self, count=1, WORD=False): """ Return an index relative to the cursor position pointing to the start - of the previous word. Return `None` if nothing was found. + of the previous word. Return `None` if nothing was found. """ - if count < 0: - return self.find_next_word_beginning(count=-count, WORD=WORD) - + if count < 0: + return self.find_next_word_beginning(count=-count, WORD=WORD) + regex = _FIND_BIG_WORD_RE if WORD else _FIND_WORD_RE iterator = regex.finditer(self.text_before_cursor[::-1]) @@ -544,30 +544,30 @@ class Document(object): except StopIteration: pass - def find_previous_word_ending(self, count=1, WORD=False): - """ - Return an index relative to the cursor position pointing to the end - of the previous word. Return `None` if nothing was found. - """ - if count < 0: - return self.find_next_word_ending(count=-count, WORD=WORD) - - text_before_cursor = self.text_after_cursor[:1] + self.text_before_cursor[::-1] - - regex = _FIND_BIG_WORD_RE if WORD else _FIND_WORD_RE - iterator = regex.finditer(text_before_cursor) - - try: - for i, match in enumerate(iterator): - # Take first match, unless it's the word on which we're right now. - if i == 0 and match.start(1) == 0: - count += 1 - - if i + 1 == count: - return -match.start(1) + 1 - except StopIteration: - pass - + def find_previous_word_ending(self, count=1, WORD=False): + """ + Return an index relative to the cursor position pointing to the end + of the previous word. Return `None` if nothing was found. + """ + if count < 0: + return self.find_next_word_ending(count=-count, WORD=WORD) + + text_before_cursor = self.text_after_cursor[:1] + self.text_before_cursor[::-1] + + regex = _FIND_BIG_WORD_RE if WORD else _FIND_WORD_RE + iterator = regex.finditer(text_before_cursor) + + try: + for i, match in enumerate(iterator): + # Take first match, unless it's the word on which we're right now. + if i == 0 and match.start(1) == 0: + count += 1 + + if i + 1 == count: + return -match.start(1) + 1 + except StopIteration: + pass + def find_next_matching_line(self, match_func, count=1): """ Look downwards for empty lines. @@ -606,119 +606,119 @@ class Document(object): """ Relative position for cursor left. """ - if count < 0: - return self.get_cursor_right_position(-count) - + if count < 0: + return self.get_cursor_right_position(-count) + return - min(self.cursor_position_col, count) def get_cursor_right_position(self, count=1): """ Relative position for cursor_right. """ - if count < 0: - return self.get_cursor_left_position(-count) - + if count < 0: + return self.get_cursor_left_position(-count) + return min(count, len(self.current_line_after_cursor)) - def get_cursor_up_position(self, count=1, preferred_column=None): + def get_cursor_up_position(self, count=1, preferred_column=None): """ Return the relative cursor position (character index) where we would be if the user pressed the arrow-up button. - - :param preferred_column: When given, go to this column instead of - staying at the current column. - """ - assert count >= 1 - column = self.cursor_position_col if preferred_column is None else preferred_column - - return self.translate_row_col_to_index( - max(0, self.cursor_position_row - count), column) - self.cursor_position - - def get_cursor_down_position(self, count=1, preferred_column=None): - """ - Return the relative cursor position (character index) where we would be if the - user pressed the arrow-down button. - - :param preferred_column: When given, go to this column instead of - staying at the current column. + + :param preferred_column: When given, go to this column instead of + staying at the current column. """ assert count >= 1 - column = self.cursor_position_col if preferred_column is None else preferred_column - - return self.translate_row_col_to_index( - self.cursor_position_row + count, column) - self.cursor_position - - def find_enclosing_bracket_right(self, left_ch, right_ch, end_pos=None): - """ - Find the right bracket enclosing current position. Return the relative - position to the cursor position. - - When `end_pos` is given, don't look past the position. - """ - if self.current_char == right_ch: - return 0 - - if end_pos is None: - end_pos = len(self.text) - else: - end_pos = min(len(self.text), end_pos) - - stack = 1 - - # Look forward. - for i in range(self.cursor_position + 1, end_pos): - c = self.text[i] - - if c == left_ch: - stack += 1 - elif c == right_ch: - stack -= 1 - - if stack == 0: - return i - self.cursor_position - - def find_enclosing_bracket_left(self, left_ch, right_ch, start_pos=None): - """ - Find the left bracket enclosing current position. Return the relative - position to the cursor position. - - When `start_pos` is given, don't look past the position. - """ - if self.current_char == left_ch: - return 0 - - if start_pos is None: - start_pos = 0 - else: - start_pos = max(0, start_pos) - - stack = 1 - - # Look backward. - for i in range(self.cursor_position - 1, start_pos - 1, -1): - c = self.text[i] - - if c == right_ch: - stack += 1 - elif c == left_ch: - stack -= 1 - - if stack == 0: - return i - self.cursor_position - - def find_matching_bracket_position(self, start_pos=None, end_pos=None): + column = self.cursor_position_col if preferred_column is None else preferred_column + + return self.translate_row_col_to_index( + max(0, self.cursor_position_row - count), column) - self.cursor_position + + def get_cursor_down_position(self, count=1, preferred_column=None): + """ + Return the relative cursor position (character index) where we would be if the + user pressed the arrow-down button. + + :param preferred_column: When given, go to this column instead of + staying at the current column. + """ + assert count >= 1 + column = self.cursor_position_col if preferred_column is None else preferred_column + + return self.translate_row_col_to_index( + self.cursor_position_row + count, column) - self.cursor_position + + def find_enclosing_bracket_right(self, left_ch, right_ch, end_pos=None): + """ + Find the right bracket enclosing current position. Return the relative + position to the cursor position. + + When `end_pos` is given, don't look past the position. + """ + if self.current_char == right_ch: + return 0 + + if end_pos is None: + end_pos = len(self.text) + else: + end_pos = min(len(self.text), end_pos) + + stack = 1 + + # Look forward. + for i in range(self.cursor_position + 1, end_pos): + c = self.text[i] + + if c == left_ch: + stack += 1 + elif c == right_ch: + stack -= 1 + + if stack == 0: + return i - self.cursor_position + + def find_enclosing_bracket_left(self, left_ch, right_ch, start_pos=None): + """ + Find the left bracket enclosing current position. Return the relative + position to the cursor position. + + When `start_pos` is given, don't look past the position. + """ + if self.current_char == left_ch: + return 0 + + if start_pos is None: + start_pos = 0 + else: + start_pos = max(0, start_pos) + + stack = 1 + + # Look backward. + for i in range(self.cursor_position - 1, start_pos - 1, -1): + c = self.text[i] + + if c == right_ch: + stack += 1 + elif c == left_ch: + stack -= 1 + + if stack == 0: + return i - self.cursor_position + + def find_matching_bracket_position(self, start_pos=None, end_pos=None): """ Return relative cursor position of matching [, (, { or < bracket. - - When `start_pos` or `end_pos` are given. Don't look past the positions. + + When `start_pos` or `end_pos` are given. Don't look past the positions. """ - # Look for a match. + # Look for a match. for A, B in '()', '[]', '{}', '<>': if self.current_char == A: - return self.find_enclosing_bracket_right(A, B, end_pos=end_pos) or 0 + return self.find_enclosing_bracket_right(A, B, end_pos=end_pos) or 0 elif self.current_char == B: - return self.find_enclosing_bracket_left(A, B, start_pos=start_pos) or 0 + return self.find_enclosing_bracket_left(A, B, start_pos=start_pos) or 0 return 0 @@ -746,7 +746,7 @@ class Document(object): """ Relative position for the last non blank character of this line. """ - return len(self.current_line.rstrip()) - self.cursor_position_col - 1 + return len(self.current_line.rstrip()) - self.cursor_position_col - 1 def get_column_cursor_position(self, column): """ @@ -760,7 +760,7 @@ class Document(object): return column - current_column - def selection_range(self): # XXX: shouldn't this return `None` if there is no selection??? + def selection_range(self): # XXX: shouldn't this return `None` if there is no selection??? """ Return (from, to) tuple of the selection. start and end position are included. @@ -800,46 +800,46 @@ class Document(object): else: # In case of a LINES selection, go to the start/end of the lines. if self.selection.type == SelectionType.LINES: - from_ = max(0, self.text.rfind('\n', 0, from_) + 1) + from_ = max(0, self.text.rfind('\n', 0, from_) + 1) - if self.text.find('\n', to) >= 0: - to = self.text.find('\n', to) + if self.text.find('\n', to) >= 0: + to = self.text.find('\n', to) else: - to = len(self.text) - 1 + to = len(self.text) - 1 yield from_, to - def selection_range_at_line(self, row): - """ - If the selection spans a portion of the given line, return a (from, to) tuple. - Otherwise, return None. - """ - if self.selection: - row_start = self.translate_row_col_to_index(row, 0) - row_end = self.translate_row_col_to_index(row, max(0, len(self.lines[row]) - 1)) - - from_, to = sorted([self.cursor_position, self.selection.original_cursor_position]) - - # Take the intersection of the current line and the selection. - intersection_start = max(row_start, from_) - intersection_end = min(row_end, to) - - if intersection_start <= intersection_end: - if self.selection.type == SelectionType.LINES: - intersection_start = row_start - intersection_end = row_end - elif self.selection.type == SelectionType.BLOCK: - _, col1 = self.translate_index_to_position(from_) - _, col2 = self.translate_index_to_position(to) - col1, col2 = sorted([col1, col2]) - intersection_start = self.translate_row_col_to_index(row, col1) - intersection_end = self.translate_row_col_to_index(row, col2) - - _, from_column = self.translate_index_to_position(intersection_start) - _, to_column = self.translate_index_to_position(intersection_end) - - return from_column, to_column - + def selection_range_at_line(self, row): + """ + If the selection spans a portion of the given line, return a (from, to) tuple. + Otherwise, return None. + """ + if self.selection: + row_start = self.translate_row_col_to_index(row, 0) + row_end = self.translate_row_col_to_index(row, max(0, len(self.lines[row]) - 1)) + + from_, to = sorted([self.cursor_position, self.selection.original_cursor_position]) + + # Take the intersection of the current line and the selection. + intersection_start = max(row_start, from_) + intersection_end = min(row_end, to) + + if intersection_start <= intersection_end: + if self.selection.type == SelectionType.LINES: + intersection_start = row_start + intersection_end = row_end + elif self.selection.type == SelectionType.BLOCK: + _, col1 = self.translate_index_to_position(from_) + _, col2 = self.translate_index_to_position(to) + col1, col2 = sorted([col1, col2]) + intersection_start = self.translate_row_col_to_index(row, col1) + intersection_end = self.translate_row_col_to_index(row, col2) + + _, from_column = self.translate_index_to_position(intersection_start) + _, to_column = self.translate_index_to_position(intersection_end) + + return from_column, to_column + def cut_selection(self): """ Return a (:class:`.Document`, :class:`.ClipboardData`) tuple, where the @@ -911,7 +911,7 @@ class Document(object): new_text = '\n'.join(lines) elif data.type == SelectionType.BLOCK: - lines = self.lines[:] + lines = self.lines[:] start_line = self.cursor_position_row start_column = self.cursor_position_col + (0 if before else 1) @@ -941,36 +941,36 @@ class Document(object): return count - def start_of_paragraph(self, count=1, before=False): - """ - Return the start of the current paragraph. (Relative cursor position.) - """ - def match_func(text): - return not text or text.isspace() - - line_index = self.find_previous_matching_line(match_func=match_func, count=count) - - if line_index: - add = 0 if before else 1 - return min(0, self.get_cursor_up_position(count=-line_index) + add) - else: - return -self.cursor_position - - def end_of_paragraph(self, count=1, after=False): - """ - Return the end of the current paragraph. (Relative cursor position.) - """ - def match_func(text): - return not text or text.isspace() - - line_index = self.find_next_matching_line(match_func=match_func, count=count) - - if line_index: - add = 0 if after else 1 - return max(0, self.get_cursor_down_position(count=line_index) - add) - else: - return len(self.text_after_cursor) - + def start_of_paragraph(self, count=1, before=False): + """ + Return the start of the current paragraph. (Relative cursor position.) + """ + def match_func(text): + return not text or text.isspace() + + line_index = self.find_previous_matching_line(match_func=match_func, count=count) + + if line_index: + add = 0 if before else 1 + return min(0, self.get_cursor_up_position(count=-line_index) + add) + else: + return -self.cursor_position + + def end_of_paragraph(self, count=1, after=False): + """ + Return the end of the current paragraph. (Relative cursor position.) + """ + def match_func(text): + return not text or text.isspace() + + line_index = self.find_next_matching_line(match_func=match_func, count=count) + + if line_index: + add = 0 if after else 1 + return max(0, self.get_cursor_down_position(count=line_index) - add) + else: + return len(self.text_after_cursor) + # Modifiers. def insert_after(self, text): diff --git a/contrib/python/prompt-toolkit/py2/prompt_toolkit/enums.py b/contrib/python/prompt-toolkit/py2/prompt_toolkit/enums.py index 6945f44c96..e7c87536eb 100644 --- a/contrib/python/prompt-toolkit/py2/prompt_toolkit/enums.py +++ b/contrib/python/prompt-toolkit/py2/prompt_toolkit/enums.py @@ -6,12 +6,12 @@ class IncrementalSearchDirection(object): BACKWARD = 'BACKWARD' -class EditingMode(object): - # The set of key bindings that is active. - VI = 'VI' - EMACS = 'EMACS' - - +class EditingMode(object): + # The set of key bindings that is active. + VI = 'VI' + EMACS = 'EMACS' + + #: Name of the search buffer. SEARCH_BUFFER = 'SEARCH_BUFFER' diff --git a/contrib/python/prompt-toolkit/py2/prompt_toolkit/eventloop/asyncio_posix.py b/contrib/python/prompt-toolkit/py2/prompt_toolkit/eventloop/asyncio_posix.py index 426ed96f67..737ca0ec00 100644 --- a/contrib/python/prompt-toolkit/py2/prompt_toolkit/eventloop/asyncio_posix.py +++ b/contrib/python/prompt-toolkit/py2/prompt_toolkit/eventloop/asyncio_posix.py @@ -67,10 +67,10 @@ class PosixAsyncioEventLoop(EventLoop): inputstream.feed(data) timeout.reset() - # Quit when the input stream was closed. - if stdin_reader.closed: - self.stop() - + # Quit when the input stream was closed. + if stdin_reader.closed: + self.stop() + self.loop.add_reader(stdin.fileno(), stdin_ready) # Block this coroutine until stop() has been called. diff --git a/contrib/python/prompt-toolkit/py2/prompt_toolkit/eventloop/asyncio_win32.py b/contrib/python/prompt-toolkit/py2/prompt_toolkit/eventloop/asyncio_win32.py index 45f5f52679..6e4e2ca9e7 100644 --- a/contrib/python/prompt-toolkit/py2/prompt_toolkit/eventloop/asyncio_win32.py +++ b/contrib/python/prompt-toolkit/py2/prompt_toolkit/eventloop/asyncio_win32.py @@ -66,8 +66,8 @@ class Win32AsyncioEventLoop(EventLoop): # was not created here. self.closed = True - self._console_input_reader.close() - + self._console_input_reader.close() + def run_in_executor(self, callback): self.loop.run_in_executor(None, callback) diff --git a/contrib/python/prompt-toolkit/py2/prompt_toolkit/eventloop/base.py b/contrib/python/prompt-toolkit/py2/prompt_toolkit/eventloop/base.py index db86face66..520ab9e366 100644 --- a/contrib/python/prompt-toolkit/py2/prompt_toolkit/eventloop/base.py +++ b/contrib/python/prompt-toolkit/py2/prompt_toolkit/eventloop/base.py @@ -74,12 +74,12 @@ class EventLoop(with_metaclass(ABCMeta, object)): Call this function in the main event loop. Similar to Twisted's ``callFromThread``. - :param _max_postpone_until: `None` or `time.time` value. For interal + :param _max_postpone_until: `None` or `time.time` value. For interal use. If the eventloop is saturated, consider this task to be low priority and postpone maximum until this timestamp. (For instance, repaint is done using low priority.) - - Note: In the past, this used to be a datetime.datetime instance, - but apparently, executing `time.time` is more efficient: it - does fewer system calls. (It doesn't read /etc/localtime.) + + Note: In the past, this used to be a datetime.datetime instance, + but apparently, executing `time.time` is more efficient: it + does fewer system calls. (It doesn't read /etc/localtime.) """ diff --git a/contrib/python/prompt-toolkit/py2/prompt_toolkit/eventloop/inputhook.py b/contrib/python/prompt-toolkit/py2/prompt_toolkit/eventloop/inputhook.py index bab1f4c003..44e0a60591 100644 --- a/contrib/python/prompt-toolkit/py2/prompt_toolkit/eventloop/inputhook.py +++ b/contrib/python/prompt-toolkit/py2/prompt_toolkit/eventloop/inputhook.py @@ -25,8 +25,8 @@ controls everything. from __future__ import unicode_literals import os import threading -from prompt_toolkit.utils import is_windows -from .select import select_fds +from prompt_toolkit.utils import is_windows +from .select import select_fds __all__ = ( 'InputHookContext', @@ -75,19 +75,19 @@ class InputHookContext(object): # Flush the read end of the pipe. try: - # Before calling 'os.read', call select.select. This is required - # when the gevent monkey patch has been applied. 'os.read' is never - # monkey patched and won't be cooperative, so that would block all - # other select() calls otherwise. - # See: http://www.gevent.org/gevent.os.html - - # Note: On Windows, this is apparently not an issue. - # However, if we would ever want to add a select call, it - # should use `windll.kernel32.WaitForMultipleObjects`, - # because `select.select` can't wait for a pipe on Windows. - if not is_windows(): - select_fds([self._r], timeout=None) - + # Before calling 'os.read', call select.select. This is required + # when the gevent monkey patch has been applied. 'os.read' is never + # monkey patched and won't be cooperative, so that would block all + # other select() calls otherwise. + # See: http://www.gevent.org/gevent.os.html + + # Note: On Windows, this is apparently not an issue. + # However, if we would ever want to add a select call, it + # should use `windll.kernel32.WaitForMultipleObjects`, + # because `select.select` can't wait for a pipe on Windows. + if not is_windows(): + select_fds([self._r], timeout=None) + os.read(self._r, 1024) except OSError: # This happens when the window resizes and a SIGWINCH was received. diff --git a/contrib/python/prompt-toolkit/py2/prompt_toolkit/eventloop/posix.py b/contrib/python/prompt-toolkit/py2/prompt_toolkit/eventloop/posix.py index f631dbd891..be70d61f19 100644 --- a/contrib/python/prompt-toolkit/py2/prompt_toolkit/eventloop/posix.py +++ b/contrib/python/prompt-toolkit/py2/prompt_toolkit/eventloop/posix.py @@ -3,7 +3,7 @@ import fcntl import os import signal import threading -import time +import time from prompt_toolkit.terminal.vt100_input import InputStream from prompt_toolkit.utils import DummyContext, in_main_thread @@ -13,22 +13,22 @@ from .callbacks import EventLoopCallbacks from .inputhook import InputHookContext from .posix_utils import PosixStdinReader from .utils import TimeIt -from .select import AutoSelector, Selector, fd_to_int +from .select import AutoSelector, Selector, fd_to_int __all__ = ( 'PosixEventLoop', ) -_now = time.time +_now = time.time class PosixEventLoop(EventLoop): """ Event loop for posix systems (Linux, Mac os X). """ - def __init__(self, inputhook=None, selector=AutoSelector): + def __init__(self, inputhook=None, selector=AutoSelector): assert inputhook is None or callable(inputhook) - assert issubclass(selector, Selector) + assert issubclass(selector, Selector) self.running = False self.closed = False @@ -37,7 +37,7 @@ class PosixEventLoop(EventLoop): self._calls_from_executor = [] self._read_fds = {} # Maps fd to handler. - self.selector = selector() + self.selector = selector() # Create a pipe for inter thread communication. self._schedule_pipe = os.pipe() @@ -84,31 +84,31 @@ class PosixEventLoop(EventLoop): # Set timeout again. current_timeout[0] = INPUT_TIMEOUT - # Quit when the input stream was closed. - if stdin_reader.closed: - self.stop() - + # Quit when the input stream was closed. + if stdin_reader.closed: + self.stop() + self.add_reader(stdin, read_from_stdin) self.add_reader(self._schedule_pipe[0], None) with ctx: while self._running: # Call inputhook. - if self._inputhook_context: - with TimeIt() as inputhook_timer: + if self._inputhook_context: + with TimeIt() as inputhook_timer: def ready(wait): " True when there is input ready. The inputhook should return control. " return self._ready_for_reading(current_timeout[0] if wait else 0) != [] self._inputhook_context.call_inputhook(ready) - inputhook_duration = inputhook_timer.duration - else: - inputhook_duration = 0 + inputhook_duration = inputhook_timer.duration + else: + inputhook_duration = 0 # Calculate remaining timeout. (The inputhook consumed some of the time.) if current_timeout[0] is None: remaining_timeout = None else: - remaining_timeout = max(0, current_timeout[0] - inputhook_duration) + remaining_timeout = max(0, current_timeout[0] - inputhook_duration) # Wait until input is ready. fds = self._ready_for_reading(remaining_timeout) @@ -126,23 +126,23 @@ class PosixEventLoop(EventLoop): # case. tasks = [] low_priority_tasks = [] - now = None # Lazy load time. (Fewer system calls.) + now = None # Lazy load time. (Fewer system calls.) for fd in fds: # For the 'call_from_executor' fd, put each pending # item on either the high or low priority queue. if fd == self._schedule_pipe[0]: for c, max_postpone_until in self._calls_from_executor: - if max_postpone_until is None: - # Execute now. + if max_postpone_until is None: + # Execute now. tasks.append(c) else: - # Execute soon, if `max_postpone_until` is in the future. - now = now or _now() - if max_postpone_until < now: - tasks.append(c) - else: - low_priority_tasks.append((c, max_postpone_until)) + # Execute soon, if `max_postpone_until` is in the future. + now = now or _now() + if max_postpone_until < now: + tasks.append(c) + else: + low_priority_tasks.append((c, max_postpone_until)) self._calls_from_executor = [] # Flush all the pipe content. @@ -185,8 +185,8 @@ class PosixEventLoop(EventLoop): """ Return the file descriptors that are ready for reading. """ - fds = self.selector.select(timeout) - return fds + fds = self.selector.select(timeout) + return fds def received_winch(self): """ @@ -230,23 +230,23 @@ class PosixEventLoop(EventLoop): Call this function in the main event loop. Similar to Twisted's ``callFromThread``. - :param _max_postpone_until: `None` or `time.time` value. For interal + :param _max_postpone_until: `None` or `time.time` value. For interal use. If the eventloop is saturated, consider this task to be low priority and postpone maximum until this timestamp. (For instance, repaint is done using low priority.) """ - assert _max_postpone_until is None or isinstance(_max_postpone_until, float) + assert _max_postpone_until is None or isinstance(_max_postpone_until, float) self._calls_from_executor.append((callback, _max_postpone_until)) if self._schedule_pipe: - try: - os.write(self._schedule_pipe[1], b'x') - except (AttributeError, IndexError, OSError): - # Handle race condition. We're in a different thread. - # - `_schedule_pipe` could have become None in the meantime. - # - We catch `OSError` (actually BrokenPipeError), because the - # main thread could have closed the pipe already. - pass + try: + os.write(self._schedule_pipe[1], b'x') + except (AttributeError, IndexError, OSError): + # Handle race condition. We're in a different thread. + # - `_schedule_pipe` could have become None in the meantime. + # - We catch `OSError` (actually BrokenPipeError), because the + # main thread could have closed the pipe already. + pass def stop(self): """ @@ -270,18 +270,18 @@ class PosixEventLoop(EventLoop): def add_reader(self, fd, callback): " Add read file descriptor to the event loop. " - fd = fd_to_int(fd) + fd = fd_to_int(fd) self._read_fds[fd] = callback - self.selector.register(fd) + self.selector.register(fd) def remove_reader(self, fd): " Remove read file descriptor from the event loop. " - fd = fd_to_int(fd) - + fd = fd_to_int(fd) + if fd in self._read_fds: del self._read_fds[fd] - self.selector.unregister(fd) + self.selector.unregister(fd) class call_on_sigwinch(object): diff --git a/contrib/python/prompt-toolkit/py2/prompt_toolkit/eventloop/posix_utils.py b/contrib/python/prompt-toolkit/py2/prompt_toolkit/eventloop/posix_utils.py index 320df438ca..bb675ba9aa 100644 --- a/contrib/python/prompt-toolkit/py2/prompt_toolkit/eventloop/posix_utils.py +++ b/contrib/python/prompt-toolkit/py2/prompt_toolkit/eventloop/posix_utils.py @@ -2,7 +2,7 @@ from __future__ import unicode_literals from codecs import getincrementaldecoder import os -import six +import six __all__ = ( 'PosixStdinReader', @@ -13,42 +13,42 @@ class PosixStdinReader(object): """ Wrapper around stdin which reads (nonblocking) the next available 1024 bytes and decodes it. - - Note that you can't be sure that the input file is closed if the ``read`` - function returns an empty string. When ``errors=ignore`` is passed, - ``read`` can return an empty string if all malformed input was replaced by - an empty string. (We can't block here and wait for more input.) So, because - of that, check the ``closed`` attribute, to be sure that the file has been - closed. - - :param stdin_fd: File descriptor from which we read. - :param errors: Can be 'ignore', 'strict' or 'replace'. - On Python3, this can be 'surrogateescape', which is the default. - - 'surrogateescape' is preferred, because this allows us to transfer - unrecognised bytes to the key bindings. Some terminals, like lxterminal - and Guake, use the 'Mxx' notation to send mouse events, where each 'x' - can be any possible byte. + + Note that you can't be sure that the input file is closed if the ``read`` + function returns an empty string. When ``errors=ignore`` is passed, + ``read`` can return an empty string if all malformed input was replaced by + an empty string. (We can't block here and wait for more input.) So, because + of that, check the ``closed`` attribute, to be sure that the file has been + closed. + + :param stdin_fd: File descriptor from which we read. + :param errors: Can be 'ignore', 'strict' or 'replace'. + On Python3, this can be 'surrogateescape', which is the default. + + 'surrogateescape' is preferred, because this allows us to transfer + unrecognised bytes to the key bindings. Some terminals, like lxterminal + and Guake, use the 'Mxx' notation to send mouse events, where each 'x' + can be any possible byte. """ - # By default, we want to 'ignore' errors here. The input stream can be full - # of junk. One occurrence of this that I had was when using iTerm2 on OS X, - # with "Option as Meta" checked (You should choose "Option as +Esc".) - - def __init__(self, stdin_fd, - errors=('ignore' if six.PY2 else 'surrogateescape')): + # By default, we want to 'ignore' errors here. The input stream can be full + # of junk. One occurrence of this that I had was when using iTerm2 on OS X, + # with "Option as Meta" checked (You should choose "Option as +Esc".) + + def __init__(self, stdin_fd, + errors=('ignore' if six.PY2 else 'surrogateescape')): assert isinstance(stdin_fd, int) self.stdin_fd = stdin_fd - self.errors = errors + self.errors = errors # Create incremental decoder for decoding stdin. # We can not just do `os.read(stdin.fileno(), 1024).decode('utf-8')`, because # it could be that we are in the middle of a utf-8 byte sequence. self._stdin_decoder_cls = getincrementaldecoder('utf-8') - self._stdin_decoder = self._stdin_decoder_cls(errors=errors) - - #: True when there is nothing anymore to read. - self.closed = False + self._stdin_decoder = self._stdin_decoder_cls(errors=errors) + #: True when there is nothing anymore to read. + self.closed = False + def read(self, count=1024): # By default we choose a rather small chunk size, because reading # big amounts of input at once, causes the event loop to process @@ -56,27 +56,27 @@ class PosixStdinReader(object): # loop. This will make the application feel unresponsive. """ Read the input and return it as a string. - - Return the text. Note that this can return an empty string, even when - the input stream was not yet closed. This means that something went - wrong during the decoding. + + Return the text. Note that this can return an empty string, even when + the input stream was not yet closed. This means that something went + wrong during the decoding. """ - if self.closed: - return b'' - + if self.closed: + return b'' + # Note: the following works better than wrapping `self.stdin` like # `codecs.getreader('utf-8')(stdin)` and doing `read(1)`. # Somehow that causes some latency when the escape # character is pressed. (Especially on combination with the `select`.) try: data = os.read(self.stdin_fd, count) - - # Nothing more to read, stream is closed. - if data == b'': - self.closed = True - return '' + + # Nothing more to read, stream is closed. + if data == b'': + self.closed = True + return '' except OSError: # In case of SIGWINCH data = b'' - return self._stdin_decoder.decode(data) + return self._stdin_decoder.decode(data) diff --git a/contrib/python/prompt-toolkit/py2/prompt_toolkit/eventloop/select.py b/contrib/python/prompt-toolkit/py2/prompt_toolkit/eventloop/select.py index f678f84c55..66e8e346b8 100644 --- a/contrib/python/prompt-toolkit/py2/prompt_toolkit/eventloop/select.py +++ b/contrib/python/prompt-toolkit/py2/prompt_toolkit/eventloop/select.py @@ -1,216 +1,216 @@ -""" -Selectors for the Posix event loop. -""" -from __future__ import unicode_literals, absolute_import -import sys -import abc -import errno -import select -import six - -__all__ = ( - 'AutoSelector', - 'PollSelector', - 'SelectSelector', - 'Selector', - 'fd_to_int', -) - -def fd_to_int(fd): - assert isinstance(fd, int) or hasattr(fd, 'fileno') - - if isinstance(fd, int): - return fd - else: - return fd.fileno() - - -class Selector(six.with_metaclass(abc.ABCMeta, object)): - @abc.abstractmethod - def register(self, fd): - assert isinstance(fd, int) - - @abc.abstractmethod - def unregister(self, fd): - assert isinstance(fd, int) - - @abc.abstractmethod - def select(self, timeout): - pass - - @abc.abstractmethod - def close(self): - pass - - -class AutoSelector(Selector): - def __init__(self): - self._fds = [] - - self._select_selector = SelectSelector() - self._selectors = [self._select_selector] - - # When 'select.poll' exists, create a PollSelector. - if hasattr(select, 'poll'): - self._poll_selector = PollSelector() - self._selectors.append(self._poll_selector) - else: - self._poll_selector = None - - # Use of the 'select' module, that was introduced in Python3.4. We don't - # use it before 3.5 however, because this is the point where this module - # retries interrupted system calls. - if sys.version_info >= (3, 5): - self._py3_selector = Python3Selector() - self._selectors.append(self._py3_selector) - else: - self._py3_selector = None - - def register(self, fd): - assert isinstance(fd, int) - - self._fds.append(fd) - - for sel in self._selectors: - sel.register(fd) - - def unregister(self, fd): - assert isinstance(fd, int) - - self._fds.remove(fd) - - for sel in self._selectors: - sel.unregister(fd) - - def select(self, timeout): - # Try Python 3 selector first. - if self._py3_selector: - try: - return self._py3_selector.select(timeout) - except PermissionError: - # We had a situation (in pypager) where epoll raised a - # PermissionError when a local file descriptor was registered, - # however poll and select worked fine. So, in that case, just - # try using select below. - pass - - try: - # Prefer 'select.select', if we don't have much file descriptors. - # This is more universal. - return self._select_selector.select(timeout) - except ValueError: - # When we have more than 1024 open file descriptors, we'll always - # get a "ValueError: filedescriptor out of range in select()" for - # 'select'. In this case, try, using 'poll' instead. - if self._poll_selector is not None: - return self._poll_selector.select(timeout) - else: - raise - - def close(self): - for sel in self._selectors: - sel.close() - - -class Python3Selector(Selector): - """ - Use of the Python3 'selectors' module. - - NOTE: Only use on Python 3.5 or newer! - """ - def __init__(self): - assert sys.version_info >= (3, 5) - - import selectors # Inline import: Python3 only! - self._sel = selectors.DefaultSelector() - - def register(self, fd): - assert isinstance(fd, int) - import selectors # Inline import: Python3 only! - self._sel.register(fd, selectors.EVENT_READ, None) - - def unregister(self, fd): - assert isinstance(fd, int) - self._sel.unregister(fd) - - def select(self, timeout): - events = self._sel.select(timeout=timeout) - return [key.fileobj for key, mask in events] - - def close(self): - self._sel.close() - - -class PollSelector(Selector): - def __init__(self): - self._poll = select.poll() - - def register(self, fd): - assert isinstance(fd, int) - self._poll.register(fd, select.POLLIN) - - def unregister(self, fd): - assert isinstance(fd, int) - - def select(self, timeout): - tuples = self._poll.poll(timeout) # Returns (fd, event) tuples. - return [t[0] for t in tuples] - - def close(self): - pass # XXX - - -class SelectSelector(Selector): - """ - Wrapper around select.select. - - When the SIGWINCH signal is handled, other system calls, like select - are aborted in Python. This wrapper will retry the system call. - """ - def __init__(self): - self._fds = [] - - def register(self, fd): - self._fds.append(fd) - - def unregister(self, fd): - self._fds.remove(fd) - - def select(self, timeout): - while True: - try: - return select.select(self._fds, [], [], timeout)[0] - except select.error as e: - # Retry select call when EINTR - if e.args and e.args[0] == errno.EINTR: - continue - else: - raise - - def close(self): - pass - - -def select_fds(read_fds, timeout, selector=AutoSelector): - """ - Wait for a list of file descriptors (`read_fds`) to become ready for - reading. This chooses the most appropriate select-tool for use in - prompt-toolkit. - """ - # Map to ensure that we return the objects that were passed in originally. - # Whether they are a fd integer or an object that has a fileno(). - # (The 'poll' implementation for instance, returns always integers.) - fd_map = dict((fd_to_int(fd), fd) for fd in read_fds) - - # Wait, using selector. - sel = selector() - try: - for fd in read_fds: - sel.register(fd) - - result = sel.select(timeout) - - if result is not None: - return [fd_map[fd_to_int(fd)] for fd in result] - finally: - sel.close() +""" +Selectors for the Posix event loop. +""" +from __future__ import unicode_literals, absolute_import +import sys +import abc +import errno +import select +import six + +__all__ = ( + 'AutoSelector', + 'PollSelector', + 'SelectSelector', + 'Selector', + 'fd_to_int', +) + +def fd_to_int(fd): + assert isinstance(fd, int) or hasattr(fd, 'fileno') + + if isinstance(fd, int): + return fd + else: + return fd.fileno() + + +class Selector(six.with_metaclass(abc.ABCMeta, object)): + @abc.abstractmethod + def register(self, fd): + assert isinstance(fd, int) + + @abc.abstractmethod + def unregister(self, fd): + assert isinstance(fd, int) + + @abc.abstractmethod + def select(self, timeout): + pass + + @abc.abstractmethod + def close(self): + pass + + +class AutoSelector(Selector): + def __init__(self): + self._fds = [] + + self._select_selector = SelectSelector() + self._selectors = [self._select_selector] + + # When 'select.poll' exists, create a PollSelector. + if hasattr(select, 'poll'): + self._poll_selector = PollSelector() + self._selectors.append(self._poll_selector) + else: + self._poll_selector = None + + # Use of the 'select' module, that was introduced in Python3.4. We don't + # use it before 3.5 however, because this is the point where this module + # retries interrupted system calls. + if sys.version_info >= (3, 5): + self._py3_selector = Python3Selector() + self._selectors.append(self._py3_selector) + else: + self._py3_selector = None + + def register(self, fd): + assert isinstance(fd, int) + + self._fds.append(fd) + + for sel in self._selectors: + sel.register(fd) + + def unregister(self, fd): + assert isinstance(fd, int) + + self._fds.remove(fd) + + for sel in self._selectors: + sel.unregister(fd) + + def select(self, timeout): + # Try Python 3 selector first. + if self._py3_selector: + try: + return self._py3_selector.select(timeout) + except PermissionError: + # We had a situation (in pypager) where epoll raised a + # PermissionError when a local file descriptor was registered, + # however poll and select worked fine. So, in that case, just + # try using select below. + pass + + try: + # Prefer 'select.select', if we don't have much file descriptors. + # This is more universal. + return self._select_selector.select(timeout) + except ValueError: + # When we have more than 1024 open file descriptors, we'll always + # get a "ValueError: filedescriptor out of range in select()" for + # 'select'. In this case, try, using 'poll' instead. + if self._poll_selector is not None: + return self._poll_selector.select(timeout) + else: + raise + + def close(self): + for sel in self._selectors: + sel.close() + + +class Python3Selector(Selector): + """ + Use of the Python3 'selectors' module. + + NOTE: Only use on Python 3.5 or newer! + """ + def __init__(self): + assert sys.version_info >= (3, 5) + + import selectors # Inline import: Python3 only! + self._sel = selectors.DefaultSelector() + + def register(self, fd): + assert isinstance(fd, int) + import selectors # Inline import: Python3 only! + self._sel.register(fd, selectors.EVENT_READ, None) + + def unregister(self, fd): + assert isinstance(fd, int) + self._sel.unregister(fd) + + def select(self, timeout): + events = self._sel.select(timeout=timeout) + return [key.fileobj for key, mask in events] + + def close(self): + self._sel.close() + + +class PollSelector(Selector): + def __init__(self): + self._poll = select.poll() + + def register(self, fd): + assert isinstance(fd, int) + self._poll.register(fd, select.POLLIN) + + def unregister(self, fd): + assert isinstance(fd, int) + + def select(self, timeout): + tuples = self._poll.poll(timeout) # Returns (fd, event) tuples. + return [t[0] for t in tuples] + + def close(self): + pass # XXX + + +class SelectSelector(Selector): + """ + Wrapper around select.select. + + When the SIGWINCH signal is handled, other system calls, like select + are aborted in Python. This wrapper will retry the system call. + """ + def __init__(self): + self._fds = [] + + def register(self, fd): + self._fds.append(fd) + + def unregister(self, fd): + self._fds.remove(fd) + + def select(self, timeout): + while True: + try: + return select.select(self._fds, [], [], timeout)[0] + except select.error as e: + # Retry select call when EINTR + if e.args and e.args[0] == errno.EINTR: + continue + else: + raise + + def close(self): + pass + + +def select_fds(read_fds, timeout, selector=AutoSelector): + """ + Wait for a list of file descriptors (`read_fds`) to become ready for + reading. This chooses the most appropriate select-tool for use in + prompt-toolkit. + """ + # Map to ensure that we return the objects that were passed in originally. + # Whether they are a fd integer or an object that has a fileno(). + # (The 'poll' implementation for instance, returns always integers.) + fd_map = dict((fd_to_int(fd), fd) for fd in read_fds) + + # Wait, using selector. + sel = selector() + try: + for fd in read_fds: + sel.register(fd) + + result = sel.select(timeout) + + if result is not None: + return [fd_map[fd_to_int(fd)] for fd in result] + finally: + sel.close() diff --git a/contrib/python/prompt-toolkit/py2/prompt_toolkit/eventloop/win32.py b/contrib/python/prompt-toolkit/py2/prompt_toolkit/eventloop/win32.py index 18e356f088..0a3f63620c 100644 --- a/contrib/python/prompt-toolkit/py2/prompt_toolkit/eventloop/win32.py +++ b/contrib/python/prompt-toolkit/py2/prompt_toolkit/eventloop/win32.py @@ -15,7 +15,7 @@ from .utils import TimeIt from ctypes import windll, pointer from ctypes.wintypes import DWORD, BOOL, HANDLE -import msvcrt +import msvcrt import threading __all__ = ( @@ -29,23 +29,23 @@ INPUT_TIMEOUT_MS = int(1000 * INPUT_TIMEOUT) class Win32EventLoop(EventLoop): """ Event loop for Windows systems. - - :param recognize_paste: When True, try to discover paste actions and turn - the event into a BracketedPaste. + + :param recognize_paste: When True, try to discover paste actions and turn + the event into a BracketedPaste. """ - def __init__(self, inputhook=None, recognize_paste=True): + def __init__(self, inputhook=None, recognize_paste=True): assert inputhook is None or callable(inputhook) self._event = HANDLE(_create_event()) - self._console_input_reader = ConsoleInputReader(recognize_paste=recognize_paste) + self._console_input_reader = ConsoleInputReader(recognize_paste=recognize_paste) self._calls_from_executor = [] self.closed = False self._running = False - # Additional readers. - self._read_fds = {} # Maps fd to handler. - + # Additional readers. + self._read_fds = {} # Maps fd to handler. + # Create inputhook context. self._inputhook_context = InputHookContext(inputhook) if inputhook else None @@ -86,9 +86,9 @@ class Win32EventLoop(EventLoop): windll.kernel32.ResetEvent(self._event) self._process_queued_calls_from_executor() - elif handle in self._read_fds: - callback = self._read_fds[handle] - callback() + elif handle in self._read_fds: + callback = self._read_fds[handle] + callback() else: # Fire input timeout event. callbacks.input_timeout() @@ -98,9 +98,9 @@ class Win32EventLoop(EventLoop): """ Return the handle that is ready for reading or `None` on timeout. """ - handles = [self._event, self._console_input_reader.handle] - handles.extend(self._read_fds.keys()) - return _wait_for_handles(handles, timeout) + handles = [self._event, self._console_input_reader.handle] + handles.extend(self._read_fds.keys()) + return _wait_for_handles(handles, timeout) def stop(self): self._running = False @@ -114,8 +114,8 @@ class Win32EventLoop(EventLoop): if self._inputhook_context: self._inputhook_context.close() - self._console_input_reader.close() - + self._console_input_reader.close() + def run_in_executor(self, callback): """ Run a long running function in a background thread. @@ -148,14 +148,14 @@ class Win32EventLoop(EventLoop): def add_reader(self, fd, callback): " Start watching the file descriptor for read availability. " - h = msvcrt.get_osfhandle(fd) - self._read_fds[h] = callback + h = msvcrt.get_osfhandle(fd) + self._read_fds[h] = callback def remove_reader(self, fd): " Stop watching the file descriptor for read availability. " - h = msvcrt.get_osfhandle(fd) - if h in self._read_fds: - del self._read_fds[h] + h = msvcrt.get_osfhandle(fd) + if h in self._read_fds: + del self._read_fds[h] def _wait_for_handles(handles, timeout=-1): diff --git a/contrib/python/prompt-toolkit/py2/prompt_toolkit/filters/base.py b/contrib/python/prompt-toolkit/py2/prompt_toolkit/filters/base.py index 6a1a1d0b10..f2b872a2d0 100644 --- a/contrib/python/prompt-toolkit/py2/prompt_toolkit/filters/base.py +++ b/contrib/python/prompt-toolkit/py2/prompt_toolkit/filters/base.py @@ -2,9 +2,9 @@ from __future__ import unicode_literals from abc import ABCMeta, abstractmethod from six import with_metaclass -from prompt_toolkit.utils import test_callable_args - +from prompt_toolkit.utils import test_callable_args + __all__ = ( 'Filter', 'Never', @@ -29,19 +29,19 @@ class Filter(with_metaclass(ABCMeta, object)): """ Chaining of filters using the & operator. """ - return _and_cache[self, other] + return _and_cache[self, other] def __or__(self, other): """ Chaining of filters using the | operator. """ - return _or_cache[self, other] + return _or_cache[self, other] def __invert__(self): """ Inverting of filters using the ~ operator. """ - return _invert_cache[self] + return _invert_cache[self] def __bool__(self): """ @@ -56,11 +56,11 @@ class Filter(with_metaclass(ABCMeta, object)): __nonzero__ = __bool__ # For Python 2. - def test_args(self, *args): + def test_args(self, *args): """ - Test whether this filter can be called with the following argument list. + Test whether this filter can be called with the following argument list. """ - return test_callable_args(self.__call__, args) + return test_callable_args(self.__call__, args) class _AndCache(dict): @@ -74,14 +74,14 @@ class _AndCache(dict): removed. In practise however, there is a finite amount of filters. """ def __missing__(self, filters): - a, b = filters - assert isinstance(b, Filter), 'Expecting filter, got %r' % b - - if isinstance(b, Always) or isinstance(a, Never): - return a - elif isinstance(b, Never) or isinstance(a, Always): - return b - + a, b = filters + assert isinstance(b, Filter), 'Expecting filter, got %r' % b + + if isinstance(b, Always) or isinstance(a, Never): + return a + elif isinstance(b, Never) or isinstance(a, Always): + return b + result = _AndList(filters) self[filters] = result return result @@ -90,30 +90,30 @@ class _AndCache(dict): class _OrCache(dict): """ Cache for Or operation between filters. """ def __missing__(self, filters): - a, b = filters - assert isinstance(b, Filter), 'Expecting filter, got %r' % b - - if isinstance(b, Always) or isinstance(a, Never): - return b - elif isinstance(b, Never) or isinstance(a, Always): - return a - + a, b = filters + assert isinstance(b, Filter), 'Expecting filter, got %r' % b + + if isinstance(b, Always) or isinstance(a, Never): + return b + elif isinstance(b, Never) or isinstance(a, Always): + return a + result = _OrList(filters) self[filters] = result return result -class _InvertCache(dict): - """ Cache for inversion operator. """ - def __missing__(self, filter): - result = _Invert(filter) - self[filter] = result - return result - - +class _InvertCache(dict): + """ Cache for inversion operator. """ + def __missing__(self, filter): + result = _Invert(filter) + self[filter] = result + return result + + _and_cache = _AndCache() _or_cache = _OrCache() -_invert_cache = _InvertCache() +_invert_cache = _InvertCache() class _AndList(Filter): @@ -131,8 +131,8 @@ class _AndList(Filter): self.filters = all_filters - def test_args(self, *args): - return all(f.test_args(*args) for f in self.filters) + def test_args(self, *args): + return all(f.test_args(*args) for f in self.filters) def __call__(self, *a, **kw): return all(f(*a, **kw) for f in self.filters) @@ -156,8 +156,8 @@ class _OrList(Filter): self.filters = all_filters - def test_args(self, *args): - return all(f.test_args(*args) for f in self.filters) + def test_args(self, *args): + return all(f.test_args(*args) for f in self.filters) def __call__(self, *a, **kw): return any(f(*a, **kw) for f in self.filters) @@ -179,8 +179,8 @@ class _Invert(Filter): def __repr__(self): return '~%r' % self.filter - def test_args(self, *args): - return self.filter.test_args(*args) + def test_args(self, *args): + return self.filter.test_args(*args) class Always(Filter): @@ -230,5 +230,5 @@ class Condition(Filter): def __repr__(self): return 'Condition(%r)' % self.func - def test_args(self, *a): - return test_callable_args(self.func, a) + def test_args(self, *a): + return test_callable_args(self.func, a) diff --git a/contrib/python/prompt-toolkit/py2/prompt_toolkit/filters/cli.py b/contrib/python/prompt-toolkit/py2/prompt_toolkit/filters/cli.py index c0b07317be..dbcd74dea9 100644 --- a/contrib/python/prompt-toolkit/py2/prompt_toolkit/filters/cli.py +++ b/contrib/python/prompt-toolkit/py2/prompt_toolkit/filters/cli.py @@ -3,9 +3,9 @@ Filters that accept a `CommandLineInterface` as argument. """ from __future__ import unicode_literals from .base import Filter -from prompt_toolkit.enums import EditingMode -from prompt_toolkit.key_binding.vi_state import InputMode as ViInputMode -from prompt_toolkit.cache import memoized +from prompt_toolkit.enums import EditingMode +from prompt_toolkit.key_binding.vi_state import InputMode as ViInputMode +from prompt_toolkit.cache import memoized __all__ = ( 'HasArg', @@ -21,38 +21,38 @@ __all__ = ( 'IsReadOnly', 'IsReturning', 'RendererHeightIsKnown', - 'InEditingMode', - - # Vi modes. - 'ViMode', - 'ViNavigationMode', - 'ViInsertMode', - 'ViInsertMultipleMode', - 'ViReplaceMode', - 'ViSelectionMode', - 'ViWaitingForTextObjectMode', - 'ViDigraphMode', - - # Emacs modes. - 'EmacsMode', - 'EmacsInsertMode', - 'EmacsSelectionMode', + 'InEditingMode', + + # Vi modes. + 'ViMode', + 'ViNavigationMode', + 'ViInsertMode', + 'ViInsertMultipleMode', + 'ViReplaceMode', + 'ViSelectionMode', + 'ViWaitingForTextObjectMode', + 'ViDigraphMode', + + # Emacs modes. + 'EmacsMode', + 'EmacsInsertMode', + 'EmacsSelectionMode', ) -@memoized() +@memoized() class HasFocus(Filter): """ Enable when this buffer has the focus. """ def __init__(self, buffer_name): - self._buffer_name = buffer_name - - @property - def buffer_name(self): - " The given buffer name. (Read-only) " - return self._buffer_name + self._buffer_name = buffer_name + @property + def buffer_name(self): + " The given buffer name. (Read-only) " + return self._buffer_name + def __call__(self, cli): return cli.current_buffer_name == self.buffer_name @@ -60,19 +60,19 @@ class HasFocus(Filter): return 'HasFocus(%r)' % self.buffer_name -@memoized() +@memoized() class InFocusStack(Filter): """ Enable when this buffer appears on the focus stack. """ def __init__(self, buffer_name): - self._buffer_name = buffer_name - - @property - def buffer_name(self): - " The given buffer name. (Read-only) " - return self._buffer_name + self._buffer_name = buffer_name + @property + def buffer_name(self): + " The given buffer name. (Read-only) " + return self._buffer_name + def __call__(self, cli): return self.buffer_name in cli.buffers.focus_stack @@ -80,7 +80,7 @@ class InFocusStack(Filter): return 'InFocusStack(%r)' % self.buffer_name -@memoized() +@memoized() class HasSelection(Filter): """ Enable when the current buffer has a selection. @@ -92,7 +92,7 @@ class HasSelection(Filter): return 'HasSelection()' -@memoized() +@memoized() class HasCompletions(Filter): """ Enable when the current buffer has completions. @@ -104,7 +104,7 @@ class HasCompletions(Filter): return 'HasCompletions()' -@memoized() +@memoized() class IsMultiline(Filter): """ Enable in multiline mode. @@ -116,7 +116,7 @@ class IsMultiline(Filter): return 'IsMultiline()' -@memoized() +@memoized() class IsReadOnly(Filter): """ True when the current buffer is read only. @@ -128,7 +128,7 @@ class IsReadOnly(Filter): return 'IsReadOnly()' -@memoized() +@memoized() class HasValidationError(Filter): """ Current buffer has validation error. @@ -140,7 +140,7 @@ class HasValidationError(Filter): return 'HasValidationError()' -@memoized() +@memoized() class HasArg(Filter): """ Enable when the input processor has an 'arg'. @@ -152,7 +152,7 @@ class HasArg(Filter): return 'HasArg()' -@memoized() +@memoized() class HasSearch(Filter): """ Incremental search is active. @@ -164,7 +164,7 @@ class HasSearch(Filter): return 'HasSearch()' -@memoized() +@memoized() class IsReturning(Filter): """ When a return value has been set. @@ -176,7 +176,7 @@ class IsReturning(Filter): return 'IsReturning()' -@memoized() +@memoized() class IsAborting(Filter): """ True when aborting. (E.g. Control-C pressed.) @@ -188,7 +188,7 @@ class IsAborting(Filter): return 'IsAborting()' -@memoized() +@memoized() class IsExiting(Filter): """ True when exiting. (E.g. Control-D pressed.) @@ -200,7 +200,7 @@ class IsExiting(Filter): return 'IsExiting()' -@memoized() +@memoized() class IsDone(Filter): """ True when the CLI is returning, aborting or exiting. @@ -212,7 +212,7 @@ class IsDone(Filter): return 'IsDone()' -@memoized() +@memoized() class RendererHeightIsKnown(Filter): """ Only True when the renderer knows it's real height. @@ -228,168 +228,168 @@ class RendererHeightIsKnown(Filter): def __repr__(self): return 'RendererHeightIsKnown()' - - -@memoized() -class InEditingMode(Filter): - """ - Check whether a given editing mode is active. (Vi or Emacs.) - """ - def __init__(self, editing_mode): - self._editing_mode = editing_mode - - @property - def editing_mode(self): - " The given editing mode. (Read-only) " - return self._editing_mode - - def __call__(self, cli): - return cli.editing_mode == self.editing_mode - - def __repr__(self): - return 'InEditingMode(%r)' % (self.editing_mode, ) - - -@memoized() -class ViMode(Filter): - def __call__(self, cli): - return cli.editing_mode == EditingMode.VI - - def __repr__(self): - return 'ViMode()' - - -@memoized() -class ViNavigationMode(Filter): - """ - Active when the set for Vi navigation key bindings are active. - """ - def __call__(self, cli): - if (cli.editing_mode != EditingMode.VI - or cli.vi_state.operator_func - or cli.vi_state.waiting_for_digraph - or cli.current_buffer.selection_state): - return False - - return (cli.vi_state.input_mode == ViInputMode.NAVIGATION or - cli.current_buffer.read_only()) - - def __repr__(self): - return 'ViNavigationMode()' - - -@memoized() -class ViInsertMode(Filter): - def __call__(self, cli): - if (cli.editing_mode != EditingMode.VI - or cli.vi_state.operator_func - or cli.vi_state.waiting_for_digraph - or cli.current_buffer.selection_state - or cli.current_buffer.read_only()): - return False - - return cli.vi_state.input_mode == ViInputMode.INSERT - - def __repr__(self): - return 'ViInputMode()' - - -@memoized() -class ViInsertMultipleMode(Filter): - def __call__(self, cli): - if (cli.editing_mode != EditingMode.VI - or cli.vi_state.operator_func - or cli.vi_state.waiting_for_digraph - or cli.current_buffer.selection_state - or cli.current_buffer.read_only()): - return False - - return cli.vi_state.input_mode == ViInputMode.INSERT_MULTIPLE - - def __repr__(self): - return 'ViInsertMultipleMode()' - - -@memoized() -class ViReplaceMode(Filter): - def __call__(self, cli): - if (cli.editing_mode != EditingMode.VI - or cli.vi_state.operator_func - or cli.vi_state.waiting_for_digraph - or cli.current_buffer.selection_state - or cli.current_buffer.read_only()): - return False - - return cli.vi_state.input_mode == ViInputMode.REPLACE - - def __repr__(self): - return 'ViReplaceMode()' - - -@memoized() -class ViSelectionMode(Filter): - def __call__(self, cli): - if cli.editing_mode != EditingMode.VI: - return False - - return bool(cli.current_buffer.selection_state) - - def __repr__(self): - return 'ViSelectionMode()' - - -@memoized() -class ViWaitingForTextObjectMode(Filter): - def __call__(self, cli): - if cli.editing_mode != EditingMode.VI: - return False - - return cli.vi_state.operator_func is not None - - def __repr__(self): - return 'ViWaitingForTextObjectMode()' - - -@memoized() -class ViDigraphMode(Filter): - def __call__(self, cli): - if cli.editing_mode != EditingMode.VI: - return False - - return cli.vi_state.waiting_for_digraph - - def __repr__(self): - return 'ViDigraphMode()' - - -@memoized() -class EmacsMode(Filter): - " When the Emacs bindings are active. " - def __call__(self, cli): - return cli.editing_mode == EditingMode.EMACS - - def __repr__(self): - return 'EmacsMode()' - - -@memoized() -class EmacsInsertMode(Filter): - def __call__(self, cli): - if (cli.editing_mode != EditingMode.EMACS - or cli.current_buffer.selection_state - or cli.current_buffer.read_only()): - return False - return True - - def __repr__(self): - return 'EmacsInsertMode()' - - -@memoized() -class EmacsSelectionMode(Filter): - def __call__(self, cli): - return (cli.editing_mode == EditingMode.EMACS - and cli.current_buffer.selection_state) - - def __repr__(self): - return 'EmacsSelectionMode()' + + +@memoized() +class InEditingMode(Filter): + """ + Check whether a given editing mode is active. (Vi or Emacs.) + """ + def __init__(self, editing_mode): + self._editing_mode = editing_mode + + @property + def editing_mode(self): + " The given editing mode. (Read-only) " + return self._editing_mode + + def __call__(self, cli): + return cli.editing_mode == self.editing_mode + + def __repr__(self): + return 'InEditingMode(%r)' % (self.editing_mode, ) + + +@memoized() +class ViMode(Filter): + def __call__(self, cli): + return cli.editing_mode == EditingMode.VI + + def __repr__(self): + return 'ViMode()' + + +@memoized() +class ViNavigationMode(Filter): + """ + Active when the set for Vi navigation key bindings are active. + """ + def __call__(self, cli): + if (cli.editing_mode != EditingMode.VI + or cli.vi_state.operator_func + or cli.vi_state.waiting_for_digraph + or cli.current_buffer.selection_state): + return False + + return (cli.vi_state.input_mode == ViInputMode.NAVIGATION or + cli.current_buffer.read_only()) + + def __repr__(self): + return 'ViNavigationMode()' + + +@memoized() +class ViInsertMode(Filter): + def __call__(self, cli): + if (cli.editing_mode != EditingMode.VI + or cli.vi_state.operator_func + or cli.vi_state.waiting_for_digraph + or cli.current_buffer.selection_state + or cli.current_buffer.read_only()): + return False + + return cli.vi_state.input_mode == ViInputMode.INSERT + + def __repr__(self): + return 'ViInputMode()' + + +@memoized() +class ViInsertMultipleMode(Filter): + def __call__(self, cli): + if (cli.editing_mode != EditingMode.VI + or cli.vi_state.operator_func + or cli.vi_state.waiting_for_digraph + or cli.current_buffer.selection_state + or cli.current_buffer.read_only()): + return False + + return cli.vi_state.input_mode == ViInputMode.INSERT_MULTIPLE + + def __repr__(self): + return 'ViInsertMultipleMode()' + + +@memoized() +class ViReplaceMode(Filter): + def __call__(self, cli): + if (cli.editing_mode != EditingMode.VI + or cli.vi_state.operator_func + or cli.vi_state.waiting_for_digraph + or cli.current_buffer.selection_state + or cli.current_buffer.read_only()): + return False + + return cli.vi_state.input_mode == ViInputMode.REPLACE + + def __repr__(self): + return 'ViReplaceMode()' + + +@memoized() +class ViSelectionMode(Filter): + def __call__(self, cli): + if cli.editing_mode != EditingMode.VI: + return False + + return bool(cli.current_buffer.selection_state) + + def __repr__(self): + return 'ViSelectionMode()' + + +@memoized() +class ViWaitingForTextObjectMode(Filter): + def __call__(self, cli): + if cli.editing_mode != EditingMode.VI: + return False + + return cli.vi_state.operator_func is not None + + def __repr__(self): + return 'ViWaitingForTextObjectMode()' + + +@memoized() +class ViDigraphMode(Filter): + def __call__(self, cli): + if cli.editing_mode != EditingMode.VI: + return False + + return cli.vi_state.waiting_for_digraph + + def __repr__(self): + return 'ViDigraphMode()' + + +@memoized() +class EmacsMode(Filter): + " When the Emacs bindings are active. " + def __call__(self, cli): + return cli.editing_mode == EditingMode.EMACS + + def __repr__(self): + return 'EmacsMode()' + + +@memoized() +class EmacsInsertMode(Filter): + def __call__(self, cli): + if (cli.editing_mode != EditingMode.EMACS + or cli.current_buffer.selection_state + or cli.current_buffer.read_only()): + return False + return True + + def __repr__(self): + return 'EmacsInsertMode()' + + +@memoized() +class EmacsSelectionMode(Filter): + def __call__(self, cli): + return (cli.editing_mode == EditingMode.EMACS + and cli.current_buffer.selection_state) + + def __repr__(self): + return 'EmacsSelectionMode()' diff --git a/contrib/python/prompt-toolkit/py2/prompt_toolkit/filters/types.py b/contrib/python/prompt-toolkit/py2/prompt_toolkit/filters/types.py index 3e89c39c01..fa518b7b95 100644 --- a/contrib/python/prompt-toolkit/py2/prompt_toolkit/filters/types.py +++ b/contrib/python/prompt-toolkit/py2/prompt_toolkit/filters/types.py @@ -1,37 +1,37 @@ from __future__ import unicode_literals from six import with_metaclass -from collections import defaultdict -import weakref +from collections import defaultdict +import weakref __all__ = ( 'CLIFilter', 'SimpleFilter', ) -# Cache for _FilterTypeMeta. (Don't test the same __instancecheck__ twice as -# long as the object lives. -- We do this a lot and calling 'test_args' is -# expensive.) -_instance_check_cache = defaultdict(weakref.WeakKeyDictionary) - - +# Cache for _FilterTypeMeta. (Don't test the same __instancecheck__ twice as +# long as the object lives. -- We do this a lot and calling 'test_args' is +# expensive.) +_instance_check_cache = defaultdict(weakref.WeakKeyDictionary) + + class _FilterTypeMeta(type): def __instancecheck__(cls, instance): - cache = _instance_check_cache[tuple(cls.arguments_list)] - - def get(): - " The actual test. " - if not hasattr(instance, 'test_args'): - return False - return instance.test_args(*cls.arguments_list) - - try: - return cache[instance] - except KeyError: - result = get() - cache[instance] = result - return result - - + cache = _instance_check_cache[tuple(cls.arguments_list)] + + def get(): + " The actual test. " + if not hasattr(instance, 'test_args'): + return False + return instance.test_args(*cls.arguments_list) + + try: + return cache[instance] + except KeyError: + result = get() + cache[instance] = result + return result + + class _FilterType(with_metaclass(_FilterTypeMeta)): def __new__(cls): raise NotImplementedError('This class should not be initiated.') diff --git a/contrib/python/prompt-toolkit/py2/prompt_toolkit/filters/utils.py b/contrib/python/prompt-toolkit/py2/prompt_toolkit/filters/utils.py index 836d2956e7..a4da36f863 100644 --- a/contrib/python/prompt-toolkit/py2/prompt_toolkit/filters/utils.py +++ b/contrib/python/prompt-toolkit/py2/prompt_toolkit/filters/utils.py @@ -16,8 +16,8 @@ def to_simple_filter(bool_or_filter): Accept both booleans and CLIFilters as input and turn it into a SimpleFilter. """ - if not isinstance(bool_or_filter, (bool, SimpleFilter)): - raise TypeError('Expecting a bool or a SimpleFilter instance. Got %r' % bool_or_filter) + if not isinstance(bool_or_filter, (bool, SimpleFilter)): + raise TypeError('Expecting a bool or a SimpleFilter instance. Got %r' % bool_or_filter) return { True: _always, @@ -30,8 +30,8 @@ def to_cli_filter(bool_or_filter): Accept both booleans and CLIFilters as input and turn it into a CLIFilter. """ - if not isinstance(bool_or_filter, (bool, CLIFilter)): - raise TypeError('Expecting a bool or a CLIFilter instance. Got %r' % bool_or_filter) + if not isinstance(bool_or_filter, (bool, CLIFilter)): + raise TypeError('Expecting a bool or a CLIFilter instance. Got %r' % bool_or_filter) return { True: _always, diff --git a/contrib/python/prompt-toolkit/py2/prompt_toolkit/history.py b/contrib/python/prompt-toolkit/py2/prompt_toolkit/history.py index d1eb5f2730..62ab42bd38 100644 --- a/contrib/python/prompt-toolkit/py2/prompt_toolkit/history.py +++ b/contrib/python/prompt-toolkit/py2/prompt_toolkit/history.py @@ -103,8 +103,8 @@ class FileHistory(History): # Save to file. with open(self.filename, 'ab') as f: - def write(t): - f.write(t.encode('utf-8')) + def write(t): + f.write(t.encode('utf-8')) write('\n# %s\n' % datetime.datetime.now()) for line in string.split('\n'): diff --git a/contrib/python/prompt-toolkit/py2/prompt_toolkit/input.py b/contrib/python/prompt-toolkit/py2/prompt_toolkit/input.py index f123732560..d3ed08ce86 100644 --- a/contrib/python/prompt-toolkit/py2/prompt_toolkit/input.py +++ b/contrib/python/prompt-toolkit/py2/prompt_toolkit/input.py @@ -7,7 +7,7 @@ from .utils import DummyContext, is_windows from abc import ABCMeta, abstractmethod from six import with_metaclass -import io +import io import os import sys @@ -63,21 +63,21 @@ class StdinInput(Input): def __init__(self, stdin=None): self.stdin = stdin or sys.stdin - # The input object should be a TTY. - assert self.stdin.isatty() - - # Test whether the given input object has a file descriptor. - # (Idle reports stdin to be a TTY, but fileno() is not implemented.) - try: - # This should not raise, but can return 0. - self.stdin.fileno() - except io.UnsupportedOperation: - if 'idlelib.run' in sys.modules: - raise io.UnsupportedOperation( - 'Stdin is not a terminal. Running from Idle is not supported.') - else: - raise io.UnsupportedOperation('Stdin is not a terminal.') - + # The input object should be a TTY. + assert self.stdin.isatty() + + # Test whether the given input object has a file descriptor. + # (Idle reports stdin to be a TTY, but fileno() is not implemented.) + try: + # This should not raise, but can return 0. + self.stdin.fileno() + except io.UnsupportedOperation: + if 'idlelib.run' in sys.modules: + raise io.UnsupportedOperation( + 'Stdin is not a terminal. Running from Idle is not supported.') + else: + raise io.UnsupportedOperation('Stdin is not a terminal.') + def __repr__(self): return 'StdinInput(stdin=%r)' % (self.stdin,) @@ -114,22 +114,22 @@ class PipeInput(Input): def read(self): return os.read(self._r) - def send_text(self, data): - " Send text to the input. " + def send_text(self, data): + " Send text to the input. " os.write(self._w, data.encode('utf-8')) - # Deprecated alias for `send_text`. - send = send_text - + # Deprecated alias for `send_text`. + send = send_text + def raw_mode(self): return DummyContext() def cooked_mode(self): return DummyContext() - - def close(self): - " Close pipe fds. " - os.close(self._r) - os.close(self._w) - self._r = None - self._w = None + + def close(self): + " Close pipe fds. " + os.close(self._r) + os.close(self._w) + self._r = None + self._w = None diff --git a/contrib/python/prompt-toolkit/py2/prompt_toolkit/interface.py b/contrib/python/prompt-toolkit/py2/prompt_toolkit/interface.py index e1e0e56393..9b3a1be04d 100644 --- a/contrib/python/prompt-toolkit/py2/prompt_toolkit/interface.py +++ b/contrib/python/prompt-toolkit/py2/prompt_toolkit/interface.py @@ -10,30 +10,30 @@ import six import sys import textwrap import threading -import time -import types +import time +import types import weakref -from subprocess import Popen - +from subprocess import Popen + from .application import Application, AbortAction from .buffer import Buffer from .buffer_mapping import BufferMapping -from .completion import CompleteEvent, get_common_complete_suffix +from .completion import CompleteEvent, get_common_complete_suffix from .enums import SEARCH_BUFFER from .eventloop.base import EventLoop from .eventloop.callbacks import EventLoopCallbacks from .filters import Condition from .input import StdinInput, Input from .key_binding.input_processor import InputProcessor -from .key_binding.input_processor import KeyPress -from .key_binding.registry import Registry -from .key_binding.vi_state import ViState -from .keys import Keys +from .key_binding.input_processor import KeyPress +from .key_binding.registry import Registry +from .key_binding.vi_state import ViState +from .keys import Keys from .output import Output from .renderer import Renderer, print_tokens from .search_state import SearchState -from .utils import Event +from .utils import Event # Following import is required for backwards compatibility. from .buffer import AcceptAction @@ -57,23 +57,23 @@ class CommandLineInterface(object): :param application: :class:`~prompt_toolkit.application.Application` instance. :param eventloop: The :class:`~prompt_toolkit.eventloop.base.EventLoop` to - be used when `run` is called. The easiest way to create - an eventloop is by calling - :meth:`~prompt_toolkit.shortcuts.create_eventloop`. + be used when `run` is called. The easiest way to create + an eventloop is by calling + :meth:`~prompt_toolkit.shortcuts.create_eventloop`. :param input: :class:`~prompt_toolkit.input.Input` instance. :param output: :class:`~prompt_toolkit.output.Output` instance. (Probably Vt100_Output or Win32Output.) """ def __init__(self, application, eventloop=None, input=None, output=None): assert isinstance(application, Application) - assert isinstance(eventloop, EventLoop), 'Passing an eventloop is required.' + assert isinstance(eventloop, EventLoop), 'Passing an eventloop is required.' assert output is None or isinstance(output, Output) assert input is None or isinstance(input, Input) - from .shortcuts import create_output + from .shortcuts import create_output self.application = application - self.eventloop = eventloop + self.eventloop = eventloop self._is_running = False # Inputs and outputs. @@ -84,15 +84,15 @@ class CommandLineInterface(object): assert isinstance(application.buffers, BufferMapping) self.buffers = application.buffers - #: EditingMode.VI or EditingMode.EMACS - self.editing_mode = application.editing_mode - + #: EditingMode.VI or EditingMode.EMACS + self.editing_mode = application.editing_mode + #: Quoted insert. This flag is set if we go into quoted insert mode. self.quoted_insert = False - #: Vi state. (For Vi key bindings.) - self.vi_state = ViState() - + #: Vi state. (For Vi key bindings.) + self.vi_state = ViState() + #: The `Renderer` instance. # Make sure that the same stdout is used, when a custom renderer has been passed. self.renderer = Renderer( @@ -125,20 +125,20 @@ class CommandLineInterface(object): for name, b in self.buffers.items(): self.add_buffer(name, b) - # Events. - self.on_buffer_changed = Event(self, application.on_buffer_changed) - self.on_initialize = Event(self, application.on_initialize) - self.on_input_timeout = Event(self, application.on_input_timeout) - self.on_invalidate = Event(self, application.on_invalidate) - self.on_render = Event(self, application.on_render) - self.on_reset = Event(self, application.on_reset) - self.on_start = Event(self, application.on_start) - self.on_stop = Event(self, application.on_stop) + # Events. + self.on_buffer_changed = Event(self, application.on_buffer_changed) + self.on_initialize = Event(self, application.on_initialize) + self.on_input_timeout = Event(self, application.on_input_timeout) + self.on_invalidate = Event(self, application.on_invalidate) + self.on_render = Event(self, application.on_render) + self.on_reset = Event(self, application.on_reset) + self.on_start = Event(self, application.on_start) + self.on_stop = Event(self, application.on_stop) # Trigger initialize callback. - self.reset() - self.on_initialize += self.application.on_initialize - self.on_initialize.fire() + self.reset() + self.on_initialize += self.application.on_initialize + self.on_initialize.fire() @property def layout(self): @@ -174,7 +174,7 @@ class CommandLineInterface(object): ensures that it's only called while typing if the `complete_while_typing` filter is enabled. """ - def on_text_insert(_): + def on_text_insert(_): # Only complete when "complete_while_typing" is enabled. if buffer.completer and buffer.complete_while_typing(): completer_function() @@ -187,18 +187,18 @@ class CommandLineInterface(object): buffer.on_text_insert += create_on_insert_handler() - def buffer_changed(_): - """ - When the text in a buffer changes. - (A paste event is also a change, but not an insert. So we don't - want to do autocompletions in this case, but we want to propagate - the on_buffer_changed event.) - """ - # Trigger on_buffer_changed. - self.on_buffer_changed.fire() - - buffer.on_text_changed += buffer_changed - + def buffer_changed(_): + """ + When the text in a buffer changes. + (A paste event is also a change, but not an insert. So we don't + want to do autocompletions in this case, but we want to propagate + the on_buffer_changed event.) + """ + # Trigger on_buffer_changed. + self.on_buffer_changed.fire() + + buffer.on_text_changed += buffer_changed + def start_completion(self, buffer_name=None, select_first=False, select_last=False, insert_common_part=False, complete_event=None): @@ -293,14 +293,14 @@ class CommandLineInterface(object): self.renderer.reset() self.input_processor.reset() self.layout.reset() - self.vi_state.reset() + self.vi_state.reset() # Search new search state. (Does also remember what has to be # highlighted.) self.search_state = SearchState(ignore_case=Condition(lambda: self.is_ignoring_case)) # Trigger reset event. - self.on_reset.fire() + self.on_reset.fire() @property def in_paste_mode(self): @@ -333,17 +333,17 @@ class CommandLineInterface(object): self._redraw() # Call redraw in the eventloop (thread safe). - # Usually with the high priority, in order to make the application - # feel responsive, but this can be tuned by changing the value of - # `max_render_postpone_time`. - if self.max_render_postpone_time: - _max_postpone_until = time.time() + self.max_render_postpone_time - else: - _max_postpone_until = None - - self.eventloop.call_from_executor( - redraw, _max_postpone_until=_max_postpone_until) - + # Usually with the high priority, in order to make the application + # feel responsive, but this can be tuned by changing the value of + # `max_render_postpone_time`. + if self.max_render_postpone_time: + _max_postpone_until = time.time() + self.max_render_postpone_time + else: + _max_postpone_until = None + + self.eventloop.call_from_executor( + redraw, _max_postpone_until=_max_postpone_until) + # Depracated alias for 'invalidate'. request_redraw = invalidate @@ -357,9 +357,9 @@ class CommandLineInterface(object): self.render_counter += 1 self.renderer.render(self, self.layout, is_done=self.is_done) - # Fire render event. - self.on_render.fire() - + # Fire render event. + self.on_render.fire() + def _on_resize(self): """ When the window size changes, we erase the current output and request @@ -368,7 +368,7 @@ class CommandLineInterface(object): """ # Erase, request position (when cursor is at the start position) # and redraw again. -- The order is important. - self.renderer.erase(leave_alternate_screen=False, erase_title=False) + self.renderer.erase(leave_alternate_screen=False, erase_title=False) self.renderer.request_absolute_cursor_position() self._redraw() @@ -387,7 +387,7 @@ class CommandLineInterface(object): c() del self.pre_run_callables[:] - def run(self, reset_current_buffer=False, pre_run=None): + def run(self, reset_current_buffer=False, pre_run=None): """ Read input from the command line. This runs the eventloop until a return value has been set. @@ -401,7 +401,7 @@ class CommandLineInterface(object): try: self._is_running = True - self.on_start.fire() + self.on_start.fire() self.reset() # Call pre_run. @@ -416,16 +416,16 @@ class CommandLineInterface(object): finally: # Clean up renderer. (This will leave the alternate screen, if we use # that.) - - # If exit/abort haven't been called set, but another exception was - # thrown instead for some reason, make sure that we redraw in exit - # mode. - if not self.is_done: - self._exit_flag = True - self._redraw() - + + # If exit/abort haven't been called set, but another exception was + # thrown instead for some reason, make sure that we redraw in exit + # mode. + if not self.is_done: + self._exit_flag = True + self._redraw() + self.renderer.reset() - self.on_stop.fire() + self.on_stop.fire() self._is_running = False # Return result. @@ -442,41 +442,41 @@ class CommandLineInterface(object): This is only available on Python >3.3, with asyncio. """ - # Inline import, because it slows down startup when asyncio is not - # needed. - import asyncio + # Inline import, because it slows down startup when asyncio is not + # needed. + import asyncio - @asyncio.coroutine - def run(): - assert pre_run is None or callable(pre_run) + @asyncio.coroutine + def run(): + assert pre_run is None or callable(pre_run) - try: - self._is_running = True + try: + self._is_running = True - self.on_start.fire() + self.on_start.fire() self.reset() - # Call pre_run. + # Call pre_run. self._pre_run(pre_run) - with self.input.raw_mode(): - self.renderer.request_absolute_cursor_position() - self._redraw() - - yield from self.eventloop.run_as_coroutine( - self.input, self.create_eventloop_callbacks()) - - return self.return_value() - finally: - if not self.is_done: - self._exit_flag = True - self._redraw() - - self.renderer.reset() - self.on_stop.fire() - self._is_running = False - - return run() + with self.input.raw_mode(): + self.renderer.request_absolute_cursor_position() + self._redraw() + + yield from self.eventloop.run_as_coroutine( + self.input, self.create_eventloop_callbacks()) + + return self.return_value() + finally: + if not self.is_done: + self._exit_flag = True + self._redraw() + + self.renderer.reset() + self.on_stop.fire() + self._is_running = False + + return run() ''')) except SyntaxError: # Python2, or early versions of Python 3. @@ -488,9 +488,9 @@ class CommandLineInterface(object): """ raise NotImplementedError - def run_sub_application(self, application, done_callback=None, erase_when_done=False, - _from_application_generator=False): - # `erase_when_done` is deprecated, set Application.erase_when_done instead. + def run_sub_application(self, application, done_callback=None, erase_when_done=False, + _from_application_generator=False): + # `erase_when_done` is deprecated, set Application.erase_when_done instead. """ Run a sub :class:`~prompt_toolkit.application.Application`. @@ -514,8 +514,8 @@ class CommandLineInterface(object): raise RuntimeError('Another sub application started already.') # Erase current application. - if not _from_application_generator: - self.renderer.erase() + if not _from_application_generator: + self.renderer.erase() # Callback when the sub app is done. def done(): @@ -523,17 +523,17 @@ class CommandLineInterface(object): # and reset the renderer. (This reset will also quit the alternate # screen, if the sub application used that.) sub_cli._redraw() - if erase_when_done or application.erase_when_done: - sub_cli.renderer.erase() + if erase_when_done or application.erase_when_done: + sub_cli.renderer.erase() sub_cli.renderer.reset() sub_cli._is_running = False # Don't render anymore. self._sub_cli = None # Restore main application. - if not _from_application_generator: - self.renderer.request_absolute_cursor_position() - self._redraw() + if not _from_application_generator: + self.renderer.request_absolute_cursor_position() + self._redraw() # Deliver result. if done_callback: @@ -636,7 +636,7 @@ class CommandLineInterface(object): self.renderer.reset() # Make sure to disable mouse mode, etc... else: self.renderer.erase() - self._return_value = None + self._return_value = None # Run system command. if cooked_mode: @@ -652,63 +652,63 @@ class CommandLineInterface(object): return result - def run_application_generator(self, coroutine, render_cli_done=False): - """ - EXPERIMENTAL - Like `run_in_terminal`, but takes a generator that can yield Application instances. - - Example: - - def f(): - yield Application1(...) - print('...') - yield Application2(...) - cli.run_in_terminal_async(f) - - The values which are yielded by the given coroutine are supposed to be - `Application` instances that run in the current CLI, all other code is - supposed to be CPU bound, so except for yielding the applications, - there should not be any user interaction or I/O in the given function. - """ - # Draw interface in 'done' state, or erase. - if render_cli_done: - self._return_value = True - self._redraw() - self.renderer.reset() # Make sure to disable mouse mode, etc... - else: - self.renderer.erase() - self._return_value = None - - # Loop through the generator. - g = coroutine() - assert isinstance(g, types.GeneratorType) - - def step_next(send_value=None): - " Execute next step of the coroutine." - try: - # Run until next yield, in cooked mode. - with self.input.cooked_mode(): - result = g.send(send_value) - except StopIteration: - done() - except: - done() - raise - else: - # Process yielded value from coroutine. - assert isinstance(result, Application) - self.run_sub_application(result, done_callback=step_next, - _from_application_generator=True) - - def done(): - # Redraw interface again. - self.renderer.reset() - self.renderer.request_absolute_cursor_position() - self._redraw() - - # Start processing coroutine. - step_next() - + def run_application_generator(self, coroutine, render_cli_done=False): + """ + EXPERIMENTAL + Like `run_in_terminal`, but takes a generator that can yield Application instances. + + Example: + + def f(): + yield Application1(...) + print('...') + yield Application2(...) + cli.run_in_terminal_async(f) + + The values which are yielded by the given coroutine are supposed to be + `Application` instances that run in the current CLI, all other code is + supposed to be CPU bound, so except for yielding the applications, + there should not be any user interaction or I/O in the given function. + """ + # Draw interface in 'done' state, or erase. + if render_cli_done: + self._return_value = True + self._redraw() + self.renderer.reset() # Make sure to disable mouse mode, etc... + else: + self.renderer.erase() + self._return_value = None + + # Loop through the generator. + g = coroutine() + assert isinstance(g, types.GeneratorType) + + def step_next(send_value=None): + " Execute next step of the coroutine." + try: + # Run until next yield, in cooked mode. + with self.input.cooked_mode(): + result = g.send(send_value) + except StopIteration: + done() + except: + done() + raise + else: + # Process yielded value from coroutine. + assert isinstance(result, Application) + self.run_sub_application(result, done_callback=step_next, + _from_application_generator=True) + + def done(): + # Redraw interface again. + self.renderer.reset() + self.renderer.request_absolute_cursor_position() + self._redraw() + + # Start processing coroutine. + step_next() + def run_system_command(self, command): """ Run system command (While hiding the prompt. When finished, all the @@ -716,57 +716,57 @@ class CommandLineInterface(object): :param command: Shell command to be executed. """ - def wait_for_enter(): - """ - Create a sub application to wait for the enter key press. - This has two advantages over using 'input'/'raw_input': - - This will share the same input/output I/O. - - This doesn't block the event loop. - """ - from .shortcuts import create_prompt_application - - registry = Registry() - - @registry.add_binding(Keys.ControlJ) - @registry.add_binding(Keys.ControlM) - def _(event): - event.cli.set_return_value(None) - - application = create_prompt_application( - message='Press ENTER to continue...', - key_bindings_registry=registry) - self.run_sub_application(application) - + def wait_for_enter(): + """ + Create a sub application to wait for the enter key press. + This has two advantages over using 'input'/'raw_input': + - This will share the same input/output I/O. + - This doesn't block the event loop. + """ + from .shortcuts import create_prompt_application + + registry = Registry() + + @registry.add_binding(Keys.ControlJ) + @registry.add_binding(Keys.ControlM) + def _(event): + event.cli.set_return_value(None) + + application = create_prompt_application( + message='Press ENTER to continue...', + key_bindings_registry=registry) + self.run_sub_application(application) + def run(): - # Try to use the same input/output file descriptors as the one, - # used to run this application. - try: - input_fd = self.input.fileno() - except AttributeError: - input_fd = sys.stdin.fileno() + # Try to use the same input/output file descriptors as the one, + # used to run this application. try: - output_fd = self.output.fileno() - except AttributeError: - output_fd = sys.stdout.fileno() - - # Run sub process. - # XXX: This will still block the event loop. - p = Popen(command, shell=True, - stdin=input_fd, stdout=output_fd) - p.wait() - - # Wait for the user to press enter. - wait_for_enter() - + input_fd = self.input.fileno() + except AttributeError: + input_fd = sys.stdin.fileno() + try: + output_fd = self.output.fileno() + except AttributeError: + output_fd = sys.stdout.fileno() + + # Run sub process. + # XXX: This will still block the event loop. + p = Popen(command, shell=True, + stdin=input_fd, stdout=output_fd) + p.wait() + + # Wait for the user to press enter. + wait_for_enter() + self.run_in_terminal(run) - def suspend_to_background(self, suspend_group=True): + def suspend_to_background(self, suspend_group=True): """ (Not thread safe -- to be called from inside the key bindings.) Suspend process. - - :param suspend_group: When true, suspend the whole process group. - (This is the default, and probably what you want.) + + :param suspend_group: When true, suspend the whole process group. + (This is the default, and probably what you want.) """ # Only suspend when the opperating system supports it. # (Not on Windows.) @@ -775,13 +775,13 @@ class CommandLineInterface(object): # Send `SIGSTP` to own process. # This will cause it to suspend. - # Usually we want the whole process group to be suspended. This - # handles the case when input is piped from another process. - if suspend_group: - os.kill(0, signal.SIGTSTP) - else: - os.kill(os.getpid(), signal.SIGTSTP) - + # Usually we want the whole process group to be suspended. This + # handles the case when input is piped from another process. + if suspend_group: + os.kill(0, signal.SIGTSTP) + else: + os.kill(os.getpid(), signal.SIGTSTP) + self.run_in_terminal(run) def print_tokens(self, tokens, style=None): @@ -835,16 +835,16 @@ class CommandLineInterface(object): """ complete_thread_running = [False] # By ref. - def completion_does_nothing(document, completion): - """ - Return `True` if applying this completion doesn't have any effect. - (When it doesn't insert any new text. - """ - text_before_cursor = document.text_before_cursor - replaced_text = text_before_cursor[ - len(text_before_cursor) + completion.start_position:] - return replaced_text == completion.text - + def completion_does_nothing(document, completion): + """ + Return `True` if applying this completion doesn't have any effect. + (When it doesn't insert any new text. + """ + text_before_cursor = document.text_before_cursor + replaced_text = text_before_cursor[ + len(text_before_cursor) + completion.start_position:] + return replaced_text == completion.text + def async_completer(select_first=False, select_last=False, insert_common_part=False, complete_event=None): document = buffer.document @@ -871,13 +871,13 @@ class CommandLineInterface(object): pressed 'Tab' in the meantime. Also don't set it if the text was changed in the meantime. """ - complete_thread_running[0] = False - - # When there is only one completion, which has nothing to add, ignore it. - if (len(completions) == 1 and - completion_does_nothing(document, completions[0])): - del completions[:] - + complete_thread_running[0] = False + + # When there is only one completion, which has nothing to add, ignore it. + if (len(completions) == 1 and + completion_does_nothing(document, completions[0])): + del completions[:] + # Set completions if the text was not yet changed. if buffer.text == document.text and \ buffer.cursor_position == document.cursor_position and \ @@ -886,28 +886,28 @@ class CommandLineInterface(object): set_completions = True select_first_anyway = False - # When the common part has to be inserted, and there + # When the common part has to be inserted, and there # is a common part. if insert_common_part: common_part = get_common_complete_suffix(document, completions) if common_part: - # Insert the common part, update completions. + # Insert the common part, update completions. buffer.insert_text(common_part) - if len(completions) > 1: - # (Don't call `async_completer` again, but - # recalculate completions. See: - # https://github.com/ipython/ipython/issues/9658) - completions[:] = [ - c.new_completion_from_position(len(common_part)) - for c in completions] - else: - set_completions = False + if len(completions) > 1: + # (Don't call `async_completer` again, but + # recalculate completions. See: + # https://github.com/ipython/ipython/issues/9658) + completions[:] = [ + c.new_completion_from_position(len(common_part)) + for c in completions] + else: + set_completions = False else: # When we were asked to insert the "common" # prefix, but there was no common suffix but # still exactly one match, then select the # first. (It could be that we have a completion - # which does * expansion, like '*.py', with + # which does * expansion, like '*.py', with # exactly one match.) if len(completions) == 1: select_first_anyway = True @@ -918,7 +918,7 @@ class CommandLineInterface(object): go_to_first=select_first or select_first_anyway, go_to_last=select_last) self.invalidate() - elif not buffer.complete_state: + elif not buffer.complete_state: # Otherwise, restart thread. async_completer() @@ -953,8 +953,8 @@ class CommandLineInterface(object): suggestion = buffer.auto_suggest.get_suggestion(self, buffer, document) def callback(): - suggest_thread_running[0] = False - + suggest_thread_running[0] = False + # Set suggestion only if the text was not yet changed. if buffer.text == document.text and \ buffer.cursor_position == document.cursor_position: @@ -984,18 +984,18 @@ class CommandLineInterface(object): """ return _StdoutProxy(self, raw=raw) - def patch_stdout_context(self, raw=False, patch_stdout=True, patch_stderr=True): + def patch_stdout_context(self, raw=False, patch_stdout=True, patch_stderr=True): """ Return a context manager that will replace ``sys.stdout`` with a proxy that makes sure that all printed text will appear above the prompt, and that it doesn't destroy the output from the renderer. - - :param patch_stdout: Replace `sys.stdout`. - :param patch_stderr: Replace `sys.stderr`. + + :param patch_stdout: Replace `sys.stdout`. + :param patch_stderr: Replace `sys.stderr`. """ - return _PatchStdoutContext( - self.stdout_proxy(raw=raw), - patch_stdout=patch_stdout, patch_stderr=patch_stderr) + return _PatchStdoutContext( + self.stdout_proxy(raw=raw), + patch_stdout=patch_stdout, patch_stderr=patch_stderr) def create_eventloop_callbacks(self): return _InterfaceEventLoopCallbacks(self) @@ -1031,46 +1031,46 @@ class _InterfaceEventLoopCallbacks(EventLoopCallbacks): def input_timeout(self): cli = self._active_cli - cli.on_input_timeout.fire() + cli.on_input_timeout.fire() def feed_key(self, key_press): """ Feed a key press to the CommandLineInterface. """ - assert isinstance(key_press, KeyPress) - cli = self._active_cli - + assert isinstance(key_press, KeyPress) + cli = self._active_cli + # Feed the key and redraw. - # (When the CLI is in 'done' state, it should return to the event loop - # as soon as possible. Ignore all key presses beyond this point.) - if not cli.is_done: - cli.input_processor.feed(key_press) - cli.input_processor.process_keys() + # (When the CLI is in 'done' state, it should return to the event loop + # as soon as possible. Ignore all key presses beyond this point.) + if not cli.is_done: + cli.input_processor.feed(key_press) + cli.input_processor.process_keys() class _PatchStdoutContext(object): - def __init__(self, new_stdout, patch_stdout=True, patch_stderr=True): + def __init__(self, new_stdout, patch_stdout=True, patch_stderr=True): self.new_stdout = new_stdout - self.patch_stdout = patch_stdout - self.patch_stderr = patch_stderr + self.patch_stdout = patch_stdout + self.patch_stderr = patch_stderr def __enter__(self): self.original_stdout = sys.stdout - self.original_stderr = sys.stderr - - if self.patch_stdout: - sys.stdout = self.new_stdout - if self.patch_stderr: - sys.stderr = self.new_stdout + self.original_stderr = sys.stderr + if self.patch_stdout: + sys.stdout = self.new_stdout + if self.patch_stderr: + sys.stderr = self.new_stdout + def __exit__(self, *a, **kw): - if self.patch_stdout: - sys.stdout = self.original_stdout - - if self.patch_stderr: - sys.stderr = self.original_stderr + if self.patch_stdout: + sys.stdout = self.original_stdout + if self.patch_stderr: + sys.stderr = self.original_stderr + class _StdoutProxy(object): """ Proxy for stdout, as returned by diff --git a/contrib/python/prompt-toolkit/py2/prompt_toolkit/key_binding/bindings/basic.py b/contrib/python/prompt-toolkit/py2/prompt_toolkit/key_binding/bindings/basic.py index 401135dec0..6debd6b9c9 100644 --- a/contrib/python/prompt-toolkit/py2/prompt_toolkit/key_binding/bindings/basic.py +++ b/contrib/python/prompt-toolkit/py2/prompt_toolkit/key_binding/bindings/basic.py @@ -5,11 +5,11 @@ from prompt_toolkit.enums import DEFAULT_BUFFER from prompt_toolkit.filters import HasSelection, Condition, EmacsInsertMode, ViInsertMode from prompt_toolkit.keys import Keys from prompt_toolkit.layout.screen import Point -from prompt_toolkit.mouse_events import MouseEventType, MouseEvent +from prompt_toolkit.mouse_events import MouseEventType, MouseEvent from prompt_toolkit.renderer import HeightIsUnknownError from prompt_toolkit.utils import suspend_to_background_supported, is_windows -from .named_commands import get_by_name +from .named_commands import get_by_name from ..registry import Registry @@ -28,7 +28,7 @@ def if_no_repeat(event): def load_basic_bindings(): registry = Registry() - insert_mode = ViInsertMode() | EmacsInsertMode() + insert_mode = ViInsertMode() | EmacsInsertMode() handle = registry.add_binding has_selection = HasSelection() @@ -88,15 +88,15 @@ def load_basic_bindings(): @handle(Keys.Down) @handle(Keys.Right) @handle(Keys.Left) - @handle(Keys.ShiftUp) - @handle(Keys.ShiftDown) - @handle(Keys.ShiftRight) - @handle(Keys.ShiftLeft) + @handle(Keys.ShiftUp) + @handle(Keys.ShiftDown) + @handle(Keys.ShiftRight) + @handle(Keys.ShiftLeft) @handle(Keys.Home) @handle(Keys.End) @handle(Keys.Delete) @handle(Keys.ShiftDelete) - @handle(Keys.ControlDelete) + @handle(Keys.ControlDelete) @handle(Keys.PageUp) @handle(Keys.PageDown) @handle(Keys.BackTab) @@ -106,7 +106,7 @@ def load_basic_bindings(): @handle(Keys.ControlUp) @handle(Keys.ControlDown) @handle(Keys.Insert) - @handle(Keys.Ignore) + @handle(Keys.Ignore) def _(event): """ First, for any of these keys, Don't do anything by default. Also don't @@ -118,61 +118,61 @@ def load_basic_bindings(): """ pass - # Readline-style bindings. - handle(Keys.Home)(get_by_name('beginning-of-line')) - handle(Keys.End)(get_by_name('end-of-line')) - handle(Keys.Left)(get_by_name('backward-char')) - handle(Keys.Right)(get_by_name('forward-char')) - handle(Keys.ControlUp)(get_by_name('previous-history')) - handle(Keys.ControlDown)(get_by_name('next-history')) - handle(Keys.ControlL)(get_by_name('clear-screen')) - - handle(Keys.ControlK, filter=insert_mode)(get_by_name('kill-line')) - handle(Keys.ControlU, filter=insert_mode)(get_by_name('unix-line-discard')) - handle(Keys.ControlH, filter=insert_mode, save_before=if_no_repeat)( - get_by_name('backward-delete-char')) - handle(Keys.Backspace, filter=insert_mode, save_before=if_no_repeat)( - get_by_name('backward-delete-char')) - handle(Keys.Delete, filter=insert_mode, save_before=if_no_repeat)( - get_by_name('delete-char')) - handle(Keys.ShiftDelete, filter=insert_mode, save_before=if_no_repeat)( - get_by_name('delete-char')) - handle(Keys.Any, filter=insert_mode, save_before=if_no_repeat)( - get_by_name('self-insert')) - handle(Keys.ControlT, filter=insert_mode)(get_by_name('transpose-chars')) - handle(Keys.ControlW, filter=insert_mode)(get_by_name('unix-word-rubout')) + # Readline-style bindings. + handle(Keys.Home)(get_by_name('beginning-of-line')) + handle(Keys.End)(get_by_name('end-of-line')) + handle(Keys.Left)(get_by_name('backward-char')) + handle(Keys.Right)(get_by_name('forward-char')) + handle(Keys.ControlUp)(get_by_name('previous-history')) + handle(Keys.ControlDown)(get_by_name('next-history')) + handle(Keys.ControlL)(get_by_name('clear-screen')) + + handle(Keys.ControlK, filter=insert_mode)(get_by_name('kill-line')) + handle(Keys.ControlU, filter=insert_mode)(get_by_name('unix-line-discard')) + handle(Keys.ControlH, filter=insert_mode, save_before=if_no_repeat)( + get_by_name('backward-delete-char')) + handle(Keys.Backspace, filter=insert_mode, save_before=if_no_repeat)( + get_by_name('backward-delete-char')) + handle(Keys.Delete, filter=insert_mode, save_before=if_no_repeat)( + get_by_name('delete-char')) + handle(Keys.ShiftDelete, filter=insert_mode, save_before=if_no_repeat)( + get_by_name('delete-char')) + handle(Keys.Any, filter=insert_mode, save_before=if_no_repeat)( + get_by_name('self-insert')) + handle(Keys.ControlT, filter=insert_mode)(get_by_name('transpose-chars')) + handle(Keys.ControlW, filter=insert_mode)(get_by_name('unix-word-rubout')) handle(Keys.ControlI, filter=insert_mode)(get_by_name('menu-complete')) handle(Keys.BackTab, filter=insert_mode)(get_by_name('menu-complete-backward')) - handle(Keys.PageUp, filter= ~has_selection)(get_by_name('previous-history')) - handle(Keys.PageDown, filter= ~has_selection)(get_by_name('next-history')) - + handle(Keys.PageUp, filter= ~has_selection)(get_by_name('previous-history')) + handle(Keys.PageDown, filter= ~has_selection)(get_by_name('next-history')) + # CTRL keys. - text_before_cursor = Condition(lambda cli: cli.current_buffer.text) - handle(Keys.ControlD, filter=text_before_cursor & insert_mode)(get_by_name('delete-char')) + text_before_cursor = Condition(lambda cli: cli.current_buffer.text) + handle(Keys.ControlD, filter=text_before_cursor & insert_mode)(get_by_name('delete-char')) - is_multiline = Condition(lambda cli: cli.current_buffer.is_multiline()) - is_returnable = Condition(lambda cli: cli.current_buffer.accept_action.is_returnable) + is_multiline = Condition(lambda cli: cli.current_buffer.is_multiline()) + is_returnable = Condition(lambda cli: cli.current_buffer.accept_action.is_returnable) - @handle(Keys.ControlJ, filter=is_multiline & insert_mode) + @handle(Keys.ControlJ, filter=is_multiline & insert_mode) def _(event): - " Newline (in case of multiline input. " - event.current_buffer.newline(copy_margin=not event.cli.in_paste_mode) + " Newline (in case of multiline input. " + event.current_buffer.newline(copy_margin=not event.cli.in_paste_mode) - @handle(Keys.ControlJ, filter=~is_multiline & is_returnable) + @handle(Keys.ControlJ, filter=~is_multiline & is_returnable) def _(event): - " Enter, accept input. " - buff = event.current_buffer - buff.accept_action.validate_and_handle(event.cli, buff) + " Enter, accept input. " + buff = event.current_buffer + buff.accept_action.validate_and_handle(event.cli, buff) - # Delete the word before the cursor. + # Delete the word before the cursor. - @handle(Keys.Up) + @handle(Keys.Up) def _(event): event.current_buffer.auto_up(count=event.arg) - @handle(Keys.Down) + @handle(Keys.Down) def _(event): event.current_buffer.auto_down(count=event.arg) @@ -211,16 +211,16 @@ def load_basic_bindings(): @handle(Keys.BracketedPaste) def _(event): " Pasting from clipboard. " - data = event.data - - # Be sure to use \n as line ending. - # Some terminals (Like iTerm2) seem to paste \r\n line endings in a - # bracketed paste. See: https://github.com/ipython/ipython/issues/9737 - data = data.replace('\r\n', '\n') - data = data.replace('\r', '\n') - - event.current_buffer.insert_text(data) - + data = event.data + + # Be sure to use \n as line ending. + # Some terminals (Like iTerm2) seem to paste \r\n line endings in a + # bracketed paste. See: https://github.com/ipython/ipython/issues/9737 + data = data.replace('\r\n', '\n') + data = data.replace('\r', '\n') + + event.current_buffer.insert_text(data) + @handle(Keys.Any, filter=Condition(lambda cli: cli.quoted_insert), eager=True) def _(event): """ @@ -228,15 +228,15 @@ def load_basic_bindings(): """ event.current_buffer.insert_text(event.data, overwrite=False) event.cli.quoted_insert = False - + return registry def load_mouse_bindings(): - """ - Key bindings, required for mouse support. - (Mouse events enter through the key binding system.) - """ + """ + Key bindings, required for mouse support. + (Mouse events enter through the key binding system.) + """ registry = Registry() @registry.add_binding(Keys.Vt100MouseEvent) @@ -253,16 +253,16 @@ def load_mouse_bindings(): # Typical. mouse_event, x, y = map(ord, event.data[3:]) mouse_event = { - 32: MouseEventType.MOUSE_DOWN, - 35: MouseEventType.MOUSE_UP, - 96: MouseEventType.SCROLL_UP, - 97: MouseEventType.SCROLL_DOWN, + 32: MouseEventType.MOUSE_DOWN, + 35: MouseEventType.MOUSE_UP, + 96: MouseEventType.SCROLL_UP, + 97: MouseEventType.SCROLL_DOWN, }.get(mouse_event) - - # Handle situations where `PosixStdinReader` used surrogateescapes. - if x >= 0xdc00: x-= 0xdc00 - if y >= 0xdc00: y-= 0xdc00 - + + # Handle situations where `PosixStdinReader` used surrogateescapes. + if x >= 0xdc00: x-= 0xdc00 + if y >= 0xdc00: y-= 0xdc00 + x -= 32 y -= 32 else: @@ -283,17 +283,17 @@ def load_mouse_bindings(): # Parse event type. if sgr: mouse_event = { - (0, 'M'): MouseEventType.MOUSE_DOWN, - (0, 'm'): MouseEventType.MOUSE_UP, - (64, 'M'): MouseEventType.SCROLL_UP, - (65, 'M'): MouseEventType.SCROLL_DOWN, + (0, 'M'): MouseEventType.MOUSE_DOWN, + (0, 'm'): MouseEventType.MOUSE_UP, + (64, 'M'): MouseEventType.SCROLL_UP, + (65, 'M'): MouseEventType.SCROLL_DOWN, }.get((mouse_event, m)) else: mouse_event = { - 32: MouseEventType.MOUSE_DOWN, - 35: MouseEventType.MOUSE_UP, - 96: MouseEventType.SCROLL_UP, - 97: MouseEventType.SCROLL_DOWN, + 32: MouseEventType.MOUSE_DOWN, + 35: MouseEventType.MOUSE_UP, + 96: MouseEventType.SCROLL_UP, + 97: MouseEventType.SCROLL_DOWN, }.get(mouse_event) x -= 1 @@ -357,7 +357,7 @@ def load_abort_and_exit_bindings(): return (cli.current_buffer_name == DEFAULT_BUFFER and not cli.current_buffer.text) - handle(Keys.ControlD, filter=ctrl_d_condition)(get_by_name('end-of-file')) + handle(Keys.ControlD, filter=ctrl_d_condition)(get_by_name('end-of-file')) return registry diff --git a/contrib/python/prompt-toolkit/py2/prompt_toolkit/key_binding/bindings/completion.py b/contrib/python/prompt-toolkit/py2/prompt_toolkit/key_binding/bindings/completion.py index 4903900bc6..2b6405a1fa 100644 --- a/contrib/python/prompt-toolkit/py2/prompt_toolkit/key_binding/bindings/completion.py +++ b/contrib/python/prompt-toolkit/py2/prompt_toolkit/key_binding/bindings/completion.py @@ -1,161 +1,161 @@ -""" -Key binding handlers for displaying completions. -""" -from __future__ import unicode_literals -from prompt_toolkit.completion import CompleteEvent, get_common_complete_suffix -from prompt_toolkit.utils import get_cwidth -from prompt_toolkit.keys import Keys -from prompt_toolkit.key_binding.registry import Registry - -import math - -__all__ = ( - 'generate_completions', - 'display_completions_like_readline', -) - -def generate_completions(event): - r""" - Tab-completion: where the first tab completes the common suffix and the - second tab lists all the completions. - """ - b = event.current_buffer - - # When already navigating through completions, select the next one. - if b.complete_state: - b.complete_next() - else: - event.cli.start_completion(insert_common_part=True, select_first=False) - - -def display_completions_like_readline(event): - """ - Key binding handler for readline-style tab completion. - This is meant to be as similar as possible to the way how readline displays - completions. - - Generate the completions immediately (blocking) and display them above the - prompt in columns. - - Usage:: - - # Call this handler when 'Tab' has been pressed. - registry.add_binding(Keys.ControlI)(display_completions_like_readline) - """ - # Request completions. - b = event.current_buffer - if b.completer is None: - return - complete_event = CompleteEvent(completion_requested=True) - completions = list(b.completer.get_completions(b.document, complete_event)) - - # Calculate the common suffix. - common_suffix = get_common_complete_suffix(b.document, completions) - - # One completion: insert it. - if len(completions) == 1: - b.delete_before_cursor(-completions[0].start_position) - b.insert_text(completions[0].text) - # Multiple completions with common part. - elif common_suffix: - b.insert_text(common_suffix) - # Otherwise: display all completions. - elif completions: - _display_completions_like_readline(event.cli, completions) - - -def _display_completions_like_readline(cli, completions): - """ - Display the list of completions in columns above the prompt. - This will ask for a confirmation if there are too many completions to fit - on a single page and provide a paginator to walk through them. - """ - from prompt_toolkit.shortcuts import create_confirm_application - assert isinstance(completions, list) - - # Get terminal dimensions. - term_size = cli.output.get_size() - term_width = term_size.columns - term_height = term_size.rows - - # Calculate amount of required columns/rows for displaying the - # completions. (Keep in mind that completions are displayed - # alphabetically column-wise.) - max_compl_width = min(term_width, - max(get_cwidth(c.text) for c in completions) + 1) - column_count = max(1, term_width // max_compl_width) - completions_per_page = column_count * (term_height - 1) - page_count = int(math.ceil(len(completions) / float(completions_per_page))) - # Note: math.ceil can return float on Python2. - - def display(page): - # Display completions. - page_completions = completions[page * completions_per_page: - (page+1) * completions_per_page] - - page_row_count = int(math.ceil(len(page_completions) / float(column_count))) - page_columns = [page_completions[i * page_row_count:(i+1) * page_row_count] - for i in range(column_count)] - - result = [] - for r in range(page_row_count): - for c in range(column_count): - try: - result.append(page_columns[c][r].text.ljust(max_compl_width)) - except IndexError: - pass - result.append('\n') - cli.output.write(''.join(result)) - cli.output.flush() - - # User interaction through an application generator function. - def run(): - if len(completions) > completions_per_page: - # Ask confirmation if it doesn't fit on the screen. - message = 'Display all {} possibilities? (y on n) '.format(len(completions)) - confirm = yield create_confirm_application(message) - - if confirm: - # Display pages. - for page in range(page_count): - display(page) - - if page != page_count - 1: - # Display --MORE-- and go to the next page. - show_more = yield _create_more_application() - if not show_more: - return - else: - cli.output.write('\n'); cli.output.flush() - else: - # Display all completions. - display(0) - - cli.run_application_generator(run, render_cli_done=True) - - -def _create_more_application(): - """ - Create an `Application` instance that displays the "--MORE--". - """ - from prompt_toolkit.shortcuts import create_prompt_application - registry = Registry() - - @registry.add_binding(' ') - @registry.add_binding('y') - @registry.add_binding('Y') - @registry.add_binding(Keys.ControlJ) - @registry.add_binding(Keys.ControlI) # Tab. - def _(event): - event.cli.set_return_value(True) - - @registry.add_binding('n') - @registry.add_binding('N') - @registry.add_binding('q') - @registry.add_binding('Q') - @registry.add_binding(Keys.ControlC) - def _(event): - event.cli.set_return_value(False) - - return create_prompt_application( - '--MORE--', key_bindings_registry=registry, erase_when_done=True) +""" +Key binding handlers for displaying completions. +""" +from __future__ import unicode_literals +from prompt_toolkit.completion import CompleteEvent, get_common_complete_suffix +from prompt_toolkit.utils import get_cwidth +from prompt_toolkit.keys import Keys +from prompt_toolkit.key_binding.registry import Registry + +import math + +__all__ = ( + 'generate_completions', + 'display_completions_like_readline', +) + +def generate_completions(event): + r""" + Tab-completion: where the first tab completes the common suffix and the + second tab lists all the completions. + """ + b = event.current_buffer + + # When already navigating through completions, select the next one. + if b.complete_state: + b.complete_next() + else: + event.cli.start_completion(insert_common_part=True, select_first=False) + + +def display_completions_like_readline(event): + """ + Key binding handler for readline-style tab completion. + This is meant to be as similar as possible to the way how readline displays + completions. + + Generate the completions immediately (blocking) and display them above the + prompt in columns. + + Usage:: + + # Call this handler when 'Tab' has been pressed. + registry.add_binding(Keys.ControlI)(display_completions_like_readline) + """ + # Request completions. + b = event.current_buffer + if b.completer is None: + return + complete_event = CompleteEvent(completion_requested=True) + completions = list(b.completer.get_completions(b.document, complete_event)) + + # Calculate the common suffix. + common_suffix = get_common_complete_suffix(b.document, completions) + + # One completion: insert it. + if len(completions) == 1: + b.delete_before_cursor(-completions[0].start_position) + b.insert_text(completions[0].text) + # Multiple completions with common part. + elif common_suffix: + b.insert_text(common_suffix) + # Otherwise: display all completions. + elif completions: + _display_completions_like_readline(event.cli, completions) + + +def _display_completions_like_readline(cli, completions): + """ + Display the list of completions in columns above the prompt. + This will ask for a confirmation if there are too many completions to fit + on a single page and provide a paginator to walk through them. + """ + from prompt_toolkit.shortcuts import create_confirm_application + assert isinstance(completions, list) + + # Get terminal dimensions. + term_size = cli.output.get_size() + term_width = term_size.columns + term_height = term_size.rows + + # Calculate amount of required columns/rows for displaying the + # completions. (Keep in mind that completions are displayed + # alphabetically column-wise.) + max_compl_width = min(term_width, + max(get_cwidth(c.text) for c in completions) + 1) + column_count = max(1, term_width // max_compl_width) + completions_per_page = column_count * (term_height - 1) + page_count = int(math.ceil(len(completions) / float(completions_per_page))) + # Note: math.ceil can return float on Python2. + + def display(page): + # Display completions. + page_completions = completions[page * completions_per_page: + (page+1) * completions_per_page] + + page_row_count = int(math.ceil(len(page_completions) / float(column_count))) + page_columns = [page_completions[i * page_row_count:(i+1) * page_row_count] + for i in range(column_count)] + + result = [] + for r in range(page_row_count): + for c in range(column_count): + try: + result.append(page_columns[c][r].text.ljust(max_compl_width)) + except IndexError: + pass + result.append('\n') + cli.output.write(''.join(result)) + cli.output.flush() + + # User interaction through an application generator function. + def run(): + if len(completions) > completions_per_page: + # Ask confirmation if it doesn't fit on the screen. + message = 'Display all {} possibilities? (y on n) '.format(len(completions)) + confirm = yield create_confirm_application(message) + + if confirm: + # Display pages. + for page in range(page_count): + display(page) + + if page != page_count - 1: + # Display --MORE-- and go to the next page. + show_more = yield _create_more_application() + if not show_more: + return + else: + cli.output.write('\n'); cli.output.flush() + else: + # Display all completions. + display(0) + + cli.run_application_generator(run, render_cli_done=True) + + +def _create_more_application(): + """ + Create an `Application` instance that displays the "--MORE--". + """ + from prompt_toolkit.shortcuts import create_prompt_application + registry = Registry() + + @registry.add_binding(' ') + @registry.add_binding('y') + @registry.add_binding('Y') + @registry.add_binding(Keys.ControlJ) + @registry.add_binding(Keys.ControlI) # Tab. + def _(event): + event.cli.set_return_value(True) + + @registry.add_binding('n') + @registry.add_binding('N') + @registry.add_binding('q') + @registry.add_binding('Q') + @registry.add_binding(Keys.ControlC) + def _(event): + event.cli.set_return_value(False) + + return create_prompt_application( + '--MORE--', key_bindings_registry=registry, erase_when_done=True) diff --git a/contrib/python/prompt-toolkit/py2/prompt_toolkit/key_binding/bindings/emacs.py b/contrib/python/prompt-toolkit/py2/prompt_toolkit/key_binding/bindings/emacs.py index bccdb04ff3..ff27532fec 100644 --- a/contrib/python/prompt-toolkit/py2/prompt_toolkit/key_binding/bindings/emacs.py +++ b/contrib/python/prompt-toolkit/py2/prompt_toolkit/key_binding/bindings/emacs.py @@ -4,10 +4,10 @@ from prompt_toolkit.buffer import SelectionType, indent, unindent from prompt_toolkit.keys import Keys from prompt_toolkit.enums import IncrementalSearchDirection, SEARCH_BUFFER, SYSTEM_BUFFER from prompt_toolkit.filters import Condition, EmacsMode, HasSelection, EmacsInsertMode, HasFocus, HasArg -from prompt_toolkit.completion import CompleteEvent +from prompt_toolkit.completion import CompleteEvent from .scroll import scroll_page_up, scroll_page_down -from .named_commands import get_by_name +from .named_commands import get_by_name from ..registry import Registry, ConditionalRegistry __all__ = ( @@ -27,8 +27,8 @@ def load_emacs_bindings(): registry = ConditionalRegistry(Registry(), EmacsMode()) handle = registry.add_binding - insert_mode = EmacsInsertMode() - has_selection = HasSelection() + insert_mode = EmacsInsertMode() + has_selection = HasSelection() @handle(Keys.Escape) def _(event): @@ -42,42 +42,42 @@ def load_emacs_bindings(): """ pass - handle(Keys.ControlA)(get_by_name('beginning-of-line')) - handle(Keys.ControlB)(get_by_name('backward-char')) - handle(Keys.ControlDelete, filter=insert_mode)(get_by_name('kill-word')) - handle(Keys.ControlE)(get_by_name('end-of-line')) - handle(Keys.ControlF)(get_by_name('forward-char')) - handle(Keys.ControlLeft)(get_by_name('backward-word')) - handle(Keys.ControlRight)(get_by_name('forward-word')) - handle(Keys.ControlX, 'r', 'y', filter=insert_mode)(get_by_name('yank')) - handle(Keys.ControlY, filter=insert_mode)(get_by_name('yank')) - handle(Keys.Escape, 'b')(get_by_name('backward-word')) - handle(Keys.Escape, 'c', filter=insert_mode)(get_by_name('capitalize-word')) - handle(Keys.Escape, 'd', filter=insert_mode)(get_by_name('kill-word')) - handle(Keys.Escape, 'f')(get_by_name('forward-word')) - handle(Keys.Escape, 'l', filter=insert_mode)(get_by_name('downcase-word')) - handle(Keys.Escape, 'u', filter=insert_mode)(get_by_name('uppercase-word')) + handle(Keys.ControlA)(get_by_name('beginning-of-line')) + handle(Keys.ControlB)(get_by_name('backward-char')) + handle(Keys.ControlDelete, filter=insert_mode)(get_by_name('kill-word')) + handle(Keys.ControlE)(get_by_name('end-of-line')) + handle(Keys.ControlF)(get_by_name('forward-char')) + handle(Keys.ControlLeft)(get_by_name('backward-word')) + handle(Keys.ControlRight)(get_by_name('forward-word')) + handle(Keys.ControlX, 'r', 'y', filter=insert_mode)(get_by_name('yank')) + handle(Keys.ControlY, filter=insert_mode)(get_by_name('yank')) + handle(Keys.Escape, 'b')(get_by_name('backward-word')) + handle(Keys.Escape, 'c', filter=insert_mode)(get_by_name('capitalize-word')) + handle(Keys.Escape, 'd', filter=insert_mode)(get_by_name('kill-word')) + handle(Keys.Escape, 'f')(get_by_name('forward-word')) + handle(Keys.Escape, 'l', filter=insert_mode)(get_by_name('downcase-word')) + handle(Keys.Escape, 'u', filter=insert_mode)(get_by_name('uppercase-word')) handle(Keys.Escape, 'y', filter=insert_mode)(get_by_name('yank-pop')) handle(Keys.Escape, Keys.ControlH, filter=insert_mode)(get_by_name('backward-kill-word')) handle(Keys.Escape, Keys.Backspace, filter=insert_mode)(get_by_name('backward-kill-word')) - handle(Keys.Escape, '\\', filter=insert_mode)(get_by_name('delete-horizontal-space')) + handle(Keys.Escape, '\\', filter=insert_mode)(get_by_name('delete-horizontal-space')) - handle(Keys.ControlUnderscore, save_before=(lambda e: False), filter=insert_mode)( - get_by_name('undo')) + handle(Keys.ControlUnderscore, save_before=(lambda e: False), filter=insert_mode)( + get_by_name('undo')) - handle(Keys.ControlX, Keys.ControlU, save_before=(lambda e: False), filter=insert_mode)( - get_by_name('undo')) + handle(Keys.ControlX, Keys.ControlU, save_before=(lambda e: False), filter=insert_mode)( + get_by_name('undo')) - handle(Keys.Escape, '<', filter= ~has_selection)(get_by_name('beginning-of-history')) - handle(Keys.Escape, '>', filter= ~has_selection)(get_by_name('end-of-history')) - - handle(Keys.Escape, '.', filter=insert_mode)(get_by_name('yank-last-arg')) - handle(Keys.Escape, '_', filter=insert_mode)(get_by_name('yank-last-arg')) - handle(Keys.Escape, Keys.ControlY, filter=insert_mode)(get_by_name('yank-nth-arg')) + handle(Keys.Escape, '<', filter= ~has_selection)(get_by_name('beginning-of-history')) + handle(Keys.Escape, '>', filter= ~has_selection)(get_by_name('end-of-history')) + + handle(Keys.Escape, '.', filter=insert_mode)(get_by_name('yank-last-arg')) + handle(Keys.Escape, '_', filter=insert_mode)(get_by_name('yank-last-arg')) + handle(Keys.Escape, Keys.ControlY, filter=insert_mode)(get_by_name('yank-nth-arg')) handle(Keys.Escape, '#', filter=insert_mode)(get_by_name('insert-comment')) handle(Keys.ControlO)(get_by_name('operate-and-get-next')) - + # ControlQ does a quoted insert. Not that for vt100 terminals, you have to # disable flow control by running ``stty -ixon``, otherwise Ctrl-Q and # Ctrl-S are captured by the terminal. @@ -87,22 +87,22 @@ def load_emacs_bindings(): handle(Keys.ControlX, ')')(get_by_name('end-kbd-macro')) handle(Keys.ControlX, 'e')(get_by_name('call-last-kbd-macro')) - @handle(Keys.ControlN) + @handle(Keys.ControlN) def _(event): - " Next line. " + " Next line. " event.current_buffer.auto_down() - @handle(Keys.ControlP) + @handle(Keys.ControlP) def _(event): - " Previous line. " + " Previous line. " event.current_buffer.auto_up(count=event.arg) def handle_digit(c): """ - Handle input of arguments. - The first number needs to be preceeded by escape. + Handle input of arguments. + The first number needs to be preceeded by escape. """ - @handle(c, filter=HasArg()) + @handle(c, filter=HasArg()) @handle(Keys.Escape, c) def _(event): event.append_to_arg_count(c) @@ -110,80 +110,80 @@ def load_emacs_bindings(): for c in '0123456789': handle_digit(c) - @handle(Keys.Escape, '-', filter=~HasArg()) + @handle(Keys.Escape, '-', filter=~HasArg()) def _(event): """ """ if event._arg is None: event.append_to_arg_count('-') - @handle('-', filter=Condition(lambda cli: cli.input_processor.arg == '-')) + @handle('-', filter=Condition(lambda cli: cli.input_processor.arg == '-')) def _(event): """ - When '-' is typed again, after exactly '-' has been given as an - argument, ignore this. + When '-' is typed again, after exactly '-' has been given as an + argument, ignore this. """ - event.cli.input_processor.arg = '-' + event.cli.input_processor.arg = '-' - is_returnable = Condition( - lambda cli: cli.current_buffer.accept_action.is_returnable) + is_returnable = Condition( + lambda cli: cli.current_buffer.accept_action.is_returnable) - # Meta + Newline: always accept input. - handle(Keys.Escape, Keys.ControlJ, filter=insert_mode & is_returnable)( - get_by_name('accept-line')) + # Meta + Newline: always accept input. + handle(Keys.Escape, Keys.ControlJ, filter=insert_mode & is_returnable)( + get_by_name('accept-line')) - def character_search(buff, char, count): - if count < 0: - match = buff.document.find_backwards(char, in_current_line=True, count=-count) - else: - match = buff.document.find(char, in_current_line=True, count=count) + def character_search(buff, char, count): + if count < 0: + match = buff.document.find_backwards(char, in_current_line=True, count=-count) + else: + match = buff.document.find(char, in_current_line=True, count=count) - if match is not None: - buff.cursor_position += match + if match is not None: + buff.cursor_position += match - @handle(Keys.ControlSquareClose, Keys.Any) + @handle(Keys.ControlSquareClose, Keys.Any) def _(event): - " When Ctl-] + a character is pressed. go to that character. " + " When Ctl-] + a character is pressed. go to that character. " # Also named 'character-search' - character_search(event.current_buffer, event.data, event.arg) + character_search(event.current_buffer, event.data, event.arg) - @handle(Keys.Escape, Keys.ControlSquareClose, Keys.Any) + @handle(Keys.Escape, Keys.ControlSquareClose, Keys.Any) def _(event): - " Like Ctl-], but backwards. " + " Like Ctl-], but backwards. " # Also named 'character-search-backward' - character_search(event.current_buffer, event.data, -event.arg) + character_search(event.current_buffer, event.data, -event.arg) - @handle(Keys.Escape, 'a') + @handle(Keys.Escape, 'a') def _(event): - " Previous sentence. " - # TODO: + " Previous sentence. " + # TODO: - @handle(Keys.Escape, 'e') + @handle(Keys.Escape, 'e') def _(event): - " Move to end of sentence. " + " Move to end of sentence. " # TODO: - @handle(Keys.Escape, 't', filter=insert_mode) + @handle(Keys.Escape, 't', filter=insert_mode) def _(event): """ Swap the last two words before the cursor. """ # TODO - @handle(Keys.Escape, '*', filter=insert_mode) + @handle(Keys.Escape, '*', filter=insert_mode) def _(event): """ - `meta-*`: Insert all possible completions of the preceding text. + `meta-*`: Insert all possible completions of the preceding text. """ - buff = event.current_buffer + buff = event.current_buffer - # List all completions. - complete_event = CompleteEvent(text_inserted=False, completion_requested=True) - completions = list(buff.completer.get_completions(buff.document, complete_event)) + # List all completions. + complete_event = CompleteEvent(text_inserted=False, completion_requested=True) + completions = list(buff.completer.get_completions(buff.document, complete_event)) - # Insert them. - text_to_insert = ' '.join(c.text for c in completions) - buff.insert_text(text_to_insert) + # Insert them. + text_to_insert = ' '.join(c.text for c in completions) + buff.insert_text(text_to_insert) @handle(Keys.ControlX, Keys.ControlX) def _(event): @@ -193,7 +193,7 @@ def load_emacs_bindings(): """ buffer = event.current_buffer - if buffer.document.is_cursor_at_the_end_of_line: + if buffer.document.is_cursor_at_the_end_of_line: buffer.cursor_position += buffer.document.get_start_of_line_position(after_whitespace=False) else: buffer.cursor_position += buffer.document.get_end_of_line_position() @@ -201,12 +201,12 @@ def load_emacs_bindings(): @handle(Keys.ControlSpace) def _(event): """ - Start of the selection (if the current buffer is not empty). + Start of the selection (if the current buffer is not empty). """ # Take the current cursor position as the start of this selection. - buff = event.current_buffer - if buff.text: - buff.start_selection(selection_type=SelectionType.CHARACTERS) + buff = event.current_buffer + if buff.text: + buff.start_selection(selection_type=SelectionType.CHARACTERS) @handle(Keys.ControlG, filter= ~has_selection) def _(event): @@ -257,7 +257,7 @@ def load_emacs_bindings(): buffer.cursor_position += buffer.document.find_next_word_beginning(count=event.arg) or \ buffer.document.get_end_of_document_position() - @handle(Keys.Escape, '/', filter=insert_mode) + @handle(Keys.Escape, '/', filter=insert_mode) def _(event): """ M-/: Complete. @@ -316,7 +316,7 @@ def load_emacs_system_bindings(): registry = ConditionalRegistry(Registry(), EmacsMode()) handle = registry.add_binding - has_focus = HasFocus(SYSTEM_BUFFER) + has_focus = HasFocus(SYSTEM_BUFFER) @handle(Keys.Escape, '!', filter= ~has_focus) def _(event): @@ -354,8 +354,8 @@ def load_emacs_search_bindings(get_search_state=None): registry = ConditionalRegistry(Registry(), EmacsMode()) handle = registry.add_binding - has_focus = HasFocus(SEARCH_BUFFER) - + has_focus = HasFocus(SEARCH_BUFFER) + assert get_search_state is None or callable(get_search_state) if not get_search_state: @@ -408,30 +408,30 @@ def load_emacs_search_bindings(get_search_state=None): get_search_state(event.cli).direction = IncrementalSearchDirection.FORWARD event.cli.push_focus(SEARCH_BUFFER) - def incremental_search(cli, direction, count=1): - " Apply search, but keep search buffer focussed. " + def incremental_search(cli, direction, count=1): + " Apply search, but keep search buffer focussed. " # Update search_state. - search_state = get_search_state(cli) - direction_changed = search_state.direction != direction + search_state = get_search_state(cli) + direction_changed = search_state.direction != direction - search_state.text = cli.buffers[SEARCH_BUFFER].text - search_state.direction = direction + search_state.text = cli.buffers[SEARCH_BUFFER].text + search_state.direction = direction # Apply search to current buffer. if not direction_changed: - input_buffer = cli.buffers.previous(cli) + input_buffer = cli.buffers.previous(cli) input_buffer.apply_search(search_state, - include_current_position=False, count=count) - - @handle(Keys.ControlR, filter=has_focus) - @handle(Keys.Up, filter=has_focus) - def _(event): - incremental_search(event.cli, IncrementalSearchDirection.BACKWARD, count=event.arg) + include_current_position=False, count=count) + @handle(Keys.ControlR, filter=has_focus) + @handle(Keys.Up, filter=has_focus) + def _(event): + incremental_search(event.cli, IncrementalSearchDirection.BACKWARD, count=event.arg) + @handle(Keys.ControlS, filter=has_focus) @handle(Keys.Down, filter=has_focus) def _(event): - incremental_search(event.cli, IncrementalSearchDirection.FORWARD, count=event.arg) + incremental_search(event.cli, IncrementalSearchDirection.FORWARD, count=event.arg) return registry diff --git a/contrib/python/prompt-toolkit/py2/prompt_toolkit/key_binding/bindings/named_commands.py b/contrib/python/prompt-toolkit/py2/prompt_toolkit/key_binding/bindings/named_commands.py index f80c439fc6..27c8eddc6b 100644 --- a/contrib/python/prompt-toolkit/py2/prompt_toolkit/key_binding/bindings/named_commands.py +++ b/contrib/python/prompt-toolkit/py2/prompt_toolkit/key_binding/bindings/named_commands.py @@ -1,272 +1,272 @@ -""" -Key bindings which are also known by GNU readline by the given names. - -See: http://www.delorie.com/gnu/docs/readline/rlman_13.html -""" -from __future__ import unicode_literals -from prompt_toolkit.enums import IncrementalSearchDirection, SEARCH_BUFFER +""" +Key bindings which are also known by GNU readline by the given names. + +See: http://www.delorie.com/gnu/docs/readline/rlman_13.html +""" +from __future__ import unicode_literals +from prompt_toolkit.enums import IncrementalSearchDirection, SEARCH_BUFFER from prompt_toolkit.selection import PasteMode -from six.moves import range -import six - +from six.moves import range +import six + from .completion import generate_completions, display_completions_like_readline from prompt_toolkit.document import Document from prompt_toolkit.enums import EditingMode from prompt_toolkit.key_binding.input_processor import KeyPress from prompt_toolkit.keys import Keys - -__all__ = ( - 'get_by_name', -) - - -# Registry that maps the Readline command names to their handlers. -_readline_commands = {} - -def register(name): - """ - Store handler in the `_readline_commands` dictionary. - """ - assert isinstance(name, six.text_type) - def decorator(handler): - assert callable(handler) - - _readline_commands[name] = handler - return handler - return decorator - - -def get_by_name(name): - """ - Return the handler for the (Readline) command with the given name. - """ - try: - return _readline_commands[name] - except KeyError: - raise KeyError('Unknown readline command: %r' % name) - -# -# Commands for moving -# See: http://www.delorie.com/gnu/docs/readline/rlman_14.html -# - -@register('beginning-of-line') -def beginning_of_line(event): - " Move to the start of the current line. " - buff = event.current_buffer - buff.cursor_position += buff.document.get_start_of_line_position(after_whitespace=False) - - -@register('end-of-line') -def end_of_line(event): - " Move to the end of the line. " - buff = event.current_buffer - buff.cursor_position += buff.document.get_end_of_line_position() - - -@register('forward-char') -def forward_char(event): - " Move forward a character. " - buff = event.current_buffer - buff.cursor_position += buff.document.get_cursor_right_position(count=event.arg) - - -@register('backward-char') -def backward_char(event): - " Move back a character. " - buff = event.current_buffer - buff.cursor_position += buff.document.get_cursor_left_position(count=event.arg) - - -@register('forward-word') -def forward_word(event): - """ - Move forward to the end of the next word. Words are composed of letters and - digits. - """ - buff = event.current_buffer - pos = buff.document.find_next_word_ending(count=event.arg) - - if pos: - buff.cursor_position += pos - - -@register('backward-word') -def backward_word(event): - """ - Move back to the start of the current or previous word. Words are composed - of letters and digits. - """ - buff = event.current_buffer - pos = buff.document.find_previous_word_beginning(count=event.arg) - - if pos: - buff.cursor_position += pos - - -@register('clear-screen') -def clear_screen(event): - """ - Clear the screen and redraw everything at the top of the screen. - """ - event.cli.renderer.clear() - - -@register('redraw-current-line') -def redraw_current_line(event): - """ - Refresh the current line. - (Readline defines this command, but prompt-toolkit doesn't have it.) - """ - pass - -# -# Commands for manipulating the history. -# See: http://www.delorie.com/gnu/docs/readline/rlman_15.html -# - -@register('accept-line') -def accept_line(event): - " Accept the line regardless of where the cursor is. " - b = event.current_buffer - b.accept_action.validate_and_handle(event.cli, b) - - -@register('previous-history') -def previous_history(event): + +__all__ = ( + 'get_by_name', +) + + +# Registry that maps the Readline command names to their handlers. +_readline_commands = {} + +def register(name): + """ + Store handler in the `_readline_commands` dictionary. + """ + assert isinstance(name, six.text_type) + def decorator(handler): + assert callable(handler) + + _readline_commands[name] = handler + return handler + return decorator + + +def get_by_name(name): + """ + Return the handler for the (Readline) command with the given name. + """ + try: + return _readline_commands[name] + except KeyError: + raise KeyError('Unknown readline command: %r' % name) + +# +# Commands for moving +# See: http://www.delorie.com/gnu/docs/readline/rlman_14.html +# + +@register('beginning-of-line') +def beginning_of_line(event): + " Move to the start of the current line. " + buff = event.current_buffer + buff.cursor_position += buff.document.get_start_of_line_position(after_whitespace=False) + + +@register('end-of-line') +def end_of_line(event): + " Move to the end of the line. " + buff = event.current_buffer + buff.cursor_position += buff.document.get_end_of_line_position() + + +@register('forward-char') +def forward_char(event): + " Move forward a character. " + buff = event.current_buffer + buff.cursor_position += buff.document.get_cursor_right_position(count=event.arg) + + +@register('backward-char') +def backward_char(event): + " Move back a character. " + buff = event.current_buffer + buff.cursor_position += buff.document.get_cursor_left_position(count=event.arg) + + +@register('forward-word') +def forward_word(event): + """ + Move forward to the end of the next word. Words are composed of letters and + digits. + """ + buff = event.current_buffer + pos = buff.document.find_next_word_ending(count=event.arg) + + if pos: + buff.cursor_position += pos + + +@register('backward-word') +def backward_word(event): + """ + Move back to the start of the current or previous word. Words are composed + of letters and digits. + """ + buff = event.current_buffer + pos = buff.document.find_previous_word_beginning(count=event.arg) + + if pos: + buff.cursor_position += pos + + +@register('clear-screen') +def clear_screen(event): + """ + Clear the screen and redraw everything at the top of the screen. + """ + event.cli.renderer.clear() + + +@register('redraw-current-line') +def redraw_current_line(event): + """ + Refresh the current line. + (Readline defines this command, but prompt-toolkit doesn't have it.) + """ + pass + +# +# Commands for manipulating the history. +# See: http://www.delorie.com/gnu/docs/readline/rlman_15.html +# + +@register('accept-line') +def accept_line(event): + " Accept the line regardless of where the cursor is. " + b = event.current_buffer + b.accept_action.validate_and_handle(event.cli, b) + + +@register('previous-history') +def previous_history(event): " Move `back` through the history list, fetching the previous command. " - event.current_buffer.history_backward(count=event.arg) - - -@register('next-history') -def next_history(event): + event.current_buffer.history_backward(count=event.arg) + + +@register('next-history') +def next_history(event): " Move `forward` through the history list, fetching the next command. " - event.current_buffer.history_forward(count=event.arg) - - -@register('beginning-of-history') -def beginning_of_history(event): - " Move to the first line in the history. " - event.current_buffer.go_to_history(0) - - -@register('end-of-history') -def end_of_history(event): - """ - Move to the end of the input history, i.e., the line currently being entered. - """ - event.current_buffer.history_forward(count=10**100) - buff = event.current_buffer - buff.go_to_history(len(buff._working_lines) - 1) - - -@register('reverse-search-history') -def reverse_search_history(event): - """ + event.current_buffer.history_forward(count=event.arg) + + +@register('beginning-of-history') +def beginning_of_history(event): + " Move to the first line in the history. " + event.current_buffer.go_to_history(0) + + +@register('end-of-history') +def end_of_history(event): + """ + Move to the end of the input history, i.e., the line currently being entered. + """ + event.current_buffer.history_forward(count=10**100) + buff = event.current_buffer + buff.go_to_history(len(buff._working_lines) - 1) + + +@register('reverse-search-history') +def reverse_search_history(event): + """ Search backward starting at the current line and moving `up` through - the history as necessary. This is an incremental search. - """ - event.cli.current_search_state.direction = IncrementalSearchDirection.BACKWARD - event.cli.push_focus(SEARCH_BUFFER) - - -# -# Commands for changing text -# - -@register('end-of-file') -def end_of_file(event): - """ - Exit. - """ - event.cli.exit() - - -@register('delete-char') -def delete_char(event): - " Delete character before the cursor. " - deleted = event.current_buffer.delete(count=event.arg) - if not deleted: - event.cli.output.bell() - - -@register('backward-delete-char') -def backward_delete_char(event): - " Delete the character behind the cursor. " - if event.arg < 0: - # When a negative argument has been given, this should delete in front - # of the cursor. - deleted = event.current_buffer.delete(count=-event.arg) - else: - deleted = event.current_buffer.delete_before_cursor(count=event.arg) - - if not deleted: - event.cli.output.bell() - - -@register('self-insert') -def self_insert(event): - " Insert yourself. " - event.current_buffer.insert_text(event.data * event.arg) - - -@register('transpose-chars') -def transpose_chars(event): - """ - Emulate Emacs transpose-char behavior: at the beginning of the buffer, - do nothing. At the end of a line or buffer, swap the characters before - the cursor. Otherwise, move the cursor right, and then swap the - characters before the cursor. - """ - b = event.current_buffer - p = b.cursor_position - if p == 0: - return - elif p == len(b.text) or b.text[p] == '\n': - b.swap_characters_before_cursor() - else: - b.cursor_position += b.document.get_cursor_right_position() - b.swap_characters_before_cursor() - - -@register('uppercase-word') -def uppercase_word(event): - """ - Uppercase the current (or following) word. - """ - buff = event.current_buffer - - for i in range(event.arg): - pos = buff.document.find_next_word_ending() - words = buff.document.text_after_cursor[:pos] - buff.insert_text(words.upper(), overwrite=True) - - -@register('downcase-word') -def downcase_word(event): - """ - Lowercase the current (or following) word. - """ - buff = event.current_buffer - - for i in range(event.arg): # XXX: not DRY: see meta_c and meta_u!! - pos = buff.document.find_next_word_ending() - words = buff.document.text_after_cursor[:pos] - buff.insert_text(words.lower(), overwrite=True) - - -@register('capitalize-word') -def capitalize_word(event): - """ - Capitalize the current (or following) word. - """ - buff = event.current_buffer - - for i in range(event.arg): - pos = buff.document.find_next_word_ending() - words = buff.document.text_after_cursor[:pos] - buff.insert_text(words.title(), overwrite=True) - + the history as necessary. This is an incremental search. + """ + event.cli.current_search_state.direction = IncrementalSearchDirection.BACKWARD + event.cli.push_focus(SEARCH_BUFFER) + + +# +# Commands for changing text +# + +@register('end-of-file') +def end_of_file(event): + """ + Exit. + """ + event.cli.exit() + + +@register('delete-char') +def delete_char(event): + " Delete character before the cursor. " + deleted = event.current_buffer.delete(count=event.arg) + if not deleted: + event.cli.output.bell() + + +@register('backward-delete-char') +def backward_delete_char(event): + " Delete the character behind the cursor. " + if event.arg < 0: + # When a negative argument has been given, this should delete in front + # of the cursor. + deleted = event.current_buffer.delete(count=-event.arg) + else: + deleted = event.current_buffer.delete_before_cursor(count=event.arg) + + if not deleted: + event.cli.output.bell() + + +@register('self-insert') +def self_insert(event): + " Insert yourself. " + event.current_buffer.insert_text(event.data * event.arg) + + +@register('transpose-chars') +def transpose_chars(event): + """ + Emulate Emacs transpose-char behavior: at the beginning of the buffer, + do nothing. At the end of a line or buffer, swap the characters before + the cursor. Otherwise, move the cursor right, and then swap the + characters before the cursor. + """ + b = event.current_buffer + p = b.cursor_position + if p == 0: + return + elif p == len(b.text) or b.text[p] == '\n': + b.swap_characters_before_cursor() + else: + b.cursor_position += b.document.get_cursor_right_position() + b.swap_characters_before_cursor() + + +@register('uppercase-word') +def uppercase_word(event): + """ + Uppercase the current (or following) word. + """ + buff = event.current_buffer + + for i in range(event.arg): + pos = buff.document.find_next_word_ending() + words = buff.document.text_after_cursor[:pos] + buff.insert_text(words.upper(), overwrite=True) + + +@register('downcase-word') +def downcase_word(event): + """ + Lowercase the current (or following) word. + """ + buff = event.current_buffer + + for i in range(event.arg): # XXX: not DRY: see meta_c and meta_u!! + pos = buff.document.find_next_word_ending() + words = buff.document.text_after_cursor[:pos] + buff.insert_text(words.lower(), overwrite=True) + + +@register('capitalize-word') +def capitalize_word(event): + """ + Capitalize the current (or following) word. + """ + buff = event.current_buffer + + for i in range(event.arg): + pos = buff.document.find_next_word_ending() + words = buff.document.text_after_cursor[:pos] + buff.insert_text(words.title(), overwrite=True) + @register('quoted-insert') def quoted_insert(event): @@ -277,73 +277,73 @@ def quoted_insert(event): event.cli.quoted_insert = True -# -# Killing and yanking. -# - -@register('kill-line') -def kill_line(event): - """ - Kill the text from the cursor to the end of the line. - - If we are at the end of the line, this should remove the newline. - (That way, it is possible to delete multiple lines by executing this - command multiple times.) - """ - buff = event.current_buffer - if event.arg < 0: - deleted = buff.delete_before_cursor(count=-buff.document.get_start_of_line_position()) - else: - if buff.document.current_char == '\n': - deleted = buff.delete(1) - else: - deleted = buff.delete(count=buff.document.get_end_of_line_position()) - event.cli.clipboard.set_text(deleted) - - -@register('kill-word') -def kill_word(event): - """ - Kill from point to the end of the current word, or if between words, to the - end of the next word. Word boundaries are the same as forward-word. - """ - buff = event.current_buffer - pos = buff.document.find_next_word_ending(count=event.arg) - - if pos: - deleted = buff.delete(count=pos) - event.cli.clipboard.set_text(deleted) - - -@register('unix-word-rubout') +# +# Killing and yanking. +# + +@register('kill-line') +def kill_line(event): + """ + Kill the text from the cursor to the end of the line. + + If we are at the end of the line, this should remove the newline. + (That way, it is possible to delete multiple lines by executing this + command multiple times.) + """ + buff = event.current_buffer + if event.arg < 0: + deleted = buff.delete_before_cursor(count=-buff.document.get_start_of_line_position()) + else: + if buff.document.current_char == '\n': + deleted = buff.delete(1) + else: + deleted = buff.delete(count=buff.document.get_end_of_line_position()) + event.cli.clipboard.set_text(deleted) + + +@register('kill-word') +def kill_word(event): + """ + Kill from point to the end of the current word, or if between words, to the + end of the next word. Word boundaries are the same as forward-word. + """ + buff = event.current_buffer + pos = buff.document.find_next_word_ending(count=event.arg) + + if pos: + deleted = buff.delete(count=pos) + event.cli.clipboard.set_text(deleted) + + +@register('unix-word-rubout') def unix_word_rubout(event, WORD=True): - """ + """ Kill the word behind point, using whitespace as a word boundary. Usually bound to ControlW. - """ - buff = event.current_buffer + """ + buff = event.current_buffer pos = buff.document.find_start_of_previous_word(count=event.arg, WORD=WORD) - - if pos is None: - # Nothing found? delete until the start of the document. (The - # input starts with whitespace and no words were found before the - # cursor.) - pos = - buff.cursor_position - - if pos: - deleted = buff.delete_before_cursor(count=-pos) - - # If the previous key press was also Control-W, concatenate deleted - # text. - if event.is_repeat: - deleted += event.cli.clipboard.get_data().text - - event.cli.clipboard.set_text(deleted) - else: - # Nothing to delete. Bell. - event.cli.output.bell() - - + + if pos is None: + # Nothing found? delete until the start of the document. (The + # input starts with whitespace and no words were found before the + # cursor.) + pos = - buff.cursor_position + + if pos: + deleted = buff.delete_before_cursor(count=-pos) + + # If the previous key press was also Control-W, concatenate deleted + # text. + if event.is_repeat: + deleted += event.cli.clipboard.get_data().text + + event.cli.clipboard.set_text(deleted) + else: + # Nothing to delete. Bell. + event.cli.output.bell() + + @register('backward-kill-word') def backward_kill_word(event): """ @@ -353,61 +353,61 @@ def backward_kill_word(event): unix_word_rubout(event, WORD=False) -@register('delete-horizontal-space') -def delete_horizontal_space(event): - " Delete all spaces and tabs around point. " - buff = event.current_buffer - text_before_cursor = buff.document.text_before_cursor - text_after_cursor = buff.document.text_after_cursor - - delete_before = len(text_before_cursor) - len(text_before_cursor.rstrip('\t ')) - delete_after = len(text_after_cursor) - len(text_after_cursor.lstrip('\t ')) - - buff.delete_before_cursor(count=delete_before) - buff.delete(count=delete_after) - - -@register('unix-line-discard') -def unix_line_discard(event): - """ - Kill backward from the cursor to the beginning of the current line. - """ - buff = event.current_buffer - - if buff.document.cursor_position_col == 0 and buff.document.cursor_position > 0: - buff.delete_before_cursor(count=1) - else: - deleted = buff.delete_before_cursor(count=-buff.document.get_start_of_line_position()) - event.cli.clipboard.set_text(deleted) - - -@register('yank') -def yank(event): - """ - Paste before cursor. - """ - event.current_buffer.paste_clipboard_data( +@register('delete-horizontal-space') +def delete_horizontal_space(event): + " Delete all spaces and tabs around point. " + buff = event.current_buffer + text_before_cursor = buff.document.text_before_cursor + text_after_cursor = buff.document.text_after_cursor + + delete_before = len(text_before_cursor) - len(text_before_cursor.rstrip('\t ')) + delete_after = len(text_after_cursor) - len(text_after_cursor.lstrip('\t ')) + + buff.delete_before_cursor(count=delete_before) + buff.delete(count=delete_after) + + +@register('unix-line-discard') +def unix_line_discard(event): + """ + Kill backward from the cursor to the beginning of the current line. + """ + buff = event.current_buffer + + if buff.document.cursor_position_col == 0 and buff.document.cursor_position > 0: + buff.delete_before_cursor(count=1) + else: + deleted = buff.delete_before_cursor(count=-buff.document.get_start_of_line_position()) + event.cli.clipboard.set_text(deleted) + + +@register('yank') +def yank(event): + """ + Paste before cursor. + """ + event.current_buffer.paste_clipboard_data( event.cli.clipboard.get_data(), count=event.arg, paste_mode=PasteMode.EMACS) - -@register('yank-nth-arg') -def yank_nth_arg(event): - """ - Insert the first argument of the previous command. With an argument, insert - the nth word from the previous command (start counting at 0). - """ - n = (event.arg if event.arg_present else None) - event.current_buffer.yank_nth_arg(n) - - -@register('yank-last-arg') -def yank_last_arg(event): - """ - Like `yank_nth_arg`, but if no argument has been given, yank the last word - of each line. - """ - n = (event.arg if event.arg_present else None) - event.current_buffer.yank_last_arg(n) - + +@register('yank-nth-arg') +def yank_nth_arg(event): + """ + Insert the first argument of the previous command. With an argument, insert + the nth word from the previous command (start counting at 0). + """ + n = (event.arg if event.arg_present else None) + event.current_buffer.yank_nth_arg(n) + + +@register('yank-last-arg') +def yank_last_arg(event): + """ + Like `yank_nth_arg`, but if no argument has been given, yank the last word + of each line. + """ + n = (event.arg if event.arg_present else None) + event.current_buffer.yank_last_arg(n) + @register('yank-pop') def yank_pop(event): """ @@ -424,12 +424,12 @@ def yank_pop(event): buff.paste_clipboard_data( clipboard.get_data(), paste_mode=PasteMode.EMACS) -# -# Completion. -# - -@register('complete') -def complete(event): +# +# Completion. +# + +@register('complete') +def complete(event): " Attempt to perform completion. " display_completions_like_readline(event) @@ -440,15 +440,15 @@ def menu_complete(event): Generate completions, or go to the next completion. (This is the default way of completing input in prompt_toolkit.) """ - generate_completions(event) - - + generate_completions(event) + + @register('menu-complete-backward') def menu_complete_backward(event): " Move backward through the list of possible completions. " event.current_buffer.complete_previous() -# +# # Keyboard macros. # @@ -488,13 +488,13 @@ def print_last_kbd_macro(event): event.cli.run_in_terminal(print_macro) # -# Miscellaneous Commands. -# - -@register('undo') -def undo(event): - " Incremental undo. " - event.current_buffer.undo() +# Miscellaneous Commands. +# + +@register('undo') +def undo(event): + " Incremental undo. " + event.current_buffer.undo() @register('insert-comment') diff --git a/contrib/python/prompt-toolkit/py2/prompt_toolkit/key_binding/bindings/scroll.py b/contrib/python/prompt-toolkit/py2/prompt_toolkit/key_binding/bindings/scroll.py index 2cc58129ff..91750b3c31 100644 --- a/contrib/python/prompt-toolkit/py2/prompt_toolkit/key_binding/bindings/scroll.py +++ b/contrib/python/prompt-toolkit/py2/prompt_toolkit/key_binding/bindings/scroll.py @@ -8,7 +8,7 @@ Vi, Emacs, etc... from __future__ import unicode_literals from prompt_toolkit.layout.utils import find_window_for_buffer_name -from six.moves import range +from six.moves import range __all__ = ( 'scroll_forward', @@ -35,29 +35,29 @@ def scroll_forward(event, half=False): b = event.cli.current_buffer if w and w.render_info: - info = w.render_info - ui_content = info.ui_content - - # Height to scroll. - scroll_height = info.window_height + info = w.render_info + ui_content = info.ui_content + + # Height to scroll. + scroll_height = info.window_height if half: - scroll_height //= 2 - - # Calculate how many lines is equivalent to that vertical space. - y = b.document.cursor_position_row + 1 - height = 0 - while y < ui_content.line_count: - line_height = info.get_height_for_line(y) - - if height + line_height < scroll_height: - height += line_height - y += 1 - else: - break - - b.cursor_position = b.document.translate_row_col_to_index(y, 0) - - + scroll_height //= 2 + + # Calculate how many lines is equivalent to that vertical space. + y = b.document.cursor_position_row + 1 + height = 0 + while y < ui_content.line_count: + line_height = info.get_height_for_line(y) + + if height + line_height < scroll_height: + height += line_height + y += 1 + else: + break + + b.cursor_position = b.document.translate_row_col_to_index(y, 0) + + def scroll_backward(event, half=False): """ Scroll window up. @@ -66,28 +66,28 @@ def scroll_backward(event, half=False): b = event.cli.current_buffer if w and w.render_info: - info = w.render_info - - # Height to scroll. - scroll_height = info.window_height + info = w.render_info + + # Height to scroll. + scroll_height = info.window_height if half: - scroll_height //= 2 - - # Calculate how many lines is equivalent to that vertical space. - y = max(0, b.document.cursor_position_row - 1) - height = 0 - while y > 0: - line_height = info.get_height_for_line(y) - - if height + line_height < scroll_height: - height += line_height - y -= 1 - else: - break - - b.cursor_position = b.document.translate_row_col_to_index(y, 0) - - + scroll_height //= 2 + + # Calculate how many lines is equivalent to that vertical space. + y = max(0, b.document.cursor_position_row - 1) + height = 0 + while y > 0: + line_height = info.get_height_for_line(y) + + if height + line_height < scroll_height: + height += line_height + y -= 1 + else: + break + + b.cursor_position = b.document.translate_row_col_to_index(y, 0) + + def scroll_half_page_down(event): """ Same as ControlF, but only scroll half a page. @@ -134,14 +134,14 @@ def scroll_one_line_up(event): info = w.render_info if w.vertical_scroll > 0: - first_line_height = info.get_height_for_line(info.first_visible_line()) - - cursor_up = info.cursor_position.y - (info.window_height - 1 - first_line_height - - info.configured_scroll_offsets.bottom) - - # Move cursor up, as many steps as the height of the first line. - # TODO: not entirely correct yet, in case of line wrapping and many long lines. - for _ in range(max(0, cursor_up)): + first_line_height = info.get_height_for_line(info.first_visible_line()) + + cursor_up = info.cursor_position.y - (info.window_height - 1 - first_line_height - + info.configured_scroll_offsets.bottom) + + # Move cursor up, as many steps as the height of the first line. + # TODO: not entirely correct yet, in case of line wrapping and many long lines. + for _ in range(max(0, cursor_up)): b.cursor_position += b.document.get_cursor_up_position() # Scroll window @@ -157,10 +157,10 @@ def scroll_page_down(event): if w and w.render_info: # Scroll down one page. - line_index = max(w.render_info.last_visible_line(), w.vertical_scroll + 1) - w.vertical_scroll = line_index + line_index = max(w.render_info.last_visible_line(), w.vertical_scroll + 1) + w.vertical_scroll = line_index - b.cursor_position = b.document.translate_row_col_to_index(line_index, 0) + b.cursor_position = b.document.translate_row_col_to_index(line_index, 0) b.cursor_position += b.document.get_start_of_line_position(after_whitespace=True) @@ -172,14 +172,14 @@ def scroll_page_up(event): b = event.cli.current_buffer if w and w.render_info: - # Put cursor at the first visible line. (But make sure that the cursor - # moves at least one line up.) - line_index = max(0, min(w.render_info.first_visible_line(), - b.document.cursor_position_row - 1)) + # Put cursor at the first visible line. (But make sure that the cursor + # moves at least one line up.) + line_index = max(0, min(w.render_info.first_visible_line(), + b.document.cursor_position_row - 1)) - b.cursor_position = b.document.translate_row_col_to_index(line_index, 0) - b.cursor_position += b.document.get_start_of_line_position(after_whitespace=True) + b.cursor_position = b.document.translate_row_col_to_index(line_index, 0) + b.cursor_position += b.document.get_start_of_line_position(after_whitespace=True) - # Set the scroll offset. We can safely set it to zero; the Window will - # make sure that it scrolls at least until the cursor becomes visible. - w.vertical_scroll = 0 + # Set the scroll offset. We can safely set it to zero; the Window will + # make sure that it scrolls at least until the cursor becomes visible. + w.vertical_scroll = 0 diff --git a/contrib/python/prompt-toolkit/py2/prompt_toolkit/key_binding/bindings/utils.py b/contrib/python/prompt-toolkit/py2/prompt_toolkit/key_binding/bindings/utils.py index caf08c5c1b..b3fa299d7c 100644 --- a/contrib/python/prompt-toolkit/py2/prompt_toolkit/key_binding/bindings/utils.py +++ b/contrib/python/prompt-toolkit/py2/prompt_toolkit/key_binding/bindings/utils.py @@ -7,10 +7,10 @@ __all__ = ( def create_handle_decorator(registry, filter=Always()): """ - Create a key handle decorator, which is compatible with `Registry.handle`, - but will chain the given filter to every key binding. + Create a key handle decorator, which is compatible with `Registry.handle`, + but will chain the given filter to every key binding. - :param filter: `CLIFilter` + :param filter: `CLIFilter` """ assert isinstance(filter, CLIFilter) @@ -21,5 +21,5 @@ def create_handle_decorator(registry, filter=Always()): else: kw['filter'] = filter - return registry.add_binding(*keys, **kw) + return registry.add_binding(*keys, **kw) return handle diff --git a/contrib/python/prompt-toolkit/py2/prompt_toolkit/key_binding/bindings/vi.py b/contrib/python/prompt-toolkit/py2/prompt_toolkit/key_binding/bindings/vi.py index 72568ee273..4615329eec 100644 --- a/contrib/python/prompt-toolkit/py2/prompt_toolkit/key_binding/bindings/vi.py +++ b/contrib/python/prompt-toolkit/py2/prompt_toolkit/key_binding/bindings/vi.py @@ -1,11 +1,11 @@ # pylint: disable=function-redefined from __future__ import unicode_literals -from prompt_toolkit.buffer import ClipboardData, indent, unindent, reshape_text +from prompt_toolkit.buffer import ClipboardData, indent, unindent, reshape_text from prompt_toolkit.document import Document from prompt_toolkit.enums import IncrementalSearchDirection, SEARCH_BUFFER, SYSTEM_BUFFER from prompt_toolkit.filters import Filter, Condition, HasArg, Always, IsReadOnly -from prompt_toolkit.filters.cli import ViNavigationMode, ViInsertMode, ViInsertMultipleMode, ViReplaceMode, ViSelectionMode, ViWaitingForTextObjectMode, ViDigraphMode, ViMode -from prompt_toolkit.key_binding.digraphs import DIGRAPHS +from prompt_toolkit.filters.cli import ViNavigationMode, ViInsertMode, ViInsertMultipleMode, ViReplaceMode, ViSelectionMode, ViWaitingForTextObjectMode, ViDigraphMode, ViMode +from prompt_toolkit.key_binding.digraphs import DIGRAPHS from prompt_toolkit.key_binding.vi_state import CharacterFind, InputMode from prompt_toolkit.keys import Keys from prompt_toolkit.layout.utils import find_window_for_buffer_name @@ -16,21 +16,21 @@ from .named_commands import get_by_name from ..registry import Registry, ConditionalRegistry, BaseRegistry import prompt_toolkit.filters as filters -from six.moves import range +from six.moves import range import codecs -import six -import string - -try: - from itertools import accumulate -except ImportError: # < Python 3.2 - def accumulate(iterable): - " Super simpel 'accumulate' implementation. " - total = 0 - for item in iterable: - total += item - yield total - +import six +import string + +try: + from itertools import accumulate +except ImportError: # < Python 3.2 + def accumulate(iterable): + " Super simpel 'accumulate' implementation. " + total = 0 + for item in iterable: + total += item + yield total + __all__ = ( 'load_vi_bindings', 'load_vi_search_bindings', @@ -38,40 +38,40 @@ __all__ = ( 'load_extra_vi_page_navigation_bindings', ) -if six.PY2: - ascii_lowercase = string.ascii_lowercase.decode('ascii') -else: - ascii_lowercase = string.ascii_lowercase +if six.PY2: + ascii_lowercase = string.ascii_lowercase.decode('ascii') +else: + ascii_lowercase = string.ascii_lowercase -vi_register_names = ascii_lowercase + '0123456789' +vi_register_names = ascii_lowercase + '0123456789' -class TextObjectType(object): - EXCLUSIVE = 'EXCLUSIVE' - INCLUSIVE = 'INCLUSIVE' - LINEWISE = 'LINEWISE' - BLOCK = 'BLOCK' +class TextObjectType(object): + EXCLUSIVE = 'EXCLUSIVE' + INCLUSIVE = 'INCLUSIVE' + LINEWISE = 'LINEWISE' + BLOCK = 'BLOCK' -class TextObject(object): +class TextObject(object): """ - Return struct for functions wrapped in ``text_object``. + Return struct for functions wrapped in ``text_object``. Both `start` and `end` are relative to the current cursor position. """ - def __init__(self, start, end=0, type=TextObjectType.EXCLUSIVE): + def __init__(self, start, end=0, type=TextObjectType.EXCLUSIVE): self.start = start self.end = end - self.type = type - - @property - def selection_type(self): - if self.type == TextObjectType.LINEWISE: - return SelectionType.LINES - if self.type == TextObjectType.BLOCK: - return SelectionType.BLOCK - else: - return SelectionType.CHARACTERS - + self.type = type + + @property + def selection_type(self): + if self.type == TextObjectType.LINEWISE: + return SelectionType.LINES + if self.type == TextObjectType.BLOCK: + return SelectionType.BLOCK + else: + return SelectionType.CHARACTERS + def sorted(self): """ Return a (start, end) tuple where start <= end. @@ -81,62 +81,62 @@ class TextObject(object): else: return self.end, self.start - def operator_range(self, document): - """ - Return a (start, end) tuple with start <= end that indicates the range - operators should operate on. - `buffer` is used to get start and end of line positions. - """ - start, end = self.sorted() - doc = document - - if (self.type == TextObjectType.EXCLUSIVE and - doc.translate_index_to_position(end + doc.cursor_position)[1] == 0): - # If the motion is exclusive and the end of motion is on the first - # column, the end position becomes end of previous line. - end -= 1 - if self.type == TextObjectType.INCLUSIVE: - end += 1 - if self.type == TextObjectType.LINEWISE: - # Select whole lines - row, col = doc.translate_index_to_position(start + doc.cursor_position) - start = doc.translate_row_col_to_index(row, 0) - doc.cursor_position - row, col = doc.translate_index_to_position(end + doc.cursor_position) - end = doc.translate_row_col_to_index(row, len(doc.lines[row])) - doc.cursor_position - return start, end - - def get_line_numbers(self, buffer): - """ - Return a (start_line, end_line) pair. - """ - # Get absolute cursor positions from the text object. - from_, to = self.operator_range(buffer.document) - from_ += buffer.cursor_position - to += buffer.cursor_position - - # Take the start of the lines. - from_, _ = buffer.document.translate_index_to_position(from_) - to, _ = buffer.document.translate_index_to_position(to) - - return from_, to - - def cut(self, buffer): - """ - Turn text object into `ClipboardData` instance. - """ - from_, to = self.operator_range(buffer.document) - - from_ += buffer.cursor_position - to += buffer.cursor_position - to -= 1 # SelectionState does not include the end position, `operator_range` does. - - document = Document(buffer.text, to, SelectionState( - original_cursor_position=from_, type=self.selection_type)) - - new_document, clipboard_data = document.cut_selection() - return new_document, clipboard_data - - + def operator_range(self, document): + """ + Return a (start, end) tuple with start <= end that indicates the range + operators should operate on. + `buffer` is used to get start and end of line positions. + """ + start, end = self.sorted() + doc = document + + if (self.type == TextObjectType.EXCLUSIVE and + doc.translate_index_to_position(end + doc.cursor_position)[1] == 0): + # If the motion is exclusive and the end of motion is on the first + # column, the end position becomes end of previous line. + end -= 1 + if self.type == TextObjectType.INCLUSIVE: + end += 1 + if self.type == TextObjectType.LINEWISE: + # Select whole lines + row, col = doc.translate_index_to_position(start + doc.cursor_position) + start = doc.translate_row_col_to_index(row, 0) - doc.cursor_position + row, col = doc.translate_index_to_position(end + doc.cursor_position) + end = doc.translate_row_col_to_index(row, len(doc.lines[row])) - doc.cursor_position + return start, end + + def get_line_numbers(self, buffer): + """ + Return a (start_line, end_line) pair. + """ + # Get absolute cursor positions from the text object. + from_, to = self.operator_range(buffer.document) + from_ += buffer.cursor_position + to += buffer.cursor_position + + # Take the start of the lines. + from_, _ = buffer.document.translate_index_to_position(from_) + to, _ = buffer.document.translate_index_to_position(to) + + return from_, to + + def cut(self, buffer): + """ + Turn text object into `ClipboardData` instance. + """ + from_, to = self.operator_range(buffer.document) + + from_ += buffer.cursor_position + to += buffer.cursor_position + to -= 1 # SelectionState does not include the end position, `operator_range` does. + + document = Document(buffer.text, to, SelectionState( + original_cursor_position=from_, type=self.selection_type)) + + new_document, clipboard_data = document.cut_selection() + return new_document, clipboard_data + + def create_text_object_decorator(registry): """ Create a decorator that can be used to register Vi text object implementations. @@ -304,8 +304,8 @@ def load_vi_bindings(get_search_state=None): # Overview of Readline Vi commands: # http://www.catonmat.net/download/bash-vi-editing-mode-cheat-sheet.pdf - :param get_search_state: None or a callable that takes a - CommandLineInterface and returns a SearchState. + :param get_search_state: None or a callable that takes a + CommandLineInterface and returns a SearchState. """ # Note: Some key bindings have the "~IsReadOnly()" filter added. This # prevents the handler to be executed when the focus is on a @@ -323,29 +323,29 @@ def load_vi_bindings(get_search_state=None): if get_search_state is None: def get_search_state(cli): return cli.search_state - # (Note: Always take the navigation bindings in read-only mode, even when - # ViState says different.) - navigation_mode = ViNavigationMode() - insert_mode = ViInsertMode() - insert_multiple_mode = ViInsertMultipleMode() - replace_mode = ViReplaceMode() - selection_mode = ViSelectionMode() - operator_given = ViWaitingForTextObjectMode() - digraph_mode = ViDigraphMode() + # (Note: Always take the navigation bindings in read-only mode, even when + # ViState says different.) + navigation_mode = ViNavigationMode() + insert_mode = ViInsertMode() + insert_multiple_mode = ViInsertMultipleMode() + replace_mode = ViReplaceMode() + selection_mode = ViSelectionMode() + operator_given = ViWaitingForTextObjectMode() + digraph_mode = ViDigraphMode() vi_transform_functions = [ # Rot 13 transformation - (('g', '?'), Always(), lambda string: codecs.encode(string, 'rot_13')), + (('g', '?'), Always(), lambda string: codecs.encode(string, 'rot_13')), # To lowercase - (('g', 'u'), Always(), lambda string: string.lower()), + (('g', 'u'), Always(), lambda string: string.lower()), # To uppercase. - (('g', 'U'), Always(), lambda string: string.upper()), + (('g', 'U'), Always(), lambda string: string.upper()), # Swap case. - (('g', '~'), Always(), lambda string: string.swapcase()), - (('~', ), Condition(lambda cli: cli.vi_state.tilde_operator), lambda string: string.swapcase()), + (('g', '~'), Always(), lambda string: string.swapcase()), + (('~', ), Condition(lambda cli: cli.vi_state.tilde_operator), lambda string: string.swapcase()), ] # Insert a character literally (quoted insert). @@ -357,12 +357,12 @@ def load_vi_bindings(get_search_state=None): Escape goes to vi navigation mode. """ buffer = event.current_buffer - vi_state = event.cli.vi_state + vi_state = event.cli.vi_state if vi_state.input_mode in (InputMode.INSERT, InputMode.REPLACE): buffer.cursor_position += buffer.document.get_cursor_left_position() - vi_state.reset(InputMode.NAVIGATION) + vi_state.reset(InputMode.NAVIGATION) if bool(buffer.selection_state): buffer.exit_selection() @@ -387,34 +387,34 @@ def load_vi_bindings(get_search_state=None): """ Arrow up and ControlP in navigation mode go up. """ - event.current_buffer.auto_up(count=event.arg) - - @handle('k', filter=navigation_mode) - def _(event): - """ - Go up, but if we enter a new history entry, move to the start of the - line. - """ - event.current_buffer.auto_up( - count=event.arg, go_to_start_of_line_if_history_changes=True) - + event.current_buffer.auto_up(count=event.arg) + + @handle('k', filter=navigation_mode) + def _(event): + """ + Go up, but if we enter a new history entry, move to the start of the + line. + """ + event.current_buffer.auto_up( + count=event.arg, go_to_start_of_line_if_history_changes=True) + @handle(Keys.Down, filter=navigation_mode) @handle(Keys.ControlN, filter=navigation_mode) def _(event): """ Arrow down and Control-N in navigation mode. """ - event.current_buffer.auto_down(count=event.arg) - - @handle('j', filter=navigation_mode) - def _(event): - """ - Go down, but if we enter a new history entry, go to the start of the line. - """ - event.current_buffer.auto_down( - count=event.arg, go_to_start_of_line_if_history_changes=True) - - @handle(Keys.ControlH, filter=navigation_mode) + event.current_buffer.auto_down(count=event.arg) + + @handle('j', filter=navigation_mode) + def _(event): + """ + Go down, but if we enter a new history entry, go to the start of the line. + """ + event.current_buffer.auto_down( + count=event.arg, go_to_start_of_line_if_history_changes=True) + + @handle(Keys.ControlH, filter=navigation_mode) @handle(Keys.Backspace, filter=navigation_mode) def _(event): """ @@ -458,7 +458,7 @@ def load_vi_bindings(get_search_state=None): """ event.current_buffer.cancel_completion() - @handle(Keys.ControlJ, filter=navigation_mode) # XXX: only if the selected buffer has a return handler. + @handle(Keys.ControlJ, filter=navigation_mode) # XXX: only if the selected buffer has a return handler. def _(event): """ In navigation mode, pressing enter will always return the input. @@ -475,19 +475,19 @@ def load_vi_bindings(get_search_state=None): @handle(Keys.Insert, filter=navigation_mode) def _(event): " Presing the Insert key. " - event.cli.vi_state.input_mode = InputMode.INSERT + event.cli.vi_state.input_mode = InputMode.INSERT @handle('a', filter=navigation_mode & ~IsReadOnly()) # ~IsReadOnly, because we want to stay in navigation mode for # read-only buffers. def _(event): event.current_buffer.cursor_position += event.current_buffer.document.get_cursor_right_position() - event.cli.vi_state.input_mode = InputMode.INSERT + event.cli.vi_state.input_mode = InputMode.INSERT @handle('A', filter=navigation_mode & ~IsReadOnly()) def _(event): event.current_buffer.cursor_position += event.current_buffer.document.get_end_of_line_position() - event.cli.vi_state.input_mode = InputMode.INSERT + event.cli.vi_state.input_mode = InputMode.INSERT @handle('C', filter=navigation_mode & ~IsReadOnly()) def _(event): @@ -499,7 +499,7 @@ def load_vi_bindings(get_search_state=None): deleted = buffer.delete(count=buffer.document.get_end_of_line_position()) event.cli.clipboard.set_text(deleted) - event.cli.vi_state.input_mode = InputMode.INSERT + event.cli.vi_state.input_mode = InputMode.INSERT @handle('c', 'c', filter=navigation_mode & ~IsReadOnly()) @handle('S', filter=navigation_mode & ~IsReadOnly()) @@ -516,7 +516,7 @@ def load_vi_bindings(get_search_state=None): # But we delete after the whitespace buffer.cursor_position += buffer.document.get_start_of_line_position(after_whitespace=True) buffer.delete(count=buffer.document.get_end_of_line_position()) - event.cli.vi_state.input_mode = InputMode.INSERT + event.cli.vi_state.input_mode = InputMode.INSERT @handle('D', filter=navigation_mode) def _(event): @@ -535,8 +535,8 @@ def load_vi_bindings(get_search_state=None): lines = buffer.document.lines before = '\n'.join(lines[:buffer.document.cursor_position_row]) - deleted = '\n'.join(lines[buffer.document.cursor_position_row: - buffer.document.cursor_position_row + event.arg]) + deleted = '\n'.join(lines[buffer.document.cursor_position_row: + buffer.document.cursor_position_row + event.arg]) after = '\n'.join(lines[buffer.document.cursor_position_row + event.arg:]) # Set new text. @@ -552,81 +552,81 @@ def load_vi_bindings(get_search_state=None): # Set clipboard data event.cli.clipboard.set_data(ClipboardData(deleted, SelectionType.LINES)) - @handle('x', filter=selection_mode) - def _(event): - """ - Cut selection. - ('x' is not an operator.) - """ - clipboard_data = event.current_buffer.cut_selection() - event.cli.clipboard.set_data(clipboard_data) - + @handle('x', filter=selection_mode) + def _(event): + """ + Cut selection. + ('x' is not an operator.) + """ + clipboard_data = event.current_buffer.cut_selection() + event.cli.clipboard.set_data(clipboard_data) + @handle('i', filter=navigation_mode & ~IsReadOnly()) def _(event): - event.cli.vi_state.input_mode = InputMode.INSERT + event.cli.vi_state.input_mode = InputMode.INSERT @handle('I', filter=navigation_mode & ~IsReadOnly()) def _(event): - event.cli.vi_state.input_mode = InputMode.INSERT - event.current_buffer.cursor_position += \ - event.current_buffer.document.get_start_of_line_position(after_whitespace=True) - - @Condition - def in_block_selection(cli): - buff = cli.current_buffer - return buff.selection_state and buff.selection_state.type == SelectionType.BLOCK - - @handle('I', filter=in_block_selection & ~IsReadOnly()) - def go_to_block_selection(event, after=False): - " Insert in block selection mode. " - buff = event.current_buffer - - # Store all cursor positions. - positions = [] - - if after: - def get_pos(from_to): - return from_to[1] + 1 - else: - def get_pos(from_to): - return from_to[0] - - for i, from_to in enumerate(buff.document.selection_ranges()): - positions.append(get_pos(from_to)) - if i == 0: - buff.cursor_position = get_pos(from_to) - - buff.multiple_cursor_positions = positions - - # Go to 'INSERT_MULTIPLE' mode. - event.cli.vi_state.input_mode = InputMode.INSERT_MULTIPLE - buff.exit_selection() - - @handle('A', filter=in_block_selection & ~IsReadOnly()) - def _(event): - go_to_block_selection(event, after=True) - - @handle('J', filter=navigation_mode & ~IsReadOnly()) - def _(event): - " Join lines. " + event.cli.vi_state.input_mode = InputMode.INSERT + event.current_buffer.cursor_position += \ + event.current_buffer.document.get_start_of_line_position(after_whitespace=True) + + @Condition + def in_block_selection(cli): + buff = cli.current_buffer + return buff.selection_state and buff.selection_state.type == SelectionType.BLOCK + + @handle('I', filter=in_block_selection & ~IsReadOnly()) + def go_to_block_selection(event, after=False): + " Insert in block selection mode. " + buff = event.current_buffer + + # Store all cursor positions. + positions = [] + + if after: + def get_pos(from_to): + return from_to[1] + 1 + else: + def get_pos(from_to): + return from_to[0] + + for i, from_to in enumerate(buff.document.selection_ranges()): + positions.append(get_pos(from_to)) + if i == 0: + buff.cursor_position = get_pos(from_to) + + buff.multiple_cursor_positions = positions + + # Go to 'INSERT_MULTIPLE' mode. + event.cli.vi_state.input_mode = InputMode.INSERT_MULTIPLE + buff.exit_selection() + + @handle('A', filter=in_block_selection & ~IsReadOnly()) + def _(event): + go_to_block_selection(event, after=True) + + @handle('J', filter=navigation_mode & ~IsReadOnly()) + def _(event): + " Join lines. " for i in range(event.arg): event.current_buffer.join_next_line() - @handle('g', 'J', filter=navigation_mode & ~IsReadOnly()) + @handle('g', 'J', filter=navigation_mode & ~IsReadOnly()) def _(event): - " Join lines without space. " - for i in range(event.arg): - event.current_buffer.join_next_line(separator='') - - @handle('J', filter=selection_mode & ~IsReadOnly()) - def _(event): - " Join selected lines. " + " Join lines without space. " + for i in range(event.arg): + event.current_buffer.join_next_line(separator='') + + @handle('J', filter=selection_mode & ~IsReadOnly()) + def _(event): + " Join selected lines. " event.current_buffer.join_selected_lines() - @handle('g', 'J', filter=selection_mode & ~IsReadOnly()) - def _(event): - " Join selected lines without space. " - event.current_buffer.join_selected_lines(separator='') + @handle('g', 'J', filter=selection_mode & ~IsReadOnly()) + def _(event): + " Join selected lines without space. " + event.current_buffer.join_selected_lines(separator='') @handle('p', filter=navigation_mode) def _(event): @@ -648,26 +648,26 @@ def load_vi_bindings(get_search_state=None): count=event.arg, paste_mode=PasteMode.VI_BEFORE) - @handle('"', Keys.Any, 'p', filter=navigation_mode) - def _(event): - " Paste from named register. " - c = event.key_sequence[1].data - if c in vi_register_names: - data = event.cli.vi_state.named_registers.get(c) - if data: + @handle('"', Keys.Any, 'p', filter=navigation_mode) + def _(event): + " Paste from named register. " + c = event.key_sequence[1].data + if c in vi_register_names: + data = event.cli.vi_state.named_registers.get(c) + if data: event.current_buffer.paste_clipboard_data( data, count=event.arg, paste_mode=PasteMode.VI_AFTER) - - @handle('"', Keys.Any, 'P', filter=navigation_mode) - def _(event): - " Paste (before) from named register. " - c = event.key_sequence[1].data - if c in vi_register_names: - data = event.cli.vi_state.named_registers.get(c) - if data: - event.current_buffer.paste_clipboard_data( + + @handle('"', Keys.Any, 'P', filter=navigation_mode) + def _(event): + " Paste (before) from named register. " + c = event.key_sequence[1].data + if c in vi_register_names: + data = event.cli.vi_state.named_registers.get(c) + if data: + event.current_buffer.paste_clipboard_data( data, count=event.arg, paste_mode=PasteMode.VI_BEFORE) - + @handle('r', Keys.Any, filter=navigation_mode) def _(event): """ @@ -681,7 +681,7 @@ def load_vi_bindings(get_search_state=None): """ Go to 'replace'-mode. """ - event.cli.vi_state.input_mode = InputMode.REPLACE + event.cli.vi_state.input_mode = InputMode.REPLACE @handle('s', filter=navigation_mode & ~IsReadOnly()) def _(event): @@ -691,7 +691,7 @@ def load_vi_bindings(get_search_state=None): """ text = event.current_buffer.delete(count=event.arg) event.cli.clipboard.set_text(text) - event.cli.vi_state.input_mode = InputMode.INSERT + event.cli.vi_state.input_mode = InputMode.INSERT @handle('u', filter=navigation_mode, save_before=(lambda e: False)) def _(event): @@ -830,7 +830,7 @@ def load_vi_bindings(get_search_state=None): """ event.current_buffer.insert_line_above( copy_margin=not event.cli.in_paste_mode) - event.cli.vi_state.input_mode = InputMode.INSERT + event.cli.vi_state.input_mode = InputMode.INSERT @handle('o', filter=navigation_mode & ~IsReadOnly()) def _(event): @@ -839,7 +839,7 @@ def load_vi_bindings(get_search_state=None): """ event.current_buffer.insert_line_below( copy_margin=not event.cli.in_paste_mode) - event.cli.vi_state.input_mode = InputMode.INSERT + event.cli.vi_state.input_mode = InputMode.INSERT @handle('~', filter=navigation_mode) def _(event): @@ -850,26 +850,26 @@ def load_vi_bindings(get_search_state=None): c = buffer.document.current_char if c is not None and c != '\n': - buffer.insert_text(c.swapcase(), overwrite=True) - - @handle('g', 'u', 'u', filter=navigation_mode & ~IsReadOnly()) - def _(event): - " Lowercase current line. " - buff = event.current_buffer - buff.transform_current_line(lambda s: s.lower()) - - @handle('g', 'U', 'U', filter=navigation_mode & ~IsReadOnly()) - def _(event): - " Uppercase current line. " - buff = event.current_buffer - buff.transform_current_line(lambda s: s.upper()) - - @handle('g', '~', '~', filter=navigation_mode & ~IsReadOnly()) - def _(event): - " Swap case of the current line. " - buff = event.current_buffer - buff.transform_current_line(lambda s: s.swapcase()) - + buffer.insert_text(c.swapcase(), overwrite=True) + + @handle('g', 'u', 'u', filter=navigation_mode & ~IsReadOnly()) + def _(event): + " Lowercase current line. " + buff = event.current_buffer + buff.transform_current_line(lambda s: s.lower()) + + @handle('g', 'U', 'U', filter=navigation_mode & ~IsReadOnly()) + def _(event): + " Uppercase current line. " + buff = event.current_buffer + buff.transform_current_line(lambda s: s.upper()) + + @handle('g', '~', '~', filter=navigation_mode & ~IsReadOnly()) + def _(event): + " Swap case of the current line. " + buff = event.current_buffer + buff.transform_current_line(lambda s: s.swapcase()) + @handle('#', filter=navigation_mode) def _(event): """ @@ -901,338 +901,338 @@ def load_vi_bindings(get_search_state=None): @handle('(', filter=navigation_mode) def _(event): # TODO: go to begin of sentence. - # XXX: should become text_object. + # XXX: should become text_object. pass @handle(')', filter=navigation_mode) def _(event): # TODO: go to end of sentence. - # XXX: should become text_object. + # XXX: should become text_object. pass operator = create_operator_decorator(registry) text_object = create_text_object_decorator(registry) - @text_object(Keys.Any, filter=operator_given) - def _(event): - """ - Unknown key binding while waiting for a text object. - """ - event.cli.output.bell() - - # - # *** Operators *** - # - - def create_delete_and_change_operators(delete_only, with_register=False): - """ - Delete and change operators. - - :param delete_only: Create an operator that deletes, but doesn't go to insert mode. - :param with_register: Copy the deleted text to this named register instead of the clipboard. - """ - if with_register: - handler_keys = ('"', Keys.Any, 'cd'[delete_only]) - else: - handler_keys = 'cd'[delete_only] - - @operator(*handler_keys, filter=~IsReadOnly()) - def delete_or_change_operator(event, text_object): - clipboard_data = None - buff = event.current_buffer - - if text_object: - new_document, clipboard_data = text_object.cut(buff) - buff.document = new_document - - # Set deleted/changed text to clipboard or named register. - if clipboard_data and clipboard_data.text: - if with_register: - reg_name = event.key_sequence[1].data - if reg_name in vi_register_names: - event.cli.vi_state.named_registers[reg_name] = clipboard_data - else: - event.cli.clipboard.set_data(clipboard_data) - - # Only go back to insert mode in case of 'change'. - if not delete_only: - event.cli.vi_state.input_mode = InputMode.INSERT - - create_delete_and_change_operators(False, False) - create_delete_and_change_operators(False, True) - create_delete_and_change_operators(True, False) - create_delete_and_change_operators(True, True) - - def create_transform_handler(filter, transform_func, *a): - @operator(*a, filter=filter & ~IsReadOnly()) - def _(event, text_object): - """ - Apply transformation (uppercase, lowercase, rot13, swap case). - """ - buff = event.current_buffer - start, end = text_object.operator_range(buff.document) - - if start < end: - # Transform. - buff.transform_region( - buff.cursor_position + start, - buff.cursor_position + end, - transform_func) - - # Move cursor - buff.cursor_position += (text_object.end or text_object.start) - - for k, f, func in vi_transform_functions: - create_transform_handler(f, func, *k) - - @operator('y') - def yank_handler(event, text_object): - """ - Yank operator. (Copy text.) - """ - _, clipboard_data = text_object.cut(event.current_buffer) - if clipboard_data.text: - event.cli.clipboard.set_data(clipboard_data) - - @operator('"', Keys.Any, 'y') - def _(event, text_object): - " Yank selection to named register. " - c = event.key_sequence[1].data - if c in vi_register_names: - _, clipboard_data = text_object.cut(event.current_buffer) - event.cli.vi_state.named_registers[c] = clipboard_data - - @operator('>') - def _(event, text_object): - """ - Indent. - """ - buff = event.current_buffer - from_, to = text_object.get_line_numbers(buff) - indent(buff, from_, to + 1, count=event.arg) - - @operator('<') - def _(event, text_object): - """ - Unindent. - """ - buff = event.current_buffer - from_, to = text_object.get_line_numbers(buff) - unindent(buff, from_, to + 1, count=event.arg) - - @operator('g', 'q') - def _(event, text_object): - """ - Reshape text. - """ - buff = event.current_buffer - from_, to = text_object.get_line_numbers(buff) - reshape_text(buff, from_, to) - - # - # *** Text objects *** - # - - @text_object('b') + @text_object(Keys.Any, filter=operator_given) + def _(event): + """ + Unknown key binding while waiting for a text object. + """ + event.cli.output.bell() + + # + # *** Operators *** + # + + def create_delete_and_change_operators(delete_only, with_register=False): + """ + Delete and change operators. + + :param delete_only: Create an operator that deletes, but doesn't go to insert mode. + :param with_register: Copy the deleted text to this named register instead of the clipboard. + """ + if with_register: + handler_keys = ('"', Keys.Any, 'cd'[delete_only]) + else: + handler_keys = 'cd'[delete_only] + + @operator(*handler_keys, filter=~IsReadOnly()) + def delete_or_change_operator(event, text_object): + clipboard_data = None + buff = event.current_buffer + + if text_object: + new_document, clipboard_data = text_object.cut(buff) + buff.document = new_document + + # Set deleted/changed text to clipboard or named register. + if clipboard_data and clipboard_data.text: + if with_register: + reg_name = event.key_sequence[1].data + if reg_name in vi_register_names: + event.cli.vi_state.named_registers[reg_name] = clipboard_data + else: + event.cli.clipboard.set_data(clipboard_data) + + # Only go back to insert mode in case of 'change'. + if not delete_only: + event.cli.vi_state.input_mode = InputMode.INSERT + + create_delete_and_change_operators(False, False) + create_delete_and_change_operators(False, True) + create_delete_and_change_operators(True, False) + create_delete_and_change_operators(True, True) + + def create_transform_handler(filter, transform_func, *a): + @operator(*a, filter=filter & ~IsReadOnly()) + def _(event, text_object): + """ + Apply transformation (uppercase, lowercase, rot13, swap case). + """ + buff = event.current_buffer + start, end = text_object.operator_range(buff.document) + + if start < end: + # Transform. + buff.transform_region( + buff.cursor_position + start, + buff.cursor_position + end, + transform_func) + + # Move cursor + buff.cursor_position += (text_object.end or text_object.start) + + for k, f, func in vi_transform_functions: + create_transform_handler(f, func, *k) + + @operator('y') + def yank_handler(event, text_object): + """ + Yank operator. (Copy text.) + """ + _, clipboard_data = text_object.cut(event.current_buffer) + if clipboard_data.text: + event.cli.clipboard.set_data(clipboard_data) + + @operator('"', Keys.Any, 'y') + def _(event, text_object): + " Yank selection to named register. " + c = event.key_sequence[1].data + if c in vi_register_names: + _, clipboard_data = text_object.cut(event.current_buffer) + event.cli.vi_state.named_registers[c] = clipboard_data + + @operator('>') + def _(event, text_object): + """ + Indent. + """ + buff = event.current_buffer + from_, to = text_object.get_line_numbers(buff) + indent(buff, from_, to + 1, count=event.arg) + + @operator('<') + def _(event, text_object): + """ + Unindent. + """ + buff = event.current_buffer + from_, to = text_object.get_line_numbers(buff) + unindent(buff, from_, to + 1, count=event.arg) + + @operator('g', 'q') + def _(event, text_object): + """ + Reshape text. + """ + buff = event.current_buffer + from_, to = text_object.get_line_numbers(buff) + reshape_text(buff, from_, to) + + # + # *** Text objects *** + # + + @text_object('b') def _(event): """ Move one word or token left. """ - return TextObject(event.current_buffer.document.find_start_of_previous_word(count=event.arg) or 0) + return TextObject(event.current_buffer.document.find_start_of_previous_word(count=event.arg) or 0) - @text_object('B') + @text_object('B') def _(event): """ Move one non-blank word left """ - return TextObject(event.current_buffer.document.find_start_of_previous_word(count=event.arg, WORD=True) or 0) + return TextObject(event.current_buffer.document.find_start_of_previous_word(count=event.arg, WORD=True) or 0) - @text_object('$') + @text_object('$') def key_dollar(event): """ 'c$', 'd$' and '$': Delete/change/move until end of line. """ - return TextObject(event.current_buffer.document.get_end_of_line_position()) + return TextObject(event.current_buffer.document.get_end_of_line_position()) - @text_object('w') + @text_object('w') def _(event): """ 'word' forward. 'cw', 'dw', 'w': Delete/change/move one word. """ - return TextObject(event.current_buffer.document.find_next_word_beginning(count=event.arg) or + return TextObject(event.current_buffer.document.find_next_word_beginning(count=event.arg) or event.current_buffer.document.get_end_of_document_position()) - @text_object('W') + @text_object('W') def _(event): """ 'WORD' forward. 'cW', 'dW', 'W': Delete/change/move one WORD. """ - return TextObject(event.current_buffer.document.find_next_word_beginning(count=event.arg, WORD=True) or + return TextObject(event.current_buffer.document.find_next_word_beginning(count=event.arg, WORD=True) or event.current_buffer.document.get_end_of_document_position()) - @text_object('e') + @text_object('e') def _(event): """ End of 'word': 'ce', 'de', 'e' """ end = event.current_buffer.document.find_next_word_ending(count=event.arg) - return TextObject(end - 1 if end else 0, type=TextObjectType.INCLUSIVE) + return TextObject(end - 1 if end else 0, type=TextObjectType.INCLUSIVE) - @text_object('E') + @text_object('E') def _(event): """ End of 'WORD': 'cE', 'dE', 'E' """ end = event.current_buffer.document.find_next_word_ending(count=event.arg, WORD=True) - return TextObject(end - 1 if end else 0, type=TextObjectType.INCLUSIVE) + return TextObject(end - 1 if end else 0, type=TextObjectType.INCLUSIVE) - @text_object('i', 'w', no_move_handler=True) + @text_object('i', 'w', no_move_handler=True) def _(event): """ Inner 'word': ciw and diw """ start, end = event.current_buffer.document.find_boundaries_of_current_word() - return TextObject(start, end) + return TextObject(start, end) - @text_object('a', 'w', no_move_handler=True) + @text_object('a', 'w', no_move_handler=True) def _(event): """ A 'word': caw and daw """ start, end = event.current_buffer.document.find_boundaries_of_current_word(include_trailing_whitespace=True) - return TextObject(start, end) + return TextObject(start, end) - @text_object('i', 'W', no_move_handler=True) + @text_object('i', 'W', no_move_handler=True) def _(event): """ Inner 'WORD': ciW and diW """ start, end = event.current_buffer.document.find_boundaries_of_current_word(WORD=True) - return TextObject(start, end) + return TextObject(start, end) - @text_object('a', 'W', no_move_handler=True) + @text_object('a', 'W', no_move_handler=True) def _(event): """ A 'WORD': caw and daw """ start, end = event.current_buffer.document.find_boundaries_of_current_word(WORD=True, include_trailing_whitespace=True) - return TextObject(start, end) - - @text_object('a', 'p', no_move_handler=True) - def _(event): - """ - Auto paragraph. - """ - start = event.current_buffer.document.start_of_paragraph() - end = event.current_buffer.document.end_of_paragraph(count=event.arg) - return TextObject(start, end) - - @text_object('^') + return TextObject(start, end) + + @text_object('a', 'p', no_move_handler=True) + def _(event): + """ + Auto paragraph. + """ + start = event.current_buffer.document.start_of_paragraph() + end = event.current_buffer.document.end_of_paragraph(count=event.arg) + return TextObject(start, end) + + @text_object('^') def key_circumflex(event): """ 'c^', 'd^' and '^': Soft start of line, after whitespace. """ - return TextObject(event.current_buffer.document.get_start_of_line_position(after_whitespace=True)) + return TextObject(event.current_buffer.document.get_start_of_line_position(after_whitespace=True)) - @text_object('0') + @text_object('0') def key_zero(event): """ 'c0', 'd0': Hard start of line, before whitespace. (The move '0' key is implemented elsewhere, because a '0' could also change the `arg`.) """ - return TextObject(event.current_buffer.document.get_start_of_line_position(after_whitespace=False)) + return TextObject(event.current_buffer.document.get_start_of_line_position(after_whitespace=False)) - def create_ci_ca_handles(ci_start, ci_end, inner, key=None): + def create_ci_ca_handles(ci_start, ci_end, inner, key=None): # TODO: 'dat', 'dit', (tags (like xml) """ Delete/Change string between this start and stop character. But keep these characters. This implements all the ci", ci<, ci{, ci(, di", di<, ca", ca<, ... combinations. """ - def handler(event): - if ci_start == ci_end: - # Quotes - start = event.current_buffer.document.find_backwards(ci_start, in_current_line=False) - end = event.current_buffer.document.find(ci_end, in_current_line=False) - else: - # Brackets - start = event.current_buffer.document.find_enclosing_bracket_left(ci_start, ci_end) - end = event.current_buffer.document.find_enclosing_bracket_right(ci_start, ci_end) + def handler(event): + if ci_start == ci_end: + # Quotes + start = event.current_buffer.document.find_backwards(ci_start, in_current_line=False) + end = event.current_buffer.document.find(ci_end, in_current_line=False) + else: + # Brackets + start = event.current_buffer.document.find_enclosing_bracket_left(ci_start, ci_end) + end = event.current_buffer.document.find_enclosing_bracket_right(ci_start, ci_end) if start is not None and end is not None: offset = 0 if inner else 1 - return TextObject(start + 1 - offset, end + offset) + return TextObject(start + 1 - offset, end + offset) else: # Nothing found. - return TextObject(0) - - if key is None: - text_object('ai'[inner], ci_start, no_move_handler=True)(handler) - text_object('ai'[inner], ci_end, no_move_handler=True)(handler) - else: - text_object('ai'[inner], key, no_move_handler=True)(handler) - + return TextObject(0) + + if key is None: + text_object('ai'[inner], ci_start, no_move_handler=True)(handler) + text_object('ai'[inner], ci_end, no_move_handler=True)(handler) + else: + text_object('ai'[inner], key, no_move_handler=True)(handler) + for inner in (False, True): for ci_start, ci_end in [('"', '"'), ("'", "'"), ("`", "`"), ('[', ']'), ('<', '>'), ('{', '}'), ('(', ')')]: create_ci_ca_handles(ci_start, ci_end, inner) - create_ci_ca_handles('(', ')', inner, 'b') # 'dab', 'dib' - create_ci_ca_handles('{', '}', inner, 'B') # 'daB', 'diB' - - @text_object('{') + create_ci_ca_handles('(', ')', inner, 'b') # 'dab', 'dib' + create_ci_ca_handles('{', '}', inner, 'B') # 'daB', 'diB' + + @text_object('{') def _(event): """ Move to previous blank-line separated section. Implements '{', 'c{', 'd{', 'y{' """ - index = event.current_buffer.document.start_of_paragraph( - count=event.arg, before=True) - return TextObject(index) + index = event.current_buffer.document.start_of_paragraph( + count=event.arg, before=True) + return TextObject(index) - @text_object('}') + @text_object('}') def _(event): """ Move to next blank-line separated section. Implements '}', 'c}', 'd}', 'y}' """ - index = event.current_buffer.document.end_of_paragraph(count=event.arg, after=True) - return TextObject(index) + index = event.current_buffer.document.end_of_paragraph(count=event.arg, after=True) + return TextObject(index) - @text_object('f', Keys.Any) + @text_object('f', Keys.Any) def _(event): """ Go to next occurance of character. Typing 'fx' will move the cursor to the next occurance of character. 'x'. """ - event.cli.vi_state.last_character_find = CharacterFind(event.data, False) - match = event.current_buffer.document.find( - event.data, in_current_line=True, count=event.arg) - if match: - return TextObject(match, type=TextObjectType.INCLUSIVE) - else: - return TextObject(0) + event.cli.vi_state.last_character_find = CharacterFind(event.data, False) + match = event.current_buffer.document.find( + event.data, in_current_line=True, count=event.arg) + if match: + return TextObject(match, type=TextObjectType.INCLUSIVE) + else: + return TextObject(0) - @text_object('F', Keys.Any) + @text_object('F', Keys.Any) def _(event): """ Go to previous occurance of character. Typing 'Fx' will move the cursor to the previous occurance of character. 'x'. """ - event.cli.vi_state.last_character_find = CharacterFind(event.data, True) - return TextObject(event.current_buffer.document.find_backwards( - event.data, in_current_line=True, count=event.arg) or 0) + event.cli.vi_state.last_character_find = CharacterFind(event.data, True) + return TextObject(event.current_buffer.document.find_backwards( + event.data, in_current_line=True, count=event.arg) or 0) - @text_object('t', Keys.Any) + @text_object('t', Keys.Any) def _(event): """ Move right to the next occurance of c, then one char backward. """ - event.cli.vi_state.last_character_find = CharacterFind(event.data, False) - match = event.current_buffer.document.find( - event.data, in_current_line=True, count=event.arg) - if match: - return TextObject(match - 1, type=TextObjectType.INCLUSIVE) - else: - return TextObject(0) + event.cli.vi_state.last_character_find = CharacterFind(event.data, False) + match = event.current_buffer.document.find( + event.data, in_current_line=True, count=event.arg) + if match: + return TextObject(match - 1, type=TextObjectType.INCLUSIVE) + else: + return TextObject(0) - @text_object('T', Keys.Any) + @text_object('T', Keys.Any) def _(event): """ Move left to the previous occurance of c, then one char forward. """ - event.cli.vi_state.last_character_find = CharacterFind(event.data, True) - match = event.current_buffer.document.find_backwards( - event.data, in_current_line=True, count=event.arg) - return TextObject(match + 1 if match else 0) + event.cli.vi_state.last_character_find = CharacterFind(event.data, True) + match = event.current_buffer.document.find_backwards( + event.data, in_current_line=True, count=event.arg) + return TextObject(match + 1 if match else 0) def repeat(reverse): """ Create ',' and ';' commands. """ - @text_object(',' if reverse else ';') + @text_object(',' if reverse else ';') def _(event): # Repeat the last 'f'/'F'/'t'/'T' command. pos = 0 - vi_state = event.cli.vi_state - - type = TextObjectType.EXCLUSIVE + vi_state = event.cli.vi_state + type = TextObjectType.EXCLUSIVE + if vi_state.last_character_find: char = vi_state.last_character_find.character backwards = vi_state.last_character_find.backwards @@ -1244,43 +1244,43 @@ def load_vi_bindings(get_search_state=None): pos = event.current_buffer.document.find_backwards(char, in_current_line=True, count=event.arg) else: pos = event.current_buffer.document.find(char, in_current_line=True, count=event.arg) - type = TextObjectType.INCLUSIVE - if pos: - return TextObject(pos, type=type) - else: - return TextObject(0) + type = TextObjectType.INCLUSIVE + if pos: + return TextObject(pos, type=type) + else: + return TextObject(0) repeat(True) repeat(False) - @text_object('h') - @text_object(Keys.Left) + @text_object('h') + @text_object(Keys.Left) def _(event): """ Implements 'ch', 'dh', 'h': Cursor left. """ - return TextObject(event.current_buffer.document.get_cursor_left_position(count=event.arg)) + return TextObject(event.current_buffer.document.get_cursor_left_position(count=event.arg)) - @text_object('j', no_move_handler=True, no_selection_handler=True) - # Note: We also need `no_selection_handler`, because we in - # selection mode, we prefer the other 'j' binding that keeps - # `buffer.preferred_column`. + @text_object('j', no_move_handler=True, no_selection_handler=True) + # Note: We also need `no_selection_handler`, because we in + # selection mode, we prefer the other 'j' binding that keeps + # `buffer.preferred_column`. def _(event): """ Implements 'cj', 'dj', 'j', ... Cursor up. """ - return TextObject(event.current_buffer.document.get_cursor_down_position(count=event.arg), - type=TextObjectType.LINEWISE) + return TextObject(event.current_buffer.document.get_cursor_down_position(count=event.arg), + type=TextObjectType.LINEWISE) - @text_object('k', no_move_handler=True, no_selection_handler=True) + @text_object('k', no_move_handler=True, no_selection_handler=True) def _(event): """ Implements 'ck', 'dk', 'k', ... Cursor up. """ - return TextObject(event.current_buffer.document.get_cursor_up_position(count=event.arg), - type=TextObjectType.LINEWISE) + return TextObject(event.current_buffer.document.get_cursor_up_position(count=event.arg), + type=TextObjectType.LINEWISE) - @text_object('l') - @text_object(' ') - @text_object(Keys.Right) + @text_object('l') + @text_object(' ') + @text_object(Keys.Right) def _(event): """ Implements 'cl', 'dl', 'l', 'c ', 'd ', ' '. Cursor right. """ - return TextObject(event.current_buffer.document.get_cursor_right_position(count=event.arg)) + return TextObject(event.current_buffer.document.get_cursor_right_position(count=event.arg)) - @text_object('H') + @text_object('H') def _(event): """ Moves to the start of the visible region. (Below the scroll offset.) @@ -1289,7 +1289,7 @@ def load_vi_bindings(get_search_state=None): w = find_window_for_buffer_name(event.cli, event.cli.current_buffer_name) b = event.current_buffer - if w and w.render_info: + if w and w.render_info: # When we find a Window that has BufferControl showing this window, # move to the start of the visible area. pos = (b.document.translate_row_col_to_index( @@ -1299,9 +1299,9 @@ def load_vi_bindings(get_search_state=None): else: # Otherwise, move to the start of the input. pos = -len(b.document.text_before_cursor) - return TextObject(pos, type=TextObjectType.LINEWISE) + return TextObject(pos, type=TextObjectType.LINEWISE) - @text_object('M') + @text_object('M') def _(event): """ Moves cursor to the vertical center of the visible region. @@ -1310,7 +1310,7 @@ def load_vi_bindings(get_search_state=None): w = find_window_for_buffer_name(event.cli, event.cli.current_buffer_name) b = event.current_buffer - if w and w.render_info: + if w and w.render_info: # When we find a Window that has BufferControl showing this window, # move to the center of the visible area. pos = (b.document.translate_row_col_to_index( @@ -1320,9 +1320,9 @@ def load_vi_bindings(get_search_state=None): else: # Otherwise, move to the start of the input. pos = -len(b.document.text_before_cursor) - return TextObject(pos, type=TextObjectType.LINEWISE) + return TextObject(pos, type=TextObjectType.LINEWISE) - @text_object('L') + @text_object('L') def _(event): """ Moves to the end of the visible region. (Above the scroll offset.) @@ -1330,7 +1330,7 @@ def load_vi_bindings(get_search_state=None): w = find_window_for_buffer_name(event.cli, event.cli.current_buffer_name) b = event.current_buffer - if w and w.render_info: + if w and w.render_info: # When we find a Window that has BufferControl showing this window, # move to the end of the visible area. pos = (b.document.translate_row_col_to_index( @@ -1340,40 +1340,40 @@ def load_vi_bindings(get_search_state=None): else: # Otherwise, move to the end of the input. pos = len(b.document.text_after_cursor) - return TextObject(pos, type=TextObjectType.LINEWISE) - - @text_object('n', no_move_handler=True) - def _(event): - " Search next. " - buff = event.current_buffer - cursor_position = buff.get_search_position( - get_search_state(event.cli), include_current_position=False, - count=event.arg) - return TextObject(cursor_position - buff.cursor_position) - - @handle('n', filter=navigation_mode) - def _(event): - " Search next in navigation mode. (This goes through the history.) " - event.current_buffer.apply_search( - get_search_state(event.cli), include_current_position=False, - count=event.arg) - - @text_object('N', no_move_handler=True) - def _(event): - " Search previous. " - buff = event.current_buffer - cursor_position = buff.get_search_position( - ~get_search_state(event.cli), include_current_position=False, - count=event.arg) - return TextObject(cursor_position - buff.cursor_position) - - @handle('N', filter=navigation_mode) - def _(event): - " Search previous in navigation mode. (This goes through the history.) " - event.current_buffer.apply_search( - ~get_search_state(event.cli), include_current_position=False, - count=event.arg) - + return TextObject(pos, type=TextObjectType.LINEWISE) + + @text_object('n', no_move_handler=True) + def _(event): + " Search next. " + buff = event.current_buffer + cursor_position = buff.get_search_position( + get_search_state(event.cli), include_current_position=False, + count=event.arg) + return TextObject(cursor_position - buff.cursor_position) + + @handle('n', filter=navigation_mode) + def _(event): + " Search next in navigation mode. (This goes through the history.) " + event.current_buffer.apply_search( + get_search_state(event.cli), include_current_position=False, + count=event.arg) + + @text_object('N', no_move_handler=True) + def _(event): + " Search previous. " + buff = event.current_buffer + cursor_position = buff.get_search_position( + ~get_search_state(event.cli), include_current_position=False, + count=event.arg) + return TextObject(cursor_position - buff.cursor_position) + + @handle('N', filter=navigation_mode) + def _(event): + " Search previous in navigation mode. (This goes through the history.) " + event.current_buffer.apply_search( + ~get_search_state(event.cli), include_current_position=False, + count=event.arg) + @handle('z', '+', filter=navigation_mode|selection_mode) @handle('z', 't', filter=navigation_mode|selection_mode) @handle('z', Keys.ControlJ, filter=navigation_mode|selection_mode) @@ -1383,7 +1383,7 @@ def load_vi_bindings(get_search_state=None): """ w = find_window_for_buffer_name(event.cli, event.cli.current_buffer_name) b = event.cli.current_buffer - w.vertical_scroll = b.document.cursor_position_row + w.vertical_scroll = b.document.cursor_position_row @handle('z', '-', filter=navigation_mode|selection_mode) @handle('z', 'b', filter=navigation_mode|selection_mode) @@ -1393,10 +1393,10 @@ def load_vi_bindings(get_search_state=None): """ w = find_window_for_buffer_name(event.cli, event.cli.current_buffer_name) - # We can safely set the scroll offset to zero; the Window will meke - # sure that it scrolls at least enough to make the cursor visible - # again. - w.vertical_scroll = 0 + # We can safely set the scroll offset to zero; the Window will meke + # sure that it scrolls at least enough to make the cursor visible + # again. + w.vertical_scroll = 0 @handle('z', 'z', filter=navigation_mode|selection_mode) def _(event): @@ -1407,26 +1407,26 @@ def load_vi_bindings(get_search_state=None): b = event.cli.current_buffer if w and w.render_info: - info = w.render_info - + info = w.render_info + # Calculate the offset that we need in order to position the row # containing the cursor in the center. - scroll_height = info.window_height // 2 - - y = max(0, b.document.cursor_position_row - 1) - height = 0 - while y > 0: - line_height = info.get_height_for_line(y) - - if height + line_height < scroll_height: - height += line_height - y -= 1 - else: - break + scroll_height = info.window_height // 2 - w.vertical_scroll = y + y = max(0, b.document.cursor_position_row - 1) + height = 0 + while y > 0: + line_height = info.get_height_for_line(y) - @text_object('%') + if height + line_height < scroll_height: + height += line_height + y -= 1 + else: + break + + w.vertical_scroll = y + + @text_object('%') def _(event): """ Implements 'c%', 'd%', '%, 'y%' (Move to corresponding bracket.) @@ -1439,26 +1439,26 @@ def load_vi_bindings(get_search_state=None): # row in the file. if 0 < event.arg <= 100: absolute_index = buffer.document.translate_row_col_to_index( - int((event.arg * buffer.document.line_count - 1) / 100), 0) - return TextObject(absolute_index - buffer.document.cursor_position, type=TextObjectType.LINEWISE) + int((event.arg * buffer.document.line_count - 1) / 100), 0) + return TextObject(absolute_index - buffer.document.cursor_position, type=TextObjectType.LINEWISE) else: - return TextObject(0) # Do nothing. + return TextObject(0) # Do nothing. else: # Move to the corresponding opening/closing bracket (()'s, []'s and {}'s). - match = buffer.document.find_matching_bracket_position() - if match: - return TextObject(match, type=TextObjectType.INCLUSIVE) - else: - return TextObject(0) + match = buffer.document.find_matching_bracket_position() + if match: + return TextObject(match, type=TextObjectType.INCLUSIVE) + else: + return TextObject(0) - @text_object('|') + @text_object('|') def _(event): # Move to the n-th column (you may specify the argument n by typing # it on number keys, for example, 20|). - return TextObject(event.current_buffer.document.get_column_cursor_position(event.arg - 1)) + return TextObject(event.current_buffer.document.get_column_cursor_position(event.arg - 1)) - @text_object('g', 'g') + @text_object('g', 'g') def _(event): """ Implements 'gg', 'cgg', 'ygg' @@ -1467,67 +1467,67 @@ def load_vi_bindings(get_search_state=None): if event._arg: # Move to the given line. - return TextObject(d.translate_row_col_to_index(event.arg - 1, 0) - d.cursor_position, type=TextObjectType.LINEWISE) + return TextObject(d.translate_row_col_to_index(event.arg - 1, 0) - d.cursor_position, type=TextObjectType.LINEWISE) else: # Move to the top of the input. - return TextObject(d.get_start_of_document_position(), type=TextObjectType.LINEWISE) + return TextObject(d.get_start_of_document_position(), type=TextObjectType.LINEWISE) - @text_object('g', '_') + @text_object('g', '_') def _(event): """ Go to last non-blank of line. 'g_', 'cg_', 'yg_', etc.. """ - return TextObject( - event.current_buffer.document.last_non_blank_of_current_line_position(), type=TextObjectType.INCLUSIVE) + return TextObject( + event.current_buffer.document.last_non_blank_of_current_line_position(), type=TextObjectType.INCLUSIVE) - @text_object('g', 'e') + @text_object('g', 'e') def _(event): """ Go to last character of previous word. 'ge', 'cge', 'yge', etc.. """ - prev_end = event.current_buffer.document.find_previous_word_ending(count=event.arg) - return TextObject(prev_end - 1 if prev_end is not None else 0, type=TextObjectType.INCLUSIVE) + prev_end = event.current_buffer.document.find_previous_word_ending(count=event.arg) + return TextObject(prev_end - 1 if prev_end is not None else 0, type=TextObjectType.INCLUSIVE) - @text_object('g', 'E') + @text_object('g', 'E') def _(event): """ Go to last character of previous WORD. 'gE', 'cgE', 'ygE', etc.. """ - prev_end = event.current_buffer.document.find_previous_word_ending(count=event.arg, WORD=True) - return TextObject(prev_end - 1 if prev_end is not None else 0, type=TextObjectType.INCLUSIVE) - - @text_object('g', 'm') - def _(event): - """ - Like g0, but half a screenwidth to the right. (Or as much as possible.) - """ - w = find_window_for_buffer_name(event.cli, event.cli.current_buffer_name) - buff = event.current_buffer - - if w and w.render_info: - width = w.render_info.window_width - start = buff.document.get_start_of_line_position(after_whitespace=False) - start += int(min(width / 2, len(buff.document.current_line))) - - return TextObject(start, type=TextObjectType.INCLUSIVE) - return TextObject(0) - - @text_object('G') - def _(event): - """ + prev_end = event.current_buffer.document.find_previous_word_ending(count=event.arg, WORD=True) + return TextObject(prev_end - 1 if prev_end is not None else 0, type=TextObjectType.INCLUSIVE) + + @text_object('g', 'm') + def _(event): + """ + Like g0, but half a screenwidth to the right. (Or as much as possible.) + """ + w = find_window_for_buffer_name(event.cli, event.cli.current_buffer_name) + buff = event.current_buffer + + if w and w.render_info: + width = w.render_info.window_width + start = buff.document.get_start_of_line_position(after_whitespace=False) + start += int(min(width / 2, len(buff.document.current_line))) + + return TextObject(start, type=TextObjectType.INCLUSIVE) + return TextObject(0) + + @text_object('G') + def _(event): + """ Go to the end of the document. (If no arg has been given.) """ - buf = event.current_buffer - return TextObject(buf.document.translate_row_col_to_index(buf.document.line_count - 1, 0) - - buf.cursor_position, type=TextObjectType.LINEWISE) - - # - # *** Other *** - # + buf = event.current_buffer + return TextObject(buf.document.translate_row_col_to_index(buf.document.line_count - 1, 0) - + buf.cursor_position, type=TextObjectType.LINEWISE) + # + # *** Other *** + # + @handle('G', filter=HasArg()) def _(event): """ @@ -1536,19 +1536,19 @@ def load_vi_bindings(get_search_state=None): """ event.current_buffer.go_to_history(event.arg - 1) - for n in '123456789': - @handle(n, filter=navigation_mode|selection_mode|operator_given) - def _(event): - """ - Always handle numberics in navigation mode as arg. - """ + for n in '123456789': + @handle(n, filter=navigation_mode|selection_mode|operator_given) + def _(event): + """ + Always handle numberics in navigation mode as arg. + """ event.append_to_arg_count(event.data) - @handle('0', filter=(navigation_mode|selection_mode|operator_given) & HasArg()) - def _(event): - " Zero when an argument was already give. " - event.append_to_arg_count(event.data) - + @handle('0', filter=(navigation_mode|selection_mode|operator_given) & HasArg()) + def _(event): + " Zero when an argument was already give. " + event.append_to_arg_count(event.data) + @handle(Keys.Any, filter=replace_mode) def _(event): """ @@ -1556,104 +1556,104 @@ def load_vi_bindings(get_search_state=None): """ event.current_buffer.insert_text(event.data, overwrite=True) - @handle(Keys.Any, filter=insert_multiple_mode, - save_before=(lambda e: not e.is_repeat)) - def _(event): - """ - Insert data at multiple cursor positions at once. - (Usually a result of pressing 'I' or 'A' in block-selection mode.) - """ - buff = event.current_buffer - original_text = buff.text - - # Construct new text. - text = [] - p = 0 - - for p2 in buff.multiple_cursor_positions: - text.append(original_text[p:p2]) - text.append(event.data) - p = p2 - - text.append(original_text[p:]) - - # Shift all cursor positions. - new_cursor_positions = [ - p + i + 1 for i, p in enumerate(buff.multiple_cursor_positions)] - - # Set result. - buff.text = ''.join(text) - buff.multiple_cursor_positions = new_cursor_positions - buff.cursor_position += 1 - - @handle(Keys.Backspace, filter=insert_multiple_mode) - def _(event): - " Backspace, using multiple cursors. " - buff = event.current_buffer - original_text = buff.text - - # Construct new text. - deleted_something = False - text = [] - p = 0 - - for p2 in buff.multiple_cursor_positions: - if p2 > 0 and original_text[p2 - 1] != '\n': # Don't delete across lines. - text.append(original_text[p:p2 - 1]) - deleted_something = True - else: - text.append(original_text[p:p2]) - p = p2 - - text.append(original_text[p:]) - - if deleted_something: - # Shift all cursor positions. - lengths = [len(part) for part in text[:-1]] - new_cursor_positions = list(accumulate(lengths)) - - # Set result. - buff.text = ''.join(text) - buff.multiple_cursor_positions = new_cursor_positions - buff.cursor_position -= 1 - else: - event.cli.output.bell() - - @handle(Keys.Delete, filter=insert_multiple_mode) - def _(event): - " Delete, using multiple cursors. " - buff = event.current_buffer - original_text = buff.text - - # Construct new text. - deleted_something = False - text = [] - new_cursor_positions = [] - p = 0 - - for p2 in buff.multiple_cursor_positions: - text.append(original_text[p:p2]) - if p2 >= len(original_text) or original_text[p2] == '\n': - # Don't delete across lines. - p = p2 - else: - p = p2 + 1 - deleted_something = True - - text.append(original_text[p:]) - - if deleted_something: - # Shift all cursor positions. - lengths = [len(part) for part in text[:-1]] - new_cursor_positions = list(accumulate(lengths)) - - # Set result. - buff.text = ''.join(text) - buff.multiple_cursor_positions = new_cursor_positions - else: - event.cli.output.bell() - - + @handle(Keys.Any, filter=insert_multiple_mode, + save_before=(lambda e: not e.is_repeat)) + def _(event): + """ + Insert data at multiple cursor positions at once. + (Usually a result of pressing 'I' or 'A' in block-selection mode.) + """ + buff = event.current_buffer + original_text = buff.text + + # Construct new text. + text = [] + p = 0 + + for p2 in buff.multiple_cursor_positions: + text.append(original_text[p:p2]) + text.append(event.data) + p = p2 + + text.append(original_text[p:]) + + # Shift all cursor positions. + new_cursor_positions = [ + p + i + 1 for i, p in enumerate(buff.multiple_cursor_positions)] + + # Set result. + buff.text = ''.join(text) + buff.multiple_cursor_positions = new_cursor_positions + buff.cursor_position += 1 + + @handle(Keys.Backspace, filter=insert_multiple_mode) + def _(event): + " Backspace, using multiple cursors. " + buff = event.current_buffer + original_text = buff.text + + # Construct new text. + deleted_something = False + text = [] + p = 0 + + for p2 in buff.multiple_cursor_positions: + if p2 > 0 and original_text[p2 - 1] != '\n': # Don't delete across lines. + text.append(original_text[p:p2 - 1]) + deleted_something = True + else: + text.append(original_text[p:p2]) + p = p2 + + text.append(original_text[p:]) + + if deleted_something: + # Shift all cursor positions. + lengths = [len(part) for part in text[:-1]] + new_cursor_positions = list(accumulate(lengths)) + + # Set result. + buff.text = ''.join(text) + buff.multiple_cursor_positions = new_cursor_positions + buff.cursor_position -= 1 + else: + event.cli.output.bell() + + @handle(Keys.Delete, filter=insert_multiple_mode) + def _(event): + " Delete, using multiple cursors. " + buff = event.current_buffer + original_text = buff.text + + # Construct new text. + deleted_something = False + text = [] + new_cursor_positions = [] + p = 0 + + for p2 in buff.multiple_cursor_positions: + text.append(original_text[p:p2]) + if p2 >= len(original_text) or original_text[p2] == '\n': + # Don't delete across lines. + p = p2 + else: + p = p2 + 1 + deleted_something = True + + text.append(original_text[p:]) + + if deleted_something: + # Shift all cursor positions. + lengths = [len(part) for part in text[:-1]] + new_cursor_positions = list(accumulate(lengths)) + + # Set result. + buff.text = ''.join(text) + buff.multiple_cursor_positions = new_cursor_positions + else: + event.cli.output.bell() + + @handle(Keys.ControlX, Keys.ControlL, filter=insert_mode) def _(event): """ @@ -1670,50 +1670,50 @@ def load_vi_bindings(get_search_state=None): # TODO pass - @handle(Keys.ControlK, filter=insert_mode|replace_mode) - def _(event): - " Go into digraph mode. " - event.cli.vi_state.waiting_for_digraph = True - - @Condition - def digraph_symbol_1_given(cli): - return cli.vi_state.digraph_symbol1 is not None - - @handle(Keys.Any, filter=digraph_mode & ~digraph_symbol_1_given) - def _(event): - event.cli.vi_state.digraph_symbol1 = event.data - - @handle(Keys.Any, filter=digraph_mode & digraph_symbol_1_given) - def _(event): - " Insert digraph. " - try: - # Lookup. - code = (event.cli.vi_state.digraph_symbol1, event.data) - if code not in DIGRAPHS: - code = code[::-1] # Try reversing. - symbol = DIGRAPHS[code] - except KeyError: - # Unkown digraph. - event.cli.output.bell() - else: - # Insert digraph. - overwrite = event.cli.vi_state.input_mode == InputMode.REPLACE - event.current_buffer.insert_text( - six.unichr(symbol), overwrite=overwrite) - event.cli.vi_state.waiting_for_digraph = False - finally: - event.cli.vi_state.waiting_for_digraph = False - event.cli.vi_state.digraph_symbol1 = None - + @handle(Keys.ControlK, filter=insert_mode|replace_mode) + def _(event): + " Go into digraph mode. " + event.cli.vi_state.waiting_for_digraph = True + + @Condition + def digraph_symbol_1_given(cli): + return cli.vi_state.digraph_symbol1 is not None + + @handle(Keys.Any, filter=digraph_mode & ~digraph_symbol_1_given) + def _(event): + event.cli.vi_state.digraph_symbol1 = event.data + + @handle(Keys.Any, filter=digraph_mode & digraph_symbol_1_given) + def _(event): + " Insert digraph. " + try: + # Lookup. + code = (event.cli.vi_state.digraph_symbol1, event.data) + if code not in DIGRAPHS: + code = code[::-1] # Try reversing. + symbol = DIGRAPHS[code] + except KeyError: + # Unkown digraph. + event.cli.output.bell() + else: + # Insert digraph. + overwrite = event.cli.vi_state.input_mode == InputMode.REPLACE + event.current_buffer.insert_text( + six.unichr(symbol), overwrite=overwrite) + event.cli.vi_state.waiting_for_digraph = False + finally: + event.cli.vi_state.waiting_for_digraph = False + event.cli.vi_state.digraph_symbol1 = None + return registry - + def load_vi_open_in_editor_bindings(): """ Pressing 'v' in navigation mode will open the buffer in an external editor. """ registry = Registry() - navigation_mode = ViNavigationMode() + navigation_mode = ViNavigationMode() registry.add_binding('v', filter=navigation_mode)( get_by_name('edit-and-execute-command')) @@ -1725,7 +1725,7 @@ def load_vi_system_bindings(): handle = registry.add_binding has_focus = filters.HasFocus(SYSTEM_BUFFER) - navigation_mode = ViNavigationMode() + navigation_mode = ViNavigationMode() @handle('!', filter=~has_focus & navigation_mode) def _(event): @@ -1733,7 +1733,7 @@ def load_vi_system_bindings(): '!' opens the system prompt. """ event.cli.push_focus(SYSTEM_BUFFER) - event.cli.vi_state.input_mode = InputMode.INSERT + event.cli.vi_state.input_mode = InputMode.INSERT @handle(Keys.Escape, filter=has_focus) @handle(Keys.ControlC, filter=has_focus) @@ -1741,7 +1741,7 @@ def load_vi_system_bindings(): """ Cancel system prompt. """ - event.cli.vi_state.input_mode = InputMode.NAVIGATION + event.cli.vi_state.input_mode = InputMode.NAVIGATION event.cli.buffers[SYSTEM_BUFFER].reset() event.cli.pop_focus() @@ -1750,7 +1750,7 @@ def load_vi_system_bindings(): """ Run system command. """ - event.cli.vi_state.input_mode = InputMode.NAVIGATION + event.cli.vi_state.input_mode = InputMode.NAVIGATION system_buffer = event.cli.buffers[SYSTEM_BUFFER] event.cli.run_system_command(system_buffer.text) @@ -1773,8 +1773,8 @@ def load_vi_search_bindings(get_search_state=None, handle = registry.add_binding has_focus = filters.HasFocus(search_buffer_name) - navigation_mode = ViNavigationMode() - selection_mode = ViSelectionMode() + navigation_mode = ViNavigationMode() + selection_mode = ViSelectionMode() reverse_vi_search_direction = Condition( lambda cli: cli.application.reverse_vi_search_direction(cli)) @@ -1788,7 +1788,7 @@ def load_vi_search_bindings(get_search_state=None, """ # Set the ViState. get_search_state(event.cli).direction = IncrementalSearchDirection.FORWARD - event.cli.vi_state.input_mode = InputMode.INSERT + event.cli.vi_state.input_mode = InputMode.INSERT # Focus search buffer. event.cli.push_focus(search_buffer_name) @@ -1805,7 +1805,7 @@ def load_vi_search_bindings(get_search_state=None, # Focus search buffer. event.cli.push_focus(search_buffer_name) - event.cli.vi_state.input_mode = InputMode.INSERT + event.cli.vi_state.input_mode = InputMode.INSERT @handle(Keys.ControlJ, filter=has_focus) @handle(Keys.Escape, filter=has_focus) @@ -1828,44 +1828,44 @@ def load_vi_search_bindings(get_search_state=None, search_buffer.reset() # Focus previous document again. - event.cli.vi_state.input_mode = InputMode.NAVIGATION + event.cli.vi_state.input_mode = InputMode.NAVIGATION event.cli.pop_focus() - def incremental_search(cli, direction, count=1): - " Apply search, but keep search buffer focussed. " - # Update search_state. - search_state = get_search_state(cli) - direction_changed = search_state.direction != direction - - search_state.text = cli.buffers[search_buffer_name].text - search_state.direction = direction - - # Apply search to current buffer. - if not direction_changed: - input_buffer = cli.buffers.previous(cli) - input_buffer.apply_search(search_state, - include_current_position=False, count=count) - - @handle(Keys.ControlR, filter=has_focus) - def _(event): - incremental_search(event.cli, IncrementalSearchDirection.BACKWARD, count=event.arg) - - @handle(Keys.ControlS, filter=has_focus) - def _(event): - incremental_search(event.cli, IncrementalSearchDirection.FORWARD, count=event.arg) - + def incremental_search(cli, direction, count=1): + " Apply search, but keep search buffer focussed. " + # Update search_state. + search_state = get_search_state(cli) + direction_changed = search_state.direction != direction + + search_state.text = cli.buffers[search_buffer_name].text + search_state.direction = direction + + # Apply search to current buffer. + if not direction_changed: + input_buffer = cli.buffers.previous(cli) + input_buffer.apply_search(search_state, + include_current_position=False, count=count) + + @handle(Keys.ControlR, filter=has_focus) + def _(event): + incremental_search(event.cli, IncrementalSearchDirection.BACKWARD, count=event.arg) + + @handle(Keys.ControlS, filter=has_focus) + def _(event): + incremental_search(event.cli, IncrementalSearchDirection.FORWARD, count=event.arg) + def search_buffer_is_empty(cli): """ Returns True when the search buffer is empty. """ return cli.buffers[search_buffer_name].text == '' @handle(Keys.ControlC, filter=has_focus) - @handle(Keys.ControlH, filter=has_focus & Condition(search_buffer_is_empty)) + @handle(Keys.ControlH, filter=has_focus & Condition(search_buffer_is_empty)) @handle(Keys.Backspace, filter=has_focus & Condition(search_buffer_is_empty)) def _(event): """ Cancel search. """ - event.cli.vi_state.input_mode = InputMode.NAVIGATION + event.cli.vi_state.input_mode = InputMode.NAVIGATION event.cli.pop_focus() event.cli.buffers[search_buffer_name].reset() @@ -1889,15 +1889,15 @@ def load_extra_vi_page_navigation_bindings(): handle(Keys.ControlY)(scroll_one_line_up) handle(Keys.PageDown)(scroll_page_down) handle(Keys.PageUp)(scroll_page_up) - + return registry - - -class ViStateFilter(Filter): - " Deprecated! " - def __init__(self, get_vi_state, mode): - self.get_vi_state = get_vi_state - self.mode = mode - - def __call__(self, cli): - return self.get_vi_state(cli).input_mode == self.mode + + +class ViStateFilter(Filter): + " Deprecated! " + def __init__(self, get_vi_state, mode): + self.get_vi_state = get_vi_state + self.mode = mode + + def __call__(self, cli): + return self.get_vi_state(cli).input_mode == self.mode diff --git a/contrib/python/prompt-toolkit/py2/prompt_toolkit/key_binding/digraphs.py b/contrib/python/prompt-toolkit/py2/prompt_toolkit/key_binding/digraphs.py index 36c6b15103..3301c507d3 100644 --- a/contrib/python/prompt-toolkit/py2/prompt_toolkit/key_binding/digraphs.py +++ b/contrib/python/prompt-toolkit/py2/prompt_toolkit/key_binding/digraphs.py @@ -1,1378 +1,1378 @@ -# encoding: utf-8 -from __future__ import unicode_literals -""" -Vi Digraphs. -This is a list of special characters that can be inserted in Vi insert mode by -pressing Control-K followed by to normal characters. - -Taken from Neovim and translated to Python: -https://raw.githubusercontent.com/neovim/neovim/master/src/nvim/digraph.c -""" -__all__ = ('DIGRAPHS', ) - -# digraphs for Unicode from RFC1345 -# (also work for ISO-8859-1 aka latin1) -DIGRAPHS = { - ('N', 'U'): 0x00, - ('S', 'H'): 0x01, - ('S', 'X'): 0x02, - ('E', 'X'): 0x03, - ('E', 'T'): 0x04, - ('E', 'Q'): 0x05, - ('A', 'K'): 0x06, - ('B', 'L'): 0x07, - ('B', 'S'): 0x08, - ('H', 'T'): 0x09, - ('L', 'F'): 0x0a, - ('V', 'T'): 0x0b, - ('F', 'F'): 0x0c, - ('C', 'R'): 0x0d, - ('S', 'O'): 0x0e, - ('S', 'I'): 0x0f, - ('D', 'L'): 0x10, - ('D', '1'): 0x11, - ('D', '2'): 0x12, - ('D', '3'): 0x13, - ('D', '4'): 0x14, - ('N', 'K'): 0x15, - ('S', 'Y'): 0x16, - ('E', 'B'): 0x17, - ('C', 'N'): 0x18, - ('E', 'M'): 0x19, - ('S', 'B'): 0x1a, - ('E', 'C'): 0x1b, - ('F', 'S'): 0x1c, - ('G', 'S'): 0x1d, - ('R', 'S'): 0x1e, - ('U', 'S'): 0x1f, - ('S', 'P'): 0x20, - ('N', 'b'): 0x23, - ('D', 'O'): 0x24, - ('A', 't'): 0x40, - ('<', '('): 0x5b, - ('/', '/'): 0x5c, - (')', '>'): 0x5d, - ('\'', '>'): 0x5e, - ('\'', '!'): 0x60, - ('(', '!'): 0x7b, - ('!', '!'): 0x7c, - ('!', ')'): 0x7d, - ('\'', '?'): 0x7e, - ('D', 'T'): 0x7f, - ('P', 'A'): 0x80, - ('H', 'O'): 0x81, - ('B', 'H'): 0x82, - ('N', 'H'): 0x83, - ('I', 'N'): 0x84, - ('N', 'L'): 0x85, - ('S', 'A'): 0x86, - ('E', 'S'): 0x87, - ('H', 'S'): 0x88, - ('H', 'J'): 0x89, - ('V', 'S'): 0x8a, - ('P', 'D'): 0x8b, - ('P', 'U'): 0x8c, - ('R', 'I'): 0x8d, - ('S', '2'): 0x8e, - ('S', '3'): 0x8f, - ('D', 'C'): 0x90, - ('P', '1'): 0x91, - ('P', '2'): 0x92, - ('T', 'S'): 0x93, - ('C', 'C'): 0x94, - ('M', 'W'): 0x95, - ('S', 'G'): 0x96, - ('E', 'G'): 0x97, - ('S', 'S'): 0x98, - ('G', 'C'): 0x99, - ('S', 'C'): 0x9a, - ('C', 'I'): 0x9b, - ('S', 'T'): 0x9c, - ('O', 'C'): 0x9d, - ('P', 'M'): 0x9e, - ('A', 'C'): 0x9f, - ('N', 'S'): 0xa0, - ('!', 'I'): 0xa1, - ('C', 't'): 0xa2, - ('P', 'd'): 0xa3, - ('C', 'u'): 0xa4, - ('Y', 'e'): 0xa5, - ('B', 'B'): 0xa6, - ('S', 'E'): 0xa7, - ('\'', ':'): 0xa8, - ('C', 'o'): 0xa9, - ('-', 'a'): 0xaa, - ('<', '<'): 0xab, - ('N', 'O'): 0xac, - ('-', '-'): 0xad, - ('R', 'g'): 0xae, - ('\'', 'm'): 0xaf, - ('D', 'G'): 0xb0, - ('+', '-'): 0xb1, - ('2', 'S'): 0xb2, - ('3', 'S'): 0xb3, - ('\'', '\''): 0xb4, - ('M', 'y'): 0xb5, - ('P', 'I'): 0xb6, - ('.', 'M'): 0xb7, - ('\'', ','): 0xb8, - ('1', 'S'): 0xb9, - ('-', 'o'): 0xba, - ('>', '>'): 0xbb, - ('1', '4'): 0xbc, - ('1', '2'): 0xbd, - ('3', '4'): 0xbe, - ('?', 'I'): 0xbf, - ('A', '!'): 0xc0, - ('A', '\''): 0xc1, - ('A', '>'): 0xc2, - ('A', '?'): 0xc3, - ('A', ':'): 0xc4, - ('A', 'A'): 0xc5, - ('A', 'E'): 0xc6, - ('C', ','): 0xc7, - ('E', '!'): 0xc8, - ('E', '\''): 0xc9, - ('E', '>'): 0xca, - ('E', ':'): 0xcb, - ('I', '!'): 0xcc, - ('I', '\''): 0xcd, - ('I', '>'): 0xce, - ('I', ':'): 0xcf, - ('D', '-'): 0xd0, - ('N', '?'): 0xd1, - ('O', '!'): 0xd2, - ('O', '\''): 0xd3, - ('O', '>'): 0xd4, - ('O', '?'): 0xd5, - ('O', ':'): 0xd6, - ('*', 'X'): 0xd7, - ('O', '/'): 0xd8, - ('U', '!'): 0xd9, - ('U', '\''): 0xda, - ('U', '>'): 0xdb, - ('U', ':'): 0xdc, - ('Y', '\''): 0xdd, - ('T', 'H'): 0xde, - ('s', 's'): 0xdf, - ('a', '!'): 0xe0, - ('a', '\''): 0xe1, - ('a', '>'): 0xe2, - ('a', '?'): 0xe3, - ('a', ':'): 0xe4, - ('a', 'a'): 0xe5, - ('a', 'e'): 0xe6, - ('c', ','): 0xe7, - ('e', '!'): 0xe8, - ('e', '\''): 0xe9, - ('e', '>'): 0xea, - ('e', ':'): 0xeb, - ('i', '!'): 0xec, - ('i', '\''): 0xed, - ('i', '>'): 0xee, - ('i', ':'): 0xef, - ('d', '-'): 0xf0, - ('n', '?'): 0xf1, - ('o', '!'): 0xf2, - ('o', '\''): 0xf3, - ('o', '>'): 0xf4, - ('o', '?'): 0xf5, - ('o', ':'): 0xf6, - ('-', ':'): 0xf7, - ('o', '/'): 0xf8, - ('u', '!'): 0xf9, - ('u', '\''): 0xfa, - ('u', '>'): 0xfb, - ('u', ':'): 0xfc, - ('y', '\''): 0xfd, - ('t', 'h'): 0xfe, - ('y', ':'): 0xff, - - ('A', '-'): 0x0100, - ('a', '-'): 0x0101, - ('A', '('): 0x0102, - ('a', '('): 0x0103, - ('A', ';'): 0x0104, - ('a', ';'): 0x0105, - ('C', '\''): 0x0106, - ('c', '\''): 0x0107, - ('C', '>'): 0x0108, - ('c', '>'): 0x0109, - ('C', '.'): 0x010a, - ('c', '.'): 0x010b, - ('C', '<'): 0x010c, - ('c', '<'): 0x010d, - ('D', '<'): 0x010e, - ('d', '<'): 0x010f, - ('D', '/'): 0x0110, - ('d', '/'): 0x0111, - ('E', '-'): 0x0112, - ('e', '-'): 0x0113, - ('E', '('): 0x0114, - ('e', '('): 0x0115, - ('E', '.'): 0x0116, - ('e', '.'): 0x0117, - ('E', ';'): 0x0118, - ('e', ';'): 0x0119, - ('E', '<'): 0x011a, - ('e', '<'): 0x011b, - ('G', '>'): 0x011c, - ('g', '>'): 0x011d, - ('G', '('): 0x011e, - ('g', '('): 0x011f, - ('G', '.'): 0x0120, - ('g', '.'): 0x0121, - ('G', ','): 0x0122, - ('g', ','): 0x0123, - ('H', '>'): 0x0124, - ('h', '>'): 0x0125, - ('H', '/'): 0x0126, - ('h', '/'): 0x0127, - ('I', '?'): 0x0128, - ('i', '?'): 0x0129, - ('I', '-'): 0x012a, - ('i', '-'): 0x012b, - ('I', '('): 0x012c, - ('i', '('): 0x012d, - ('I', ';'): 0x012e, - ('i', ';'): 0x012f, - ('I', '.'): 0x0130, - ('i', '.'): 0x0131, - ('I', 'J'): 0x0132, - ('i', 'j'): 0x0133, - ('J', '>'): 0x0134, - ('j', '>'): 0x0135, - ('K', ','): 0x0136, - ('k', ','): 0x0137, - ('k', 'k'): 0x0138, - ('L', '\''): 0x0139, - ('l', '\''): 0x013a, - ('L', ','): 0x013b, - ('l', ','): 0x013c, - ('L', '<'): 0x013d, - ('l', '<'): 0x013e, - ('L', '.'): 0x013f, - ('l', '.'): 0x0140, - ('L', '/'): 0x0141, - ('l', '/'): 0x0142, - ('N', '\''): 0x0143, - ('n', '\''): 0x0144, - ('N', ','): 0x0145, - ('n', ','): 0x0146, - ('N', '<'): 0x0147, - ('n', '<'): 0x0148, - ('\'', 'n'): 0x0149, - ('N', 'G'): 0x014a, - ('n', 'g'): 0x014b, - ('O', '-'): 0x014c, - ('o', '-'): 0x014d, - ('O', '('): 0x014e, - ('o', '('): 0x014f, - ('O', '"'): 0x0150, - ('o', '"'): 0x0151, - ('O', 'E'): 0x0152, - ('o', 'e'): 0x0153, - ('R', '\''): 0x0154, - ('r', '\''): 0x0155, - ('R', ','): 0x0156, - ('r', ','): 0x0157, - ('R', '<'): 0x0158, - ('r', '<'): 0x0159, - ('S', '\''): 0x015a, - ('s', '\''): 0x015b, - ('S', '>'): 0x015c, - ('s', '>'): 0x015d, - ('S', ','): 0x015e, - ('s', ','): 0x015f, - ('S', '<'): 0x0160, - ('s', '<'): 0x0161, - ('T', ','): 0x0162, - ('t', ','): 0x0163, - ('T', '<'): 0x0164, - ('t', '<'): 0x0165, - ('T', '/'): 0x0166, - ('t', '/'): 0x0167, - ('U', '?'): 0x0168, - ('u', '?'): 0x0169, - ('U', '-'): 0x016a, - ('u', '-'): 0x016b, - ('U', '('): 0x016c, - ('u', '('): 0x016d, - ('U', '0'): 0x016e, - ('u', '0'): 0x016f, - ('U', '"'): 0x0170, - ('u', '"'): 0x0171, - ('U', ';'): 0x0172, - ('u', ';'): 0x0173, - ('W', '>'): 0x0174, - ('w', '>'): 0x0175, - ('Y', '>'): 0x0176, - ('y', '>'): 0x0177, - ('Y', ':'): 0x0178, - ('Z', '\''): 0x0179, - ('z', '\''): 0x017a, - ('Z', '.'): 0x017b, - ('z', '.'): 0x017c, - ('Z', '<'): 0x017d, - ('z', '<'): 0x017e, - ('O', '9'): 0x01a0, - ('o', '9'): 0x01a1, - ('O', 'I'): 0x01a2, - ('o', 'i'): 0x01a3, - ('y', 'r'): 0x01a6, - ('U', '9'): 0x01af, - ('u', '9'): 0x01b0, - ('Z', '/'): 0x01b5, - ('z', '/'): 0x01b6, - ('E', 'D'): 0x01b7, - ('A', '<'): 0x01cd, - ('a', '<'): 0x01ce, - ('I', '<'): 0x01cf, - ('i', '<'): 0x01d0, - ('O', '<'): 0x01d1, - ('o', '<'): 0x01d2, - ('U', '<'): 0x01d3, - ('u', '<'): 0x01d4, - ('A', '1'): 0x01de, - ('a', '1'): 0x01df, - ('A', '7'): 0x01e0, - ('a', '7'): 0x01e1, - ('A', '3'): 0x01e2, - ('a', '3'): 0x01e3, - ('G', '/'): 0x01e4, - ('g', '/'): 0x01e5, - ('G', '<'): 0x01e6, - ('g', '<'): 0x01e7, - ('K', '<'): 0x01e8, - ('k', '<'): 0x01e9, - ('O', ';'): 0x01ea, - ('o', ';'): 0x01eb, - ('O', '1'): 0x01ec, - ('o', '1'): 0x01ed, - ('E', 'Z'): 0x01ee, - ('e', 'z'): 0x01ef, - ('j', '<'): 0x01f0, - ('G', '\''): 0x01f4, - ('g', '\''): 0x01f5, - (';', 'S'): 0x02bf, - ('\'', '<'): 0x02c7, - ('\'', '('): 0x02d8, - ('\'', '.'): 0x02d9, - ('\'', '0'): 0x02da, - ('\'', ';'): 0x02db, - ('\'', '"'): 0x02dd, - ('A', '%'): 0x0386, - ('E', '%'): 0x0388, - ('Y', '%'): 0x0389, - ('I', '%'): 0x038a, - ('O', '%'): 0x038c, - ('U', '%'): 0x038e, - ('W', '%'): 0x038f, - ('i', '3'): 0x0390, - ('A', '*'): 0x0391, - ('B', '*'): 0x0392, - ('G', '*'): 0x0393, - ('D', '*'): 0x0394, - ('E', '*'): 0x0395, - ('Z', '*'): 0x0396, - ('Y', '*'): 0x0397, - ('H', '*'): 0x0398, - ('I', '*'): 0x0399, - ('K', '*'): 0x039a, - ('L', '*'): 0x039b, - ('M', '*'): 0x039c, - ('N', '*'): 0x039d, - ('C', '*'): 0x039e, - ('O', '*'): 0x039f, - ('P', '*'): 0x03a0, - ('R', '*'): 0x03a1, - ('S', '*'): 0x03a3, - ('T', '*'): 0x03a4, - ('U', '*'): 0x03a5, - ('F', '*'): 0x03a6, - ('X', '*'): 0x03a7, - ('Q', '*'): 0x03a8, - ('W', '*'): 0x03a9, - ('J', '*'): 0x03aa, - ('V', '*'): 0x03ab, - ('a', '%'): 0x03ac, - ('e', '%'): 0x03ad, - ('y', '%'): 0x03ae, - ('i', '%'): 0x03af, - ('u', '3'): 0x03b0, - ('a', '*'): 0x03b1, - ('b', '*'): 0x03b2, - ('g', '*'): 0x03b3, - ('d', '*'): 0x03b4, - ('e', '*'): 0x03b5, - ('z', '*'): 0x03b6, - ('y', '*'): 0x03b7, - ('h', '*'): 0x03b8, - ('i', '*'): 0x03b9, - ('k', '*'): 0x03ba, - ('l', '*'): 0x03bb, - ('m', '*'): 0x03bc, - ('n', '*'): 0x03bd, - ('c', '*'): 0x03be, - ('o', '*'): 0x03bf, - ('p', '*'): 0x03c0, - ('r', '*'): 0x03c1, - ('*', 's'): 0x03c2, - ('s', '*'): 0x03c3, - ('t', '*'): 0x03c4, - ('u', '*'): 0x03c5, - ('f', '*'): 0x03c6, - ('x', '*'): 0x03c7, - ('q', '*'): 0x03c8, - ('w', '*'): 0x03c9, - ('j', '*'): 0x03ca, - ('v', '*'): 0x03cb, - ('o', '%'): 0x03cc, - ('u', '%'): 0x03cd, - ('w', '%'): 0x03ce, - ('\'', 'G'): 0x03d8, - (',', 'G'): 0x03d9, - ('T', '3'): 0x03da, - ('t', '3'): 0x03db, - ('M', '3'): 0x03dc, - ('m', '3'): 0x03dd, - ('K', '3'): 0x03de, - ('k', '3'): 0x03df, - ('P', '3'): 0x03e0, - ('p', '3'): 0x03e1, - ('\'', '%'): 0x03f4, - ('j', '3'): 0x03f5, - ('I', 'O'): 0x0401, - ('D', '%'): 0x0402, - ('G', '%'): 0x0403, - ('I', 'E'): 0x0404, - ('D', 'S'): 0x0405, - ('I', 'I'): 0x0406, - ('Y', 'I'): 0x0407, - ('J', '%'): 0x0408, - ('L', 'J'): 0x0409, - ('N', 'J'): 0x040a, - ('T', 's'): 0x040b, - ('K', 'J'): 0x040c, - ('V', '%'): 0x040e, - ('D', 'Z'): 0x040f, - ('A', '='): 0x0410, - ('B', '='): 0x0411, - ('V', '='): 0x0412, - ('G', '='): 0x0413, - ('D', '='): 0x0414, - ('E', '='): 0x0415, - ('Z', '%'): 0x0416, - ('Z', '='): 0x0417, - ('I', '='): 0x0418, - ('J', '='): 0x0419, - ('K', '='): 0x041a, - ('L', '='): 0x041b, - ('M', '='): 0x041c, - ('N', '='): 0x041d, - ('O', '='): 0x041e, - ('P', '='): 0x041f, - ('R', '='): 0x0420, - ('S', '='): 0x0421, - ('T', '='): 0x0422, - ('U', '='): 0x0423, - ('F', '='): 0x0424, - ('H', '='): 0x0425, - ('C', '='): 0x0426, - ('C', '%'): 0x0427, - ('S', '%'): 0x0428, - ('S', 'c'): 0x0429, - ('=', '"'): 0x042a, - ('Y', '='): 0x042b, - ('%', '"'): 0x042c, - ('J', 'E'): 0x042d, - ('J', 'U'): 0x042e, - ('J', 'A'): 0x042f, - ('a', '='): 0x0430, - ('b', '='): 0x0431, - ('v', '='): 0x0432, - ('g', '='): 0x0433, - ('d', '='): 0x0434, - ('e', '='): 0x0435, - ('z', '%'): 0x0436, - ('z', '='): 0x0437, - ('i', '='): 0x0438, - ('j', '='): 0x0439, - ('k', '='): 0x043a, - ('l', '='): 0x043b, - ('m', '='): 0x043c, - ('n', '='): 0x043d, - ('o', '='): 0x043e, - ('p', '='): 0x043f, - ('r', '='): 0x0440, - ('s', '='): 0x0441, - ('t', '='): 0x0442, - ('u', '='): 0x0443, - ('f', '='): 0x0444, - ('h', '='): 0x0445, - ('c', '='): 0x0446, - ('c', '%'): 0x0447, - ('s', '%'): 0x0448, - ('s', 'c'): 0x0449, - ('=', '\''): 0x044a, - ('y', '='): 0x044b, - ('%', '\''): 0x044c, - ('j', 'e'): 0x044d, - ('j', 'u'): 0x044e, - ('j', 'a'): 0x044f, - ('i', 'o'): 0x0451, - ('d', '%'): 0x0452, - ('g', '%'): 0x0453, - ('i', 'e'): 0x0454, - ('d', 's'): 0x0455, - ('i', 'i'): 0x0456, - ('y', 'i'): 0x0457, - ('j', '%'): 0x0458, - ('l', 'j'): 0x0459, - ('n', 'j'): 0x045a, - ('t', 's'): 0x045b, - ('k', 'j'): 0x045c, - ('v', '%'): 0x045e, - ('d', 'z'): 0x045f, - ('Y', '3'): 0x0462, - ('y', '3'): 0x0463, - ('O', '3'): 0x046a, - ('o', '3'): 0x046b, - ('F', '3'): 0x0472, - ('f', '3'): 0x0473, - ('V', '3'): 0x0474, - ('v', '3'): 0x0475, - ('C', '3'): 0x0480, - ('c', '3'): 0x0481, - ('G', '3'): 0x0490, - ('g', '3'): 0x0491, - ('A', '+'): 0x05d0, - ('B', '+'): 0x05d1, - ('G', '+'): 0x05d2, - ('D', '+'): 0x05d3, - ('H', '+'): 0x05d4, - ('W', '+'): 0x05d5, - ('Z', '+'): 0x05d6, - ('X', '+'): 0x05d7, - ('T', 'j'): 0x05d8, - ('J', '+'): 0x05d9, - ('K', '%'): 0x05da, - ('K', '+'): 0x05db, - ('L', '+'): 0x05dc, - ('M', '%'): 0x05dd, - ('M', '+'): 0x05de, - ('N', '%'): 0x05df, - ('N', '+'): 0x05e0, - ('S', '+'): 0x05e1, - ('E', '+'): 0x05e2, - ('P', '%'): 0x05e3, - ('P', '+'): 0x05e4, - ('Z', 'j'): 0x05e5, - ('Z', 'J'): 0x05e6, - ('Q', '+'): 0x05e7, - ('R', '+'): 0x05e8, - ('S', 'h'): 0x05e9, - ('T', '+'): 0x05ea, - (',', '+'): 0x060c, - (';', '+'): 0x061b, - ('?', '+'): 0x061f, - ('H', '\''): 0x0621, - ('a', 'M'): 0x0622, - ('a', 'H'): 0x0623, - ('w', 'H'): 0x0624, - ('a', 'h'): 0x0625, - ('y', 'H'): 0x0626, - ('a', '+'): 0x0627, - ('b', '+'): 0x0628, - ('t', 'm'): 0x0629, - ('t', '+'): 0x062a, - ('t', 'k'): 0x062b, - ('g', '+'): 0x062c, - ('h', 'k'): 0x062d, - ('x', '+'): 0x062e, - ('d', '+'): 0x062f, - ('d', 'k'): 0x0630, - ('r', '+'): 0x0631, - ('z', '+'): 0x0632, - ('s', '+'): 0x0633, - ('s', 'n'): 0x0634, - ('c', '+'): 0x0635, - ('d', 'd'): 0x0636, - ('t', 'j'): 0x0637, - ('z', 'H'): 0x0638, - ('e', '+'): 0x0639, - ('i', '+'): 0x063a, - ('+', '+'): 0x0640, - ('f', '+'): 0x0641, - ('q', '+'): 0x0642, - ('k', '+'): 0x0643, - ('l', '+'): 0x0644, - ('m', '+'): 0x0645, - ('n', '+'): 0x0646, - ('h', '+'): 0x0647, - ('w', '+'): 0x0648, - ('j', '+'): 0x0649, - ('y', '+'): 0x064a, - (':', '+'): 0x064b, - ('"', '+'): 0x064c, - ('=', '+'): 0x064d, - ('/', '+'): 0x064e, - ('\'', '+'): 0x064f, - ('1', '+'): 0x0650, - ('3', '+'): 0x0651, - ('0', '+'): 0x0652, - ('a', 'S'): 0x0670, - ('p', '+'): 0x067e, - ('v', '+'): 0x06a4, - ('g', 'f'): 0x06af, - ('0', 'a'): 0x06f0, - ('1', 'a'): 0x06f1, - ('2', 'a'): 0x06f2, - ('3', 'a'): 0x06f3, - ('4', 'a'): 0x06f4, - ('5', 'a'): 0x06f5, - ('6', 'a'): 0x06f6, - ('7', 'a'): 0x06f7, - ('8', 'a'): 0x06f8, - ('9', 'a'): 0x06f9, - ('B', '.'): 0x1e02, - ('b', '.'): 0x1e03, - ('B', '_'): 0x1e06, - ('b', '_'): 0x1e07, - ('D', '.'): 0x1e0a, - ('d', '.'): 0x1e0b, - ('D', '_'): 0x1e0e, - ('d', '_'): 0x1e0f, - ('D', ','): 0x1e10, - ('d', ','): 0x1e11, - ('F', '.'): 0x1e1e, - ('f', '.'): 0x1e1f, - ('G', '-'): 0x1e20, - ('g', '-'): 0x1e21, - ('H', '.'): 0x1e22, - ('h', '.'): 0x1e23, - ('H', ':'): 0x1e26, - ('h', ':'): 0x1e27, - ('H', ','): 0x1e28, - ('h', ','): 0x1e29, - ('K', '\''): 0x1e30, - ('k', '\''): 0x1e31, - ('K', '_'): 0x1e34, - ('k', '_'): 0x1e35, - ('L', '_'): 0x1e3a, - ('l', '_'): 0x1e3b, - ('M', '\''): 0x1e3e, - ('m', '\''): 0x1e3f, - ('M', '.'): 0x1e40, - ('m', '.'): 0x1e41, - ('N', '.'): 0x1e44, - ('n', '.'): 0x1e45, - ('N', '_'): 0x1e48, - ('n', '_'): 0x1e49, - ('P', '\''): 0x1e54, - ('p', '\''): 0x1e55, - ('P', '.'): 0x1e56, - ('p', '.'): 0x1e57, - ('R', '.'): 0x1e58, - ('r', '.'): 0x1e59, - ('R', '_'): 0x1e5e, - ('r', '_'): 0x1e5f, - ('S', '.'): 0x1e60, - ('s', '.'): 0x1e61, - ('T', '.'): 0x1e6a, - ('t', '.'): 0x1e6b, - ('T', '_'): 0x1e6e, - ('t', '_'): 0x1e6f, - ('V', '?'): 0x1e7c, - ('v', '?'): 0x1e7d, - ('W', '!'): 0x1e80, - ('w', '!'): 0x1e81, - ('W', '\''): 0x1e82, - ('w', '\''): 0x1e83, - ('W', ':'): 0x1e84, - ('w', ':'): 0x1e85, - ('W', '.'): 0x1e86, - ('w', '.'): 0x1e87, - ('X', '.'): 0x1e8a, - ('x', '.'): 0x1e8b, - ('X', ':'): 0x1e8c, - ('x', ':'): 0x1e8d, - ('Y', '.'): 0x1e8e, - ('y', '.'): 0x1e8f, - ('Z', '>'): 0x1e90, - ('z', '>'): 0x1e91, - ('Z', '_'): 0x1e94, - ('z', '_'): 0x1e95, - ('h', '_'): 0x1e96, - ('t', ':'): 0x1e97, - ('w', '0'): 0x1e98, - ('y', '0'): 0x1e99, - ('A', '2'): 0x1ea2, - ('a', '2'): 0x1ea3, - ('E', '2'): 0x1eba, - ('e', '2'): 0x1ebb, - ('E', '?'): 0x1ebc, - ('e', '?'): 0x1ebd, - ('I', '2'): 0x1ec8, - ('i', '2'): 0x1ec9, - ('O', '2'): 0x1ece, - ('o', '2'): 0x1ecf, - ('U', '2'): 0x1ee6, - ('u', '2'): 0x1ee7, - ('Y', '!'): 0x1ef2, - ('y', '!'): 0x1ef3, - ('Y', '2'): 0x1ef6, - ('y', '2'): 0x1ef7, - ('Y', '?'): 0x1ef8, - ('y', '?'): 0x1ef9, - (';', '\''): 0x1f00, - (',', '\''): 0x1f01, - (';', '!'): 0x1f02, - (',', '!'): 0x1f03, - ('?', ';'): 0x1f04, - ('?', ','): 0x1f05, - ('!', ':'): 0x1f06, - ('?', ':'): 0x1f07, - ('1', 'N'): 0x2002, - ('1', 'M'): 0x2003, - ('3', 'M'): 0x2004, - ('4', 'M'): 0x2005, - ('6', 'M'): 0x2006, - ('1', 'T'): 0x2009, - ('1', 'H'): 0x200a, - ('-', '1'): 0x2010, - ('-', 'N'): 0x2013, - ('-', 'M'): 0x2014, - ('-', '3'): 0x2015, - ('!', '2'): 0x2016, - ('=', '2'): 0x2017, - ('\'', '6'): 0x2018, - ('\'', '9'): 0x2019, - ('.', '9'): 0x201a, - ('9', '\''): 0x201b, - ('"', '6'): 0x201c, - ('"', '9'): 0x201d, - (':', '9'): 0x201e, - ('9', '"'): 0x201f, - ('/', '-'): 0x2020, - ('/', '='): 0x2021, - ('.', '.'): 0x2025, - ('%', '0'): 0x2030, - ('1', '\''): 0x2032, - ('2', '\''): 0x2033, - ('3', '\''): 0x2034, - ('1', '"'): 0x2035, - ('2', '"'): 0x2036, - ('3', '"'): 0x2037, - ('C', 'a'): 0x2038, - ('<', '1'): 0x2039, - ('>', '1'): 0x203a, - (':', 'X'): 0x203b, - ('\'', '-'): 0x203e, - ('/', 'f'): 0x2044, - ('0', 'S'): 0x2070, - ('4', 'S'): 0x2074, - ('5', 'S'): 0x2075, - ('6', 'S'): 0x2076, - ('7', 'S'): 0x2077, - ('8', 'S'): 0x2078, - ('9', 'S'): 0x2079, - ('+', 'S'): 0x207a, - ('-', 'S'): 0x207b, - ('=', 'S'): 0x207c, - ('(', 'S'): 0x207d, - (')', 'S'): 0x207e, - ('n', 'S'): 0x207f, - ('0', 's'): 0x2080, - ('1', 's'): 0x2081, - ('2', 's'): 0x2082, - ('3', 's'): 0x2083, - ('4', 's'): 0x2084, - ('5', 's'): 0x2085, - ('6', 's'): 0x2086, - ('7', 's'): 0x2087, - ('8', 's'): 0x2088, - ('9', 's'): 0x2089, - ('+', 's'): 0x208a, - ('-', 's'): 0x208b, - ('=', 's'): 0x208c, - ('(', 's'): 0x208d, - (')', 's'): 0x208e, - ('L', 'i'): 0x20a4, - ('P', 't'): 0x20a7, - ('W', '='): 0x20a9, - ('=', 'e'): 0x20ac, # euro - ('E', 'u'): 0x20ac, # euro - ('=', 'R'): 0x20bd, # rouble - ('=', 'P'): 0x20bd, # rouble - ('o', 'C'): 0x2103, - ('c', 'o'): 0x2105, - ('o', 'F'): 0x2109, - ('N', '0'): 0x2116, - ('P', 'O'): 0x2117, - ('R', 'x'): 0x211e, - ('S', 'M'): 0x2120, - ('T', 'M'): 0x2122, - ('O', 'm'): 0x2126, - ('A', 'O'): 0x212b, - ('1', '3'): 0x2153, - ('2', '3'): 0x2154, - ('1', '5'): 0x2155, - ('2', '5'): 0x2156, - ('3', '5'): 0x2157, - ('4', '5'): 0x2158, - ('1', '6'): 0x2159, - ('5', '6'): 0x215a, - ('1', '8'): 0x215b, - ('3', '8'): 0x215c, - ('5', '8'): 0x215d, - ('7', '8'): 0x215e, - ('1', 'R'): 0x2160, - ('2', 'R'): 0x2161, - ('3', 'R'): 0x2162, - ('4', 'R'): 0x2163, - ('5', 'R'): 0x2164, - ('6', 'R'): 0x2165, - ('7', 'R'): 0x2166, - ('8', 'R'): 0x2167, - ('9', 'R'): 0x2168, - ('a', 'R'): 0x2169, - ('b', 'R'): 0x216a, - ('c', 'R'): 0x216b, - ('1', 'r'): 0x2170, - ('2', 'r'): 0x2171, - ('3', 'r'): 0x2172, - ('4', 'r'): 0x2173, - ('5', 'r'): 0x2174, - ('6', 'r'): 0x2175, - ('7', 'r'): 0x2176, - ('8', 'r'): 0x2177, - ('9', 'r'): 0x2178, - ('a', 'r'): 0x2179, - ('b', 'r'): 0x217a, - ('c', 'r'): 0x217b, - ('<', '-'): 0x2190, - ('-', '!'): 0x2191, - ('-', '>'): 0x2192, - ('-', 'v'): 0x2193, - ('<', '>'): 0x2194, - ('U', 'D'): 0x2195, - ('<', '='): 0x21d0, - ('=', '>'): 0x21d2, - ('=', '='): 0x21d4, - ('F', 'A'): 0x2200, - ('d', 'P'): 0x2202, - ('T', 'E'): 0x2203, - ('/', '0'): 0x2205, - ('D', 'E'): 0x2206, - ('N', 'B'): 0x2207, - ('(', '-'): 0x2208, - ('-', ')'): 0x220b, - ('*', 'P'): 0x220f, - ('+', 'Z'): 0x2211, - ('-', '2'): 0x2212, - ('-', '+'): 0x2213, - ('*', '-'): 0x2217, - ('O', 'b'): 0x2218, - ('S', 'b'): 0x2219, - ('R', 'T'): 0x221a, - ('0', '('): 0x221d, - ('0', '0'): 0x221e, - ('-', 'L'): 0x221f, - ('-', 'V'): 0x2220, - ('P', 'P'): 0x2225, - ('A', 'N'): 0x2227, - ('O', 'R'): 0x2228, - ('(', 'U'): 0x2229, - (')', 'U'): 0x222a, - ('I', 'n'): 0x222b, - ('D', 'I'): 0x222c, - ('I', 'o'): 0x222e, - ('.', ':'): 0x2234, - (':', '.'): 0x2235, - (':', 'R'): 0x2236, - (':', ':'): 0x2237, - ('?', '1'): 0x223c, - ('C', 'G'): 0x223e, - ('?', '-'): 0x2243, - ('?', '='): 0x2245, - ('?', '2'): 0x2248, - ('=', '?'): 0x224c, - ('H', 'I'): 0x2253, - ('!', '='): 0x2260, - ('=', '3'): 0x2261, - ('=', '<'): 0x2264, - ('>', '='): 0x2265, - ('<', '*'): 0x226a, - ('*', '>'): 0x226b, - ('!', '<'): 0x226e, - ('!', '>'): 0x226f, - ('(', 'C'): 0x2282, - (')', 'C'): 0x2283, - ('(', '_'): 0x2286, - (')', '_'): 0x2287, - ('0', '.'): 0x2299, - ('0', '2'): 0x229a, - ('-', 'T'): 0x22a5, - ('.', 'P'): 0x22c5, - (':', '3'): 0x22ee, - ('.', '3'): 0x22ef, - ('E', 'h'): 0x2302, - ('<', '7'): 0x2308, - ('>', '7'): 0x2309, - ('7', '<'): 0x230a, - ('7', '>'): 0x230b, - ('N', 'I'): 0x2310, - ('(', 'A'): 0x2312, - ('T', 'R'): 0x2315, - ('I', 'u'): 0x2320, - ('I', 'l'): 0x2321, - ('<', '/'): 0x2329, - ('/', '>'): 0x232a, - ('V', 's'): 0x2423, - ('1', 'h'): 0x2440, - ('3', 'h'): 0x2441, - ('2', 'h'): 0x2442, - ('4', 'h'): 0x2443, - ('1', 'j'): 0x2446, - ('2', 'j'): 0x2447, - ('3', 'j'): 0x2448, - ('4', 'j'): 0x2449, - ('1', '.'): 0x2488, - ('2', '.'): 0x2489, - ('3', '.'): 0x248a, - ('4', '.'): 0x248b, - ('5', '.'): 0x248c, - ('6', '.'): 0x248d, - ('7', '.'): 0x248e, - ('8', '.'): 0x248f, - ('9', '.'): 0x2490, - ('h', 'h'): 0x2500, - ('H', 'H'): 0x2501, - ('v', 'v'): 0x2502, - ('V', 'V'): 0x2503, - ('3', '-'): 0x2504, - ('3', '_'): 0x2505, - ('3', '!'): 0x2506, - ('3', '/'): 0x2507, - ('4', '-'): 0x2508, - ('4', '_'): 0x2509, - ('4', '!'): 0x250a, - ('4', '/'): 0x250b, - ('d', 'r'): 0x250c, - ('d', 'R'): 0x250d, - ('D', 'r'): 0x250e, - ('D', 'R'): 0x250f, - ('d', 'l'): 0x2510, - ('d', 'L'): 0x2511, - ('D', 'l'): 0x2512, - ('L', 'D'): 0x2513, - ('u', 'r'): 0x2514, - ('u', 'R'): 0x2515, - ('U', 'r'): 0x2516, - ('U', 'R'): 0x2517, - ('u', 'l'): 0x2518, - ('u', 'L'): 0x2519, - ('U', 'l'): 0x251a, - ('U', 'L'): 0x251b, - ('v', 'r'): 0x251c, - ('v', 'R'): 0x251d, - ('V', 'r'): 0x2520, - ('V', 'R'): 0x2523, - ('v', 'l'): 0x2524, - ('v', 'L'): 0x2525, - ('V', 'l'): 0x2528, - ('V', 'L'): 0x252b, - ('d', 'h'): 0x252c, - ('d', 'H'): 0x252f, - ('D', 'h'): 0x2530, - ('D', 'H'): 0x2533, - ('u', 'h'): 0x2534, - ('u', 'H'): 0x2537, - ('U', 'h'): 0x2538, - ('U', 'H'): 0x253b, - ('v', 'h'): 0x253c, - ('v', 'H'): 0x253f, - ('V', 'h'): 0x2542, - ('V', 'H'): 0x254b, - ('F', 'D'): 0x2571, - ('B', 'D'): 0x2572, - ('T', 'B'): 0x2580, - ('L', 'B'): 0x2584, - ('F', 'B'): 0x2588, - ('l', 'B'): 0x258c, - ('R', 'B'): 0x2590, - ('.', 'S'): 0x2591, - (':', 'S'): 0x2592, - ('?', 'S'): 0x2593, - ('f', 'S'): 0x25a0, - ('O', 'S'): 0x25a1, - ('R', 'O'): 0x25a2, - ('R', 'r'): 0x25a3, - ('R', 'F'): 0x25a4, - ('R', 'Y'): 0x25a5, - ('R', 'H'): 0x25a6, - ('R', 'Z'): 0x25a7, - ('R', 'K'): 0x25a8, - ('R', 'X'): 0x25a9, - ('s', 'B'): 0x25aa, - ('S', 'R'): 0x25ac, - ('O', 'r'): 0x25ad, - ('U', 'T'): 0x25b2, - ('u', 'T'): 0x25b3, - ('P', 'R'): 0x25b6, - ('T', 'r'): 0x25b7, - ('D', 't'): 0x25bc, - ('d', 'T'): 0x25bd, - ('P', 'L'): 0x25c0, - ('T', 'l'): 0x25c1, - ('D', 'b'): 0x25c6, - ('D', 'w'): 0x25c7, - ('L', 'Z'): 0x25ca, - ('0', 'm'): 0x25cb, - ('0', 'o'): 0x25ce, - ('0', 'M'): 0x25cf, - ('0', 'L'): 0x25d0, - ('0', 'R'): 0x25d1, - ('S', 'n'): 0x25d8, - ('I', 'c'): 0x25d9, - ('F', 'd'): 0x25e2, - ('B', 'd'): 0x25e3, - ('*', '2'): 0x2605, - ('*', '1'): 0x2606, - ('<', 'H'): 0x261c, - ('>', 'H'): 0x261e, - ('0', 'u'): 0x263a, - ('0', 'U'): 0x263b, - ('S', 'U'): 0x263c, - ('F', 'm'): 0x2640, - ('M', 'l'): 0x2642, - ('c', 'S'): 0x2660, - ('c', 'H'): 0x2661, - ('c', 'D'): 0x2662, - ('c', 'C'): 0x2663, - ('M', 'd'): 0x2669, - ('M', '8'): 0x266a, - ('M', '2'): 0x266b, - ('M', 'b'): 0x266d, - ('M', 'x'): 0x266e, - ('M', 'X'): 0x266f, - ('O', 'K'): 0x2713, - ('X', 'X'): 0x2717, - ('-', 'X'): 0x2720, - ('I', 'S'): 0x3000, - (',', '_'): 0x3001, - ('.', '_'): 0x3002, - ('+', '"'): 0x3003, - ('+', '_'): 0x3004, - ('*', '_'): 0x3005, - (';', '_'): 0x3006, - ('0', '_'): 0x3007, - ('<', '+'): 0x300a, - ('>', '+'): 0x300b, - ('<', '\''): 0x300c, - ('>', '\''): 0x300d, - ('<', '"'): 0x300e, - ('>', '"'): 0x300f, - ('(', '"'): 0x3010, - (')', '"'): 0x3011, - ('=', 'T'): 0x3012, - ('=', '_'): 0x3013, - ('(', '\''): 0x3014, - (')', '\''): 0x3015, - ('(', 'I'): 0x3016, - (')', 'I'): 0x3017, - ('-', '?'): 0x301c, - ('A', '5'): 0x3041, - ('a', '5'): 0x3042, - ('I', '5'): 0x3043, - ('i', '5'): 0x3044, - ('U', '5'): 0x3045, - ('u', '5'): 0x3046, - ('E', '5'): 0x3047, - ('e', '5'): 0x3048, - ('O', '5'): 0x3049, - ('o', '5'): 0x304a, - ('k', 'a'): 0x304b, - ('g', 'a'): 0x304c, - ('k', 'i'): 0x304d, - ('g', 'i'): 0x304e, - ('k', 'u'): 0x304f, - ('g', 'u'): 0x3050, - ('k', 'e'): 0x3051, - ('g', 'e'): 0x3052, - ('k', 'o'): 0x3053, - ('g', 'o'): 0x3054, - ('s', 'a'): 0x3055, - ('z', 'a'): 0x3056, - ('s', 'i'): 0x3057, - ('z', 'i'): 0x3058, - ('s', 'u'): 0x3059, - ('z', 'u'): 0x305a, - ('s', 'e'): 0x305b, - ('z', 'e'): 0x305c, - ('s', 'o'): 0x305d, - ('z', 'o'): 0x305e, - ('t', 'a'): 0x305f, - ('d', 'a'): 0x3060, - ('t', 'i'): 0x3061, - ('d', 'i'): 0x3062, - ('t', 'U'): 0x3063, - ('t', 'u'): 0x3064, - ('d', 'u'): 0x3065, - ('t', 'e'): 0x3066, - ('d', 'e'): 0x3067, - ('t', 'o'): 0x3068, - ('d', 'o'): 0x3069, - ('n', 'a'): 0x306a, - ('n', 'i'): 0x306b, - ('n', 'u'): 0x306c, - ('n', 'e'): 0x306d, - ('n', 'o'): 0x306e, - ('h', 'a'): 0x306f, - ('b', 'a'): 0x3070, - ('p', 'a'): 0x3071, - ('h', 'i'): 0x3072, - ('b', 'i'): 0x3073, - ('p', 'i'): 0x3074, - ('h', 'u'): 0x3075, - ('b', 'u'): 0x3076, - ('p', 'u'): 0x3077, - ('h', 'e'): 0x3078, - ('b', 'e'): 0x3079, - ('p', 'e'): 0x307a, - ('h', 'o'): 0x307b, - ('b', 'o'): 0x307c, - ('p', 'o'): 0x307d, - ('m', 'a'): 0x307e, - ('m', 'i'): 0x307f, - ('m', 'u'): 0x3080, - ('m', 'e'): 0x3081, - ('m', 'o'): 0x3082, - ('y', 'A'): 0x3083, - ('y', 'a'): 0x3084, - ('y', 'U'): 0x3085, - ('y', 'u'): 0x3086, - ('y', 'O'): 0x3087, - ('y', 'o'): 0x3088, - ('r', 'a'): 0x3089, - ('r', 'i'): 0x308a, - ('r', 'u'): 0x308b, - ('r', 'e'): 0x308c, - ('r', 'o'): 0x308d, - ('w', 'A'): 0x308e, - ('w', 'a'): 0x308f, - ('w', 'i'): 0x3090, - ('w', 'e'): 0x3091, - ('w', 'o'): 0x3092, - ('n', '5'): 0x3093, - ('v', 'u'): 0x3094, - ('"', '5'): 0x309b, - ('0', '5'): 0x309c, - ('*', '5'): 0x309d, - ('+', '5'): 0x309e, - ('a', '6'): 0x30a1, - ('A', '6'): 0x30a2, - ('i', '6'): 0x30a3, - ('I', '6'): 0x30a4, - ('u', '6'): 0x30a5, - ('U', '6'): 0x30a6, - ('e', '6'): 0x30a7, - ('E', '6'): 0x30a8, - ('o', '6'): 0x30a9, - ('O', '6'): 0x30aa, - ('K', 'a'): 0x30ab, - ('G', 'a'): 0x30ac, - ('K', 'i'): 0x30ad, - ('G', 'i'): 0x30ae, - ('K', 'u'): 0x30af, - ('G', 'u'): 0x30b0, - ('K', 'e'): 0x30b1, - ('G', 'e'): 0x30b2, - ('K', 'o'): 0x30b3, - ('G', 'o'): 0x30b4, - ('S', 'a'): 0x30b5, - ('Z', 'a'): 0x30b6, - ('S', 'i'): 0x30b7, - ('Z', 'i'): 0x30b8, - ('S', 'u'): 0x30b9, - ('Z', 'u'): 0x30ba, - ('S', 'e'): 0x30bb, - ('Z', 'e'): 0x30bc, - ('S', 'o'): 0x30bd, - ('Z', 'o'): 0x30be, - ('T', 'a'): 0x30bf, - ('D', 'a'): 0x30c0, - ('T', 'i'): 0x30c1, - ('D', 'i'): 0x30c2, - ('T', 'U'): 0x30c3, - ('T', 'u'): 0x30c4, - ('D', 'u'): 0x30c5, - ('T', 'e'): 0x30c6, - ('D', 'e'): 0x30c7, - ('T', 'o'): 0x30c8, - ('D', 'o'): 0x30c9, - ('N', 'a'): 0x30ca, - ('N', 'i'): 0x30cb, - ('N', 'u'): 0x30cc, - ('N', 'e'): 0x30cd, - ('N', 'o'): 0x30ce, - ('H', 'a'): 0x30cf, - ('B', 'a'): 0x30d0, - ('P', 'a'): 0x30d1, - ('H', 'i'): 0x30d2, - ('B', 'i'): 0x30d3, - ('P', 'i'): 0x30d4, - ('H', 'u'): 0x30d5, - ('B', 'u'): 0x30d6, - ('P', 'u'): 0x30d7, - ('H', 'e'): 0x30d8, - ('B', 'e'): 0x30d9, - ('P', 'e'): 0x30da, - ('H', 'o'): 0x30db, - ('B', 'o'): 0x30dc, - ('P', 'o'): 0x30dd, - ('M', 'a'): 0x30de, - ('M', 'i'): 0x30df, - ('M', 'u'): 0x30e0, - ('M', 'e'): 0x30e1, - ('M', 'o'): 0x30e2, - ('Y', 'A'): 0x30e3, - ('Y', 'a'): 0x30e4, - ('Y', 'U'): 0x30e5, - ('Y', 'u'): 0x30e6, - ('Y', 'O'): 0x30e7, - ('Y', 'o'): 0x30e8, - ('R', 'a'): 0x30e9, - ('R', 'i'): 0x30ea, - ('R', 'u'): 0x30eb, - ('R', 'e'): 0x30ec, - ('R', 'o'): 0x30ed, - ('W', 'A'): 0x30ee, - ('W', 'a'): 0x30ef, - ('W', 'i'): 0x30f0, - ('W', 'e'): 0x30f1, - ('W', 'o'): 0x30f2, - ('N', '6'): 0x30f3, - ('V', 'u'): 0x30f4, - ('K', 'A'): 0x30f5, - ('K', 'E'): 0x30f6, - ('V', 'a'): 0x30f7, - ('V', 'i'): 0x30f8, - ('V', 'e'): 0x30f9, - ('V', 'o'): 0x30fa, - ('.', '6'): 0x30fb, - ('-', '6'): 0x30fc, - ('*', '6'): 0x30fd, - ('+', '6'): 0x30fe, - ('b', '4'): 0x3105, - ('p', '4'): 0x3106, - ('m', '4'): 0x3107, - ('f', '4'): 0x3108, - ('d', '4'): 0x3109, - ('t', '4'): 0x310a, - ('n', '4'): 0x310b, - ('l', '4'): 0x310c, - ('g', '4'): 0x310d, - ('k', '4'): 0x310e, - ('h', '4'): 0x310f, - ('j', '4'): 0x3110, - ('q', '4'): 0x3111, - ('x', '4'): 0x3112, - ('z', 'h'): 0x3113, - ('c', 'h'): 0x3114, - ('s', 'h'): 0x3115, - ('r', '4'): 0x3116, - ('z', '4'): 0x3117, - ('c', '4'): 0x3118, - ('s', '4'): 0x3119, - ('a', '4'): 0x311a, - ('o', '4'): 0x311b, - ('e', '4'): 0x311c, - ('a', 'i'): 0x311e, - ('e', 'i'): 0x311f, - ('a', 'u'): 0x3120, - ('o', 'u'): 0x3121, - ('a', 'n'): 0x3122, - ('e', 'n'): 0x3123, - ('a', 'N'): 0x3124, - ('e', 'N'): 0x3125, - ('e', 'r'): 0x3126, - ('i', '4'): 0x3127, - ('u', '4'): 0x3128, - ('i', 'u'): 0x3129, - ('v', '4'): 0x312a, - ('n', 'G'): 0x312b, - ('g', 'n'): 0x312c, - ('1', 'c'): 0x3220, - ('2', 'c'): 0x3221, - ('3', 'c'): 0x3222, - ('4', 'c'): 0x3223, - ('5', 'c'): 0x3224, - ('6', 'c'): 0x3225, - ('7', 'c'): 0x3226, - ('8', 'c'): 0x3227, - ('9', 'c'): 0x3228, - - # code points 0xe000 - 0xefff excluded, they have no assigned - # characters, only used in proposals. - ('f', 'f'): 0xfb00, - ('f', 'i'): 0xfb01, - ('f', 'l'): 0xfb02, - ('f', 't'): 0xfb05, - ('s', 't'): 0xfb06, - - # Vim 5.x compatible digraphs that don't conflict with the above - ('~', '!'): 161, - ('c', '|'): 162, - ('$', '$'): 163, - ('o', 'x'): 164, # currency symbol in ISO 8859-1 - ('Y', '-'): 165, - ('|', '|'): 166, - ('c', 'O'): 169, - ('-', ','): 172, - ('-', '='): 175, - ('~', 'o'): 176, - ('2', '2'): 178, - ('3', '3'): 179, - ('p', 'p'): 182, - ('~', '.'): 183, - ('1', '1'): 185, - ('~', '?'): 191, - ('A', '`'): 192, - ('A', '^'): 194, - ('A', '~'): 195, - ('A', '"'): 196, - ('A', '@'): 197, - ('E', '`'): 200, - ('E', '^'): 202, - ('E', '"'): 203, - ('I', '`'): 204, - ('I', '^'): 206, - ('I', '"'): 207, - ('N', '~'): 209, - ('O', '`'): 210, - ('O', '^'): 212, - ('O', '~'): 213, - ('/', '\\'): 215, # multiplication symbol in ISO 8859-1 - ('U', '`'): 217, - ('U', '^'): 219, - ('I', 'p'): 222, - ('a', '`'): 224, - ('a', '^'): 226, - ('a', '~'): 227, - ('a', '"'): 228, - ('a', '@'): 229, - ('e', '`'): 232, - ('e', '^'): 234, - ('e', '"'): 235, - ('i', '`'): 236, - ('i', '^'): 238, - ('n', '~'): 241, - ('o', '`'): 242, - ('o', '^'): 244, - ('o', '~'): 245, - ('u', '`'): 249, - ('u', '^'): 251, - ('y', '"'): 255, -} +# encoding: utf-8 +from __future__ import unicode_literals +""" +Vi Digraphs. +This is a list of special characters that can be inserted in Vi insert mode by +pressing Control-K followed by to normal characters. + +Taken from Neovim and translated to Python: +https://raw.githubusercontent.com/neovim/neovim/master/src/nvim/digraph.c +""" +__all__ = ('DIGRAPHS', ) + +# digraphs for Unicode from RFC1345 +# (also work for ISO-8859-1 aka latin1) +DIGRAPHS = { + ('N', 'U'): 0x00, + ('S', 'H'): 0x01, + ('S', 'X'): 0x02, + ('E', 'X'): 0x03, + ('E', 'T'): 0x04, + ('E', 'Q'): 0x05, + ('A', 'K'): 0x06, + ('B', 'L'): 0x07, + ('B', 'S'): 0x08, + ('H', 'T'): 0x09, + ('L', 'F'): 0x0a, + ('V', 'T'): 0x0b, + ('F', 'F'): 0x0c, + ('C', 'R'): 0x0d, + ('S', 'O'): 0x0e, + ('S', 'I'): 0x0f, + ('D', 'L'): 0x10, + ('D', '1'): 0x11, + ('D', '2'): 0x12, + ('D', '3'): 0x13, + ('D', '4'): 0x14, + ('N', 'K'): 0x15, + ('S', 'Y'): 0x16, + ('E', 'B'): 0x17, + ('C', 'N'): 0x18, + ('E', 'M'): 0x19, + ('S', 'B'): 0x1a, + ('E', 'C'): 0x1b, + ('F', 'S'): 0x1c, + ('G', 'S'): 0x1d, + ('R', 'S'): 0x1e, + ('U', 'S'): 0x1f, + ('S', 'P'): 0x20, + ('N', 'b'): 0x23, + ('D', 'O'): 0x24, + ('A', 't'): 0x40, + ('<', '('): 0x5b, + ('/', '/'): 0x5c, + (')', '>'): 0x5d, + ('\'', '>'): 0x5e, + ('\'', '!'): 0x60, + ('(', '!'): 0x7b, + ('!', '!'): 0x7c, + ('!', ')'): 0x7d, + ('\'', '?'): 0x7e, + ('D', 'T'): 0x7f, + ('P', 'A'): 0x80, + ('H', 'O'): 0x81, + ('B', 'H'): 0x82, + ('N', 'H'): 0x83, + ('I', 'N'): 0x84, + ('N', 'L'): 0x85, + ('S', 'A'): 0x86, + ('E', 'S'): 0x87, + ('H', 'S'): 0x88, + ('H', 'J'): 0x89, + ('V', 'S'): 0x8a, + ('P', 'D'): 0x8b, + ('P', 'U'): 0x8c, + ('R', 'I'): 0x8d, + ('S', '2'): 0x8e, + ('S', '3'): 0x8f, + ('D', 'C'): 0x90, + ('P', '1'): 0x91, + ('P', '2'): 0x92, + ('T', 'S'): 0x93, + ('C', 'C'): 0x94, + ('M', 'W'): 0x95, + ('S', 'G'): 0x96, + ('E', 'G'): 0x97, + ('S', 'S'): 0x98, + ('G', 'C'): 0x99, + ('S', 'C'): 0x9a, + ('C', 'I'): 0x9b, + ('S', 'T'): 0x9c, + ('O', 'C'): 0x9d, + ('P', 'M'): 0x9e, + ('A', 'C'): 0x9f, + ('N', 'S'): 0xa0, + ('!', 'I'): 0xa1, + ('C', 't'): 0xa2, + ('P', 'd'): 0xa3, + ('C', 'u'): 0xa4, + ('Y', 'e'): 0xa5, + ('B', 'B'): 0xa6, + ('S', 'E'): 0xa7, + ('\'', ':'): 0xa8, + ('C', 'o'): 0xa9, + ('-', 'a'): 0xaa, + ('<', '<'): 0xab, + ('N', 'O'): 0xac, + ('-', '-'): 0xad, + ('R', 'g'): 0xae, + ('\'', 'm'): 0xaf, + ('D', 'G'): 0xb0, + ('+', '-'): 0xb1, + ('2', 'S'): 0xb2, + ('3', 'S'): 0xb3, + ('\'', '\''): 0xb4, + ('M', 'y'): 0xb5, + ('P', 'I'): 0xb6, + ('.', 'M'): 0xb7, + ('\'', ','): 0xb8, + ('1', 'S'): 0xb9, + ('-', 'o'): 0xba, + ('>', '>'): 0xbb, + ('1', '4'): 0xbc, + ('1', '2'): 0xbd, + ('3', '4'): 0xbe, + ('?', 'I'): 0xbf, + ('A', '!'): 0xc0, + ('A', '\''): 0xc1, + ('A', '>'): 0xc2, + ('A', '?'): 0xc3, + ('A', ':'): 0xc4, + ('A', 'A'): 0xc5, + ('A', 'E'): 0xc6, + ('C', ','): 0xc7, + ('E', '!'): 0xc8, + ('E', '\''): 0xc9, + ('E', '>'): 0xca, + ('E', ':'): 0xcb, + ('I', '!'): 0xcc, + ('I', '\''): 0xcd, + ('I', '>'): 0xce, + ('I', ':'): 0xcf, + ('D', '-'): 0xd0, + ('N', '?'): 0xd1, + ('O', '!'): 0xd2, + ('O', '\''): 0xd3, + ('O', '>'): 0xd4, + ('O', '?'): 0xd5, + ('O', ':'): 0xd6, + ('*', 'X'): 0xd7, + ('O', '/'): 0xd8, + ('U', '!'): 0xd9, + ('U', '\''): 0xda, + ('U', '>'): 0xdb, + ('U', ':'): 0xdc, + ('Y', '\''): 0xdd, + ('T', 'H'): 0xde, + ('s', 's'): 0xdf, + ('a', '!'): 0xe0, + ('a', '\''): 0xe1, + ('a', '>'): 0xe2, + ('a', '?'): 0xe3, + ('a', ':'): 0xe4, + ('a', 'a'): 0xe5, + ('a', 'e'): 0xe6, + ('c', ','): 0xe7, + ('e', '!'): 0xe8, + ('e', '\''): 0xe9, + ('e', '>'): 0xea, + ('e', ':'): 0xeb, + ('i', '!'): 0xec, + ('i', '\''): 0xed, + ('i', '>'): 0xee, + ('i', ':'): 0xef, + ('d', '-'): 0xf0, + ('n', '?'): 0xf1, + ('o', '!'): 0xf2, + ('o', '\''): 0xf3, + ('o', '>'): 0xf4, + ('o', '?'): 0xf5, + ('o', ':'): 0xf6, + ('-', ':'): 0xf7, + ('o', '/'): 0xf8, + ('u', '!'): 0xf9, + ('u', '\''): 0xfa, + ('u', '>'): 0xfb, + ('u', ':'): 0xfc, + ('y', '\''): 0xfd, + ('t', 'h'): 0xfe, + ('y', ':'): 0xff, + + ('A', '-'): 0x0100, + ('a', '-'): 0x0101, + ('A', '('): 0x0102, + ('a', '('): 0x0103, + ('A', ';'): 0x0104, + ('a', ';'): 0x0105, + ('C', '\''): 0x0106, + ('c', '\''): 0x0107, + ('C', '>'): 0x0108, + ('c', '>'): 0x0109, + ('C', '.'): 0x010a, + ('c', '.'): 0x010b, + ('C', '<'): 0x010c, + ('c', '<'): 0x010d, + ('D', '<'): 0x010e, + ('d', '<'): 0x010f, + ('D', '/'): 0x0110, + ('d', '/'): 0x0111, + ('E', '-'): 0x0112, + ('e', '-'): 0x0113, + ('E', '('): 0x0114, + ('e', '('): 0x0115, + ('E', '.'): 0x0116, + ('e', '.'): 0x0117, + ('E', ';'): 0x0118, + ('e', ';'): 0x0119, + ('E', '<'): 0x011a, + ('e', '<'): 0x011b, + ('G', '>'): 0x011c, + ('g', '>'): 0x011d, + ('G', '('): 0x011e, + ('g', '('): 0x011f, + ('G', '.'): 0x0120, + ('g', '.'): 0x0121, + ('G', ','): 0x0122, + ('g', ','): 0x0123, + ('H', '>'): 0x0124, + ('h', '>'): 0x0125, + ('H', '/'): 0x0126, + ('h', '/'): 0x0127, + ('I', '?'): 0x0128, + ('i', '?'): 0x0129, + ('I', '-'): 0x012a, + ('i', '-'): 0x012b, + ('I', '('): 0x012c, + ('i', '('): 0x012d, + ('I', ';'): 0x012e, + ('i', ';'): 0x012f, + ('I', '.'): 0x0130, + ('i', '.'): 0x0131, + ('I', 'J'): 0x0132, + ('i', 'j'): 0x0133, + ('J', '>'): 0x0134, + ('j', '>'): 0x0135, + ('K', ','): 0x0136, + ('k', ','): 0x0137, + ('k', 'k'): 0x0138, + ('L', '\''): 0x0139, + ('l', '\''): 0x013a, + ('L', ','): 0x013b, + ('l', ','): 0x013c, + ('L', '<'): 0x013d, + ('l', '<'): 0x013e, + ('L', '.'): 0x013f, + ('l', '.'): 0x0140, + ('L', '/'): 0x0141, + ('l', '/'): 0x0142, + ('N', '\''): 0x0143, + ('n', '\''): 0x0144, + ('N', ','): 0x0145, + ('n', ','): 0x0146, + ('N', '<'): 0x0147, + ('n', '<'): 0x0148, + ('\'', 'n'): 0x0149, + ('N', 'G'): 0x014a, + ('n', 'g'): 0x014b, + ('O', '-'): 0x014c, + ('o', '-'): 0x014d, + ('O', '('): 0x014e, + ('o', '('): 0x014f, + ('O', '"'): 0x0150, + ('o', '"'): 0x0151, + ('O', 'E'): 0x0152, + ('o', 'e'): 0x0153, + ('R', '\''): 0x0154, + ('r', '\''): 0x0155, + ('R', ','): 0x0156, + ('r', ','): 0x0157, + ('R', '<'): 0x0158, + ('r', '<'): 0x0159, + ('S', '\''): 0x015a, + ('s', '\''): 0x015b, + ('S', '>'): 0x015c, + ('s', '>'): 0x015d, + ('S', ','): 0x015e, + ('s', ','): 0x015f, + ('S', '<'): 0x0160, + ('s', '<'): 0x0161, + ('T', ','): 0x0162, + ('t', ','): 0x0163, + ('T', '<'): 0x0164, + ('t', '<'): 0x0165, + ('T', '/'): 0x0166, + ('t', '/'): 0x0167, + ('U', '?'): 0x0168, + ('u', '?'): 0x0169, + ('U', '-'): 0x016a, + ('u', '-'): 0x016b, + ('U', '('): 0x016c, + ('u', '('): 0x016d, + ('U', '0'): 0x016e, + ('u', '0'): 0x016f, + ('U', '"'): 0x0170, + ('u', '"'): 0x0171, + ('U', ';'): 0x0172, + ('u', ';'): 0x0173, + ('W', '>'): 0x0174, + ('w', '>'): 0x0175, + ('Y', '>'): 0x0176, + ('y', '>'): 0x0177, + ('Y', ':'): 0x0178, + ('Z', '\''): 0x0179, + ('z', '\''): 0x017a, + ('Z', '.'): 0x017b, + ('z', '.'): 0x017c, + ('Z', '<'): 0x017d, + ('z', '<'): 0x017e, + ('O', '9'): 0x01a0, + ('o', '9'): 0x01a1, + ('O', 'I'): 0x01a2, + ('o', 'i'): 0x01a3, + ('y', 'r'): 0x01a6, + ('U', '9'): 0x01af, + ('u', '9'): 0x01b0, + ('Z', '/'): 0x01b5, + ('z', '/'): 0x01b6, + ('E', 'D'): 0x01b7, + ('A', '<'): 0x01cd, + ('a', '<'): 0x01ce, + ('I', '<'): 0x01cf, + ('i', '<'): 0x01d0, + ('O', '<'): 0x01d1, + ('o', '<'): 0x01d2, + ('U', '<'): 0x01d3, + ('u', '<'): 0x01d4, + ('A', '1'): 0x01de, + ('a', '1'): 0x01df, + ('A', '7'): 0x01e0, + ('a', '7'): 0x01e1, + ('A', '3'): 0x01e2, + ('a', '3'): 0x01e3, + ('G', '/'): 0x01e4, + ('g', '/'): 0x01e5, + ('G', '<'): 0x01e6, + ('g', '<'): 0x01e7, + ('K', '<'): 0x01e8, + ('k', '<'): 0x01e9, + ('O', ';'): 0x01ea, + ('o', ';'): 0x01eb, + ('O', '1'): 0x01ec, + ('o', '1'): 0x01ed, + ('E', 'Z'): 0x01ee, + ('e', 'z'): 0x01ef, + ('j', '<'): 0x01f0, + ('G', '\''): 0x01f4, + ('g', '\''): 0x01f5, + (';', 'S'): 0x02bf, + ('\'', '<'): 0x02c7, + ('\'', '('): 0x02d8, + ('\'', '.'): 0x02d9, + ('\'', '0'): 0x02da, + ('\'', ';'): 0x02db, + ('\'', '"'): 0x02dd, + ('A', '%'): 0x0386, + ('E', '%'): 0x0388, + ('Y', '%'): 0x0389, + ('I', '%'): 0x038a, + ('O', '%'): 0x038c, + ('U', '%'): 0x038e, + ('W', '%'): 0x038f, + ('i', '3'): 0x0390, + ('A', '*'): 0x0391, + ('B', '*'): 0x0392, + ('G', '*'): 0x0393, + ('D', '*'): 0x0394, + ('E', '*'): 0x0395, + ('Z', '*'): 0x0396, + ('Y', '*'): 0x0397, + ('H', '*'): 0x0398, + ('I', '*'): 0x0399, + ('K', '*'): 0x039a, + ('L', '*'): 0x039b, + ('M', '*'): 0x039c, + ('N', '*'): 0x039d, + ('C', '*'): 0x039e, + ('O', '*'): 0x039f, + ('P', '*'): 0x03a0, + ('R', '*'): 0x03a1, + ('S', '*'): 0x03a3, + ('T', '*'): 0x03a4, + ('U', '*'): 0x03a5, + ('F', '*'): 0x03a6, + ('X', '*'): 0x03a7, + ('Q', '*'): 0x03a8, + ('W', '*'): 0x03a9, + ('J', '*'): 0x03aa, + ('V', '*'): 0x03ab, + ('a', '%'): 0x03ac, + ('e', '%'): 0x03ad, + ('y', '%'): 0x03ae, + ('i', '%'): 0x03af, + ('u', '3'): 0x03b0, + ('a', '*'): 0x03b1, + ('b', '*'): 0x03b2, + ('g', '*'): 0x03b3, + ('d', '*'): 0x03b4, + ('e', '*'): 0x03b5, + ('z', '*'): 0x03b6, + ('y', '*'): 0x03b7, + ('h', '*'): 0x03b8, + ('i', '*'): 0x03b9, + ('k', '*'): 0x03ba, + ('l', '*'): 0x03bb, + ('m', '*'): 0x03bc, + ('n', '*'): 0x03bd, + ('c', '*'): 0x03be, + ('o', '*'): 0x03bf, + ('p', '*'): 0x03c0, + ('r', '*'): 0x03c1, + ('*', 's'): 0x03c2, + ('s', '*'): 0x03c3, + ('t', '*'): 0x03c4, + ('u', '*'): 0x03c5, + ('f', '*'): 0x03c6, + ('x', '*'): 0x03c7, + ('q', '*'): 0x03c8, + ('w', '*'): 0x03c9, + ('j', '*'): 0x03ca, + ('v', '*'): 0x03cb, + ('o', '%'): 0x03cc, + ('u', '%'): 0x03cd, + ('w', '%'): 0x03ce, + ('\'', 'G'): 0x03d8, + (',', 'G'): 0x03d9, + ('T', '3'): 0x03da, + ('t', '3'): 0x03db, + ('M', '3'): 0x03dc, + ('m', '3'): 0x03dd, + ('K', '3'): 0x03de, + ('k', '3'): 0x03df, + ('P', '3'): 0x03e0, + ('p', '3'): 0x03e1, + ('\'', '%'): 0x03f4, + ('j', '3'): 0x03f5, + ('I', 'O'): 0x0401, + ('D', '%'): 0x0402, + ('G', '%'): 0x0403, + ('I', 'E'): 0x0404, + ('D', 'S'): 0x0405, + ('I', 'I'): 0x0406, + ('Y', 'I'): 0x0407, + ('J', '%'): 0x0408, + ('L', 'J'): 0x0409, + ('N', 'J'): 0x040a, + ('T', 's'): 0x040b, + ('K', 'J'): 0x040c, + ('V', '%'): 0x040e, + ('D', 'Z'): 0x040f, + ('A', '='): 0x0410, + ('B', '='): 0x0411, + ('V', '='): 0x0412, + ('G', '='): 0x0413, + ('D', '='): 0x0414, + ('E', '='): 0x0415, + ('Z', '%'): 0x0416, + ('Z', '='): 0x0417, + ('I', '='): 0x0418, + ('J', '='): 0x0419, + ('K', '='): 0x041a, + ('L', '='): 0x041b, + ('M', '='): 0x041c, + ('N', '='): 0x041d, + ('O', '='): 0x041e, + ('P', '='): 0x041f, + ('R', '='): 0x0420, + ('S', '='): 0x0421, + ('T', '='): 0x0422, + ('U', '='): 0x0423, + ('F', '='): 0x0424, + ('H', '='): 0x0425, + ('C', '='): 0x0426, + ('C', '%'): 0x0427, + ('S', '%'): 0x0428, + ('S', 'c'): 0x0429, + ('=', '"'): 0x042a, + ('Y', '='): 0x042b, + ('%', '"'): 0x042c, + ('J', 'E'): 0x042d, + ('J', 'U'): 0x042e, + ('J', 'A'): 0x042f, + ('a', '='): 0x0430, + ('b', '='): 0x0431, + ('v', '='): 0x0432, + ('g', '='): 0x0433, + ('d', '='): 0x0434, + ('e', '='): 0x0435, + ('z', '%'): 0x0436, + ('z', '='): 0x0437, + ('i', '='): 0x0438, + ('j', '='): 0x0439, + ('k', '='): 0x043a, + ('l', '='): 0x043b, + ('m', '='): 0x043c, + ('n', '='): 0x043d, + ('o', '='): 0x043e, + ('p', '='): 0x043f, + ('r', '='): 0x0440, + ('s', '='): 0x0441, + ('t', '='): 0x0442, + ('u', '='): 0x0443, + ('f', '='): 0x0444, + ('h', '='): 0x0445, + ('c', '='): 0x0446, + ('c', '%'): 0x0447, + ('s', '%'): 0x0448, + ('s', 'c'): 0x0449, + ('=', '\''): 0x044a, + ('y', '='): 0x044b, + ('%', '\''): 0x044c, + ('j', 'e'): 0x044d, + ('j', 'u'): 0x044e, + ('j', 'a'): 0x044f, + ('i', 'o'): 0x0451, + ('d', '%'): 0x0452, + ('g', '%'): 0x0453, + ('i', 'e'): 0x0454, + ('d', 's'): 0x0455, + ('i', 'i'): 0x0456, + ('y', 'i'): 0x0457, + ('j', '%'): 0x0458, + ('l', 'j'): 0x0459, + ('n', 'j'): 0x045a, + ('t', 's'): 0x045b, + ('k', 'j'): 0x045c, + ('v', '%'): 0x045e, + ('d', 'z'): 0x045f, + ('Y', '3'): 0x0462, + ('y', '3'): 0x0463, + ('O', '3'): 0x046a, + ('o', '3'): 0x046b, + ('F', '3'): 0x0472, + ('f', '3'): 0x0473, + ('V', '3'): 0x0474, + ('v', '3'): 0x0475, + ('C', '3'): 0x0480, + ('c', '3'): 0x0481, + ('G', '3'): 0x0490, + ('g', '3'): 0x0491, + ('A', '+'): 0x05d0, + ('B', '+'): 0x05d1, + ('G', '+'): 0x05d2, + ('D', '+'): 0x05d3, + ('H', '+'): 0x05d4, + ('W', '+'): 0x05d5, + ('Z', '+'): 0x05d6, + ('X', '+'): 0x05d7, + ('T', 'j'): 0x05d8, + ('J', '+'): 0x05d9, + ('K', '%'): 0x05da, + ('K', '+'): 0x05db, + ('L', '+'): 0x05dc, + ('M', '%'): 0x05dd, + ('M', '+'): 0x05de, + ('N', '%'): 0x05df, + ('N', '+'): 0x05e0, + ('S', '+'): 0x05e1, + ('E', '+'): 0x05e2, + ('P', '%'): 0x05e3, + ('P', '+'): 0x05e4, + ('Z', 'j'): 0x05e5, + ('Z', 'J'): 0x05e6, + ('Q', '+'): 0x05e7, + ('R', '+'): 0x05e8, + ('S', 'h'): 0x05e9, + ('T', '+'): 0x05ea, + (',', '+'): 0x060c, + (';', '+'): 0x061b, + ('?', '+'): 0x061f, + ('H', '\''): 0x0621, + ('a', 'M'): 0x0622, + ('a', 'H'): 0x0623, + ('w', 'H'): 0x0624, + ('a', 'h'): 0x0625, + ('y', 'H'): 0x0626, + ('a', '+'): 0x0627, + ('b', '+'): 0x0628, + ('t', 'm'): 0x0629, + ('t', '+'): 0x062a, + ('t', 'k'): 0x062b, + ('g', '+'): 0x062c, + ('h', 'k'): 0x062d, + ('x', '+'): 0x062e, + ('d', '+'): 0x062f, + ('d', 'k'): 0x0630, + ('r', '+'): 0x0631, + ('z', '+'): 0x0632, + ('s', '+'): 0x0633, + ('s', 'n'): 0x0634, + ('c', '+'): 0x0635, + ('d', 'd'): 0x0636, + ('t', 'j'): 0x0637, + ('z', 'H'): 0x0638, + ('e', '+'): 0x0639, + ('i', '+'): 0x063a, + ('+', '+'): 0x0640, + ('f', '+'): 0x0641, + ('q', '+'): 0x0642, + ('k', '+'): 0x0643, + ('l', '+'): 0x0644, + ('m', '+'): 0x0645, + ('n', '+'): 0x0646, + ('h', '+'): 0x0647, + ('w', '+'): 0x0648, + ('j', '+'): 0x0649, + ('y', '+'): 0x064a, + (':', '+'): 0x064b, + ('"', '+'): 0x064c, + ('=', '+'): 0x064d, + ('/', '+'): 0x064e, + ('\'', '+'): 0x064f, + ('1', '+'): 0x0650, + ('3', '+'): 0x0651, + ('0', '+'): 0x0652, + ('a', 'S'): 0x0670, + ('p', '+'): 0x067e, + ('v', '+'): 0x06a4, + ('g', 'f'): 0x06af, + ('0', 'a'): 0x06f0, + ('1', 'a'): 0x06f1, + ('2', 'a'): 0x06f2, + ('3', 'a'): 0x06f3, + ('4', 'a'): 0x06f4, + ('5', 'a'): 0x06f5, + ('6', 'a'): 0x06f6, + ('7', 'a'): 0x06f7, + ('8', 'a'): 0x06f8, + ('9', 'a'): 0x06f9, + ('B', '.'): 0x1e02, + ('b', '.'): 0x1e03, + ('B', '_'): 0x1e06, + ('b', '_'): 0x1e07, + ('D', '.'): 0x1e0a, + ('d', '.'): 0x1e0b, + ('D', '_'): 0x1e0e, + ('d', '_'): 0x1e0f, + ('D', ','): 0x1e10, + ('d', ','): 0x1e11, + ('F', '.'): 0x1e1e, + ('f', '.'): 0x1e1f, + ('G', '-'): 0x1e20, + ('g', '-'): 0x1e21, + ('H', '.'): 0x1e22, + ('h', '.'): 0x1e23, + ('H', ':'): 0x1e26, + ('h', ':'): 0x1e27, + ('H', ','): 0x1e28, + ('h', ','): 0x1e29, + ('K', '\''): 0x1e30, + ('k', '\''): 0x1e31, + ('K', '_'): 0x1e34, + ('k', '_'): 0x1e35, + ('L', '_'): 0x1e3a, + ('l', '_'): 0x1e3b, + ('M', '\''): 0x1e3e, + ('m', '\''): 0x1e3f, + ('M', '.'): 0x1e40, + ('m', '.'): 0x1e41, + ('N', '.'): 0x1e44, + ('n', '.'): 0x1e45, + ('N', '_'): 0x1e48, + ('n', '_'): 0x1e49, + ('P', '\''): 0x1e54, + ('p', '\''): 0x1e55, + ('P', '.'): 0x1e56, + ('p', '.'): 0x1e57, + ('R', '.'): 0x1e58, + ('r', '.'): 0x1e59, + ('R', '_'): 0x1e5e, + ('r', '_'): 0x1e5f, + ('S', '.'): 0x1e60, + ('s', '.'): 0x1e61, + ('T', '.'): 0x1e6a, + ('t', '.'): 0x1e6b, + ('T', '_'): 0x1e6e, + ('t', '_'): 0x1e6f, + ('V', '?'): 0x1e7c, + ('v', '?'): 0x1e7d, + ('W', '!'): 0x1e80, + ('w', '!'): 0x1e81, + ('W', '\''): 0x1e82, + ('w', '\''): 0x1e83, + ('W', ':'): 0x1e84, + ('w', ':'): 0x1e85, + ('W', '.'): 0x1e86, + ('w', '.'): 0x1e87, + ('X', '.'): 0x1e8a, + ('x', '.'): 0x1e8b, + ('X', ':'): 0x1e8c, + ('x', ':'): 0x1e8d, + ('Y', '.'): 0x1e8e, + ('y', '.'): 0x1e8f, + ('Z', '>'): 0x1e90, + ('z', '>'): 0x1e91, + ('Z', '_'): 0x1e94, + ('z', '_'): 0x1e95, + ('h', '_'): 0x1e96, + ('t', ':'): 0x1e97, + ('w', '0'): 0x1e98, + ('y', '0'): 0x1e99, + ('A', '2'): 0x1ea2, + ('a', '2'): 0x1ea3, + ('E', '2'): 0x1eba, + ('e', '2'): 0x1ebb, + ('E', '?'): 0x1ebc, + ('e', '?'): 0x1ebd, + ('I', '2'): 0x1ec8, + ('i', '2'): 0x1ec9, + ('O', '2'): 0x1ece, + ('o', '2'): 0x1ecf, + ('U', '2'): 0x1ee6, + ('u', '2'): 0x1ee7, + ('Y', '!'): 0x1ef2, + ('y', '!'): 0x1ef3, + ('Y', '2'): 0x1ef6, + ('y', '2'): 0x1ef7, + ('Y', '?'): 0x1ef8, + ('y', '?'): 0x1ef9, + (';', '\''): 0x1f00, + (',', '\''): 0x1f01, + (';', '!'): 0x1f02, + (',', '!'): 0x1f03, + ('?', ';'): 0x1f04, + ('?', ','): 0x1f05, + ('!', ':'): 0x1f06, + ('?', ':'): 0x1f07, + ('1', 'N'): 0x2002, + ('1', 'M'): 0x2003, + ('3', 'M'): 0x2004, + ('4', 'M'): 0x2005, + ('6', 'M'): 0x2006, + ('1', 'T'): 0x2009, + ('1', 'H'): 0x200a, + ('-', '1'): 0x2010, + ('-', 'N'): 0x2013, + ('-', 'M'): 0x2014, + ('-', '3'): 0x2015, + ('!', '2'): 0x2016, + ('=', '2'): 0x2017, + ('\'', '6'): 0x2018, + ('\'', '9'): 0x2019, + ('.', '9'): 0x201a, + ('9', '\''): 0x201b, + ('"', '6'): 0x201c, + ('"', '9'): 0x201d, + (':', '9'): 0x201e, + ('9', '"'): 0x201f, + ('/', '-'): 0x2020, + ('/', '='): 0x2021, + ('.', '.'): 0x2025, + ('%', '0'): 0x2030, + ('1', '\''): 0x2032, + ('2', '\''): 0x2033, + ('3', '\''): 0x2034, + ('1', '"'): 0x2035, + ('2', '"'): 0x2036, + ('3', '"'): 0x2037, + ('C', 'a'): 0x2038, + ('<', '1'): 0x2039, + ('>', '1'): 0x203a, + (':', 'X'): 0x203b, + ('\'', '-'): 0x203e, + ('/', 'f'): 0x2044, + ('0', 'S'): 0x2070, + ('4', 'S'): 0x2074, + ('5', 'S'): 0x2075, + ('6', 'S'): 0x2076, + ('7', 'S'): 0x2077, + ('8', 'S'): 0x2078, + ('9', 'S'): 0x2079, + ('+', 'S'): 0x207a, + ('-', 'S'): 0x207b, + ('=', 'S'): 0x207c, + ('(', 'S'): 0x207d, + (')', 'S'): 0x207e, + ('n', 'S'): 0x207f, + ('0', 's'): 0x2080, + ('1', 's'): 0x2081, + ('2', 's'): 0x2082, + ('3', 's'): 0x2083, + ('4', 's'): 0x2084, + ('5', 's'): 0x2085, + ('6', 's'): 0x2086, + ('7', 's'): 0x2087, + ('8', 's'): 0x2088, + ('9', 's'): 0x2089, + ('+', 's'): 0x208a, + ('-', 's'): 0x208b, + ('=', 's'): 0x208c, + ('(', 's'): 0x208d, + (')', 's'): 0x208e, + ('L', 'i'): 0x20a4, + ('P', 't'): 0x20a7, + ('W', '='): 0x20a9, + ('=', 'e'): 0x20ac, # euro + ('E', 'u'): 0x20ac, # euro + ('=', 'R'): 0x20bd, # rouble + ('=', 'P'): 0x20bd, # rouble + ('o', 'C'): 0x2103, + ('c', 'o'): 0x2105, + ('o', 'F'): 0x2109, + ('N', '0'): 0x2116, + ('P', 'O'): 0x2117, + ('R', 'x'): 0x211e, + ('S', 'M'): 0x2120, + ('T', 'M'): 0x2122, + ('O', 'm'): 0x2126, + ('A', 'O'): 0x212b, + ('1', '3'): 0x2153, + ('2', '3'): 0x2154, + ('1', '5'): 0x2155, + ('2', '5'): 0x2156, + ('3', '5'): 0x2157, + ('4', '5'): 0x2158, + ('1', '6'): 0x2159, + ('5', '6'): 0x215a, + ('1', '8'): 0x215b, + ('3', '8'): 0x215c, + ('5', '8'): 0x215d, + ('7', '8'): 0x215e, + ('1', 'R'): 0x2160, + ('2', 'R'): 0x2161, + ('3', 'R'): 0x2162, + ('4', 'R'): 0x2163, + ('5', 'R'): 0x2164, + ('6', 'R'): 0x2165, + ('7', 'R'): 0x2166, + ('8', 'R'): 0x2167, + ('9', 'R'): 0x2168, + ('a', 'R'): 0x2169, + ('b', 'R'): 0x216a, + ('c', 'R'): 0x216b, + ('1', 'r'): 0x2170, + ('2', 'r'): 0x2171, + ('3', 'r'): 0x2172, + ('4', 'r'): 0x2173, + ('5', 'r'): 0x2174, + ('6', 'r'): 0x2175, + ('7', 'r'): 0x2176, + ('8', 'r'): 0x2177, + ('9', 'r'): 0x2178, + ('a', 'r'): 0x2179, + ('b', 'r'): 0x217a, + ('c', 'r'): 0x217b, + ('<', '-'): 0x2190, + ('-', '!'): 0x2191, + ('-', '>'): 0x2192, + ('-', 'v'): 0x2193, + ('<', '>'): 0x2194, + ('U', 'D'): 0x2195, + ('<', '='): 0x21d0, + ('=', '>'): 0x21d2, + ('=', '='): 0x21d4, + ('F', 'A'): 0x2200, + ('d', 'P'): 0x2202, + ('T', 'E'): 0x2203, + ('/', '0'): 0x2205, + ('D', 'E'): 0x2206, + ('N', 'B'): 0x2207, + ('(', '-'): 0x2208, + ('-', ')'): 0x220b, + ('*', 'P'): 0x220f, + ('+', 'Z'): 0x2211, + ('-', '2'): 0x2212, + ('-', '+'): 0x2213, + ('*', '-'): 0x2217, + ('O', 'b'): 0x2218, + ('S', 'b'): 0x2219, + ('R', 'T'): 0x221a, + ('0', '('): 0x221d, + ('0', '0'): 0x221e, + ('-', 'L'): 0x221f, + ('-', 'V'): 0x2220, + ('P', 'P'): 0x2225, + ('A', 'N'): 0x2227, + ('O', 'R'): 0x2228, + ('(', 'U'): 0x2229, + (')', 'U'): 0x222a, + ('I', 'n'): 0x222b, + ('D', 'I'): 0x222c, + ('I', 'o'): 0x222e, + ('.', ':'): 0x2234, + (':', '.'): 0x2235, + (':', 'R'): 0x2236, + (':', ':'): 0x2237, + ('?', '1'): 0x223c, + ('C', 'G'): 0x223e, + ('?', '-'): 0x2243, + ('?', '='): 0x2245, + ('?', '2'): 0x2248, + ('=', '?'): 0x224c, + ('H', 'I'): 0x2253, + ('!', '='): 0x2260, + ('=', '3'): 0x2261, + ('=', '<'): 0x2264, + ('>', '='): 0x2265, + ('<', '*'): 0x226a, + ('*', '>'): 0x226b, + ('!', '<'): 0x226e, + ('!', '>'): 0x226f, + ('(', 'C'): 0x2282, + (')', 'C'): 0x2283, + ('(', '_'): 0x2286, + (')', '_'): 0x2287, + ('0', '.'): 0x2299, + ('0', '2'): 0x229a, + ('-', 'T'): 0x22a5, + ('.', 'P'): 0x22c5, + (':', '3'): 0x22ee, + ('.', '3'): 0x22ef, + ('E', 'h'): 0x2302, + ('<', '7'): 0x2308, + ('>', '7'): 0x2309, + ('7', '<'): 0x230a, + ('7', '>'): 0x230b, + ('N', 'I'): 0x2310, + ('(', 'A'): 0x2312, + ('T', 'R'): 0x2315, + ('I', 'u'): 0x2320, + ('I', 'l'): 0x2321, + ('<', '/'): 0x2329, + ('/', '>'): 0x232a, + ('V', 's'): 0x2423, + ('1', 'h'): 0x2440, + ('3', 'h'): 0x2441, + ('2', 'h'): 0x2442, + ('4', 'h'): 0x2443, + ('1', 'j'): 0x2446, + ('2', 'j'): 0x2447, + ('3', 'j'): 0x2448, + ('4', 'j'): 0x2449, + ('1', '.'): 0x2488, + ('2', '.'): 0x2489, + ('3', '.'): 0x248a, + ('4', '.'): 0x248b, + ('5', '.'): 0x248c, + ('6', '.'): 0x248d, + ('7', '.'): 0x248e, + ('8', '.'): 0x248f, + ('9', '.'): 0x2490, + ('h', 'h'): 0x2500, + ('H', 'H'): 0x2501, + ('v', 'v'): 0x2502, + ('V', 'V'): 0x2503, + ('3', '-'): 0x2504, + ('3', '_'): 0x2505, + ('3', '!'): 0x2506, + ('3', '/'): 0x2507, + ('4', '-'): 0x2508, + ('4', '_'): 0x2509, + ('4', '!'): 0x250a, + ('4', '/'): 0x250b, + ('d', 'r'): 0x250c, + ('d', 'R'): 0x250d, + ('D', 'r'): 0x250e, + ('D', 'R'): 0x250f, + ('d', 'l'): 0x2510, + ('d', 'L'): 0x2511, + ('D', 'l'): 0x2512, + ('L', 'D'): 0x2513, + ('u', 'r'): 0x2514, + ('u', 'R'): 0x2515, + ('U', 'r'): 0x2516, + ('U', 'R'): 0x2517, + ('u', 'l'): 0x2518, + ('u', 'L'): 0x2519, + ('U', 'l'): 0x251a, + ('U', 'L'): 0x251b, + ('v', 'r'): 0x251c, + ('v', 'R'): 0x251d, + ('V', 'r'): 0x2520, + ('V', 'R'): 0x2523, + ('v', 'l'): 0x2524, + ('v', 'L'): 0x2525, + ('V', 'l'): 0x2528, + ('V', 'L'): 0x252b, + ('d', 'h'): 0x252c, + ('d', 'H'): 0x252f, + ('D', 'h'): 0x2530, + ('D', 'H'): 0x2533, + ('u', 'h'): 0x2534, + ('u', 'H'): 0x2537, + ('U', 'h'): 0x2538, + ('U', 'H'): 0x253b, + ('v', 'h'): 0x253c, + ('v', 'H'): 0x253f, + ('V', 'h'): 0x2542, + ('V', 'H'): 0x254b, + ('F', 'D'): 0x2571, + ('B', 'D'): 0x2572, + ('T', 'B'): 0x2580, + ('L', 'B'): 0x2584, + ('F', 'B'): 0x2588, + ('l', 'B'): 0x258c, + ('R', 'B'): 0x2590, + ('.', 'S'): 0x2591, + (':', 'S'): 0x2592, + ('?', 'S'): 0x2593, + ('f', 'S'): 0x25a0, + ('O', 'S'): 0x25a1, + ('R', 'O'): 0x25a2, + ('R', 'r'): 0x25a3, + ('R', 'F'): 0x25a4, + ('R', 'Y'): 0x25a5, + ('R', 'H'): 0x25a6, + ('R', 'Z'): 0x25a7, + ('R', 'K'): 0x25a8, + ('R', 'X'): 0x25a9, + ('s', 'B'): 0x25aa, + ('S', 'R'): 0x25ac, + ('O', 'r'): 0x25ad, + ('U', 'T'): 0x25b2, + ('u', 'T'): 0x25b3, + ('P', 'R'): 0x25b6, + ('T', 'r'): 0x25b7, + ('D', 't'): 0x25bc, + ('d', 'T'): 0x25bd, + ('P', 'L'): 0x25c0, + ('T', 'l'): 0x25c1, + ('D', 'b'): 0x25c6, + ('D', 'w'): 0x25c7, + ('L', 'Z'): 0x25ca, + ('0', 'm'): 0x25cb, + ('0', 'o'): 0x25ce, + ('0', 'M'): 0x25cf, + ('0', 'L'): 0x25d0, + ('0', 'R'): 0x25d1, + ('S', 'n'): 0x25d8, + ('I', 'c'): 0x25d9, + ('F', 'd'): 0x25e2, + ('B', 'd'): 0x25e3, + ('*', '2'): 0x2605, + ('*', '1'): 0x2606, + ('<', 'H'): 0x261c, + ('>', 'H'): 0x261e, + ('0', 'u'): 0x263a, + ('0', 'U'): 0x263b, + ('S', 'U'): 0x263c, + ('F', 'm'): 0x2640, + ('M', 'l'): 0x2642, + ('c', 'S'): 0x2660, + ('c', 'H'): 0x2661, + ('c', 'D'): 0x2662, + ('c', 'C'): 0x2663, + ('M', 'd'): 0x2669, + ('M', '8'): 0x266a, + ('M', '2'): 0x266b, + ('M', 'b'): 0x266d, + ('M', 'x'): 0x266e, + ('M', 'X'): 0x266f, + ('O', 'K'): 0x2713, + ('X', 'X'): 0x2717, + ('-', 'X'): 0x2720, + ('I', 'S'): 0x3000, + (',', '_'): 0x3001, + ('.', '_'): 0x3002, + ('+', '"'): 0x3003, + ('+', '_'): 0x3004, + ('*', '_'): 0x3005, + (';', '_'): 0x3006, + ('0', '_'): 0x3007, + ('<', '+'): 0x300a, + ('>', '+'): 0x300b, + ('<', '\''): 0x300c, + ('>', '\''): 0x300d, + ('<', '"'): 0x300e, + ('>', '"'): 0x300f, + ('(', '"'): 0x3010, + (')', '"'): 0x3011, + ('=', 'T'): 0x3012, + ('=', '_'): 0x3013, + ('(', '\''): 0x3014, + (')', '\''): 0x3015, + ('(', 'I'): 0x3016, + (')', 'I'): 0x3017, + ('-', '?'): 0x301c, + ('A', '5'): 0x3041, + ('a', '5'): 0x3042, + ('I', '5'): 0x3043, + ('i', '5'): 0x3044, + ('U', '5'): 0x3045, + ('u', '5'): 0x3046, + ('E', '5'): 0x3047, + ('e', '5'): 0x3048, + ('O', '5'): 0x3049, + ('o', '5'): 0x304a, + ('k', 'a'): 0x304b, + ('g', 'a'): 0x304c, + ('k', 'i'): 0x304d, + ('g', 'i'): 0x304e, + ('k', 'u'): 0x304f, + ('g', 'u'): 0x3050, + ('k', 'e'): 0x3051, + ('g', 'e'): 0x3052, + ('k', 'o'): 0x3053, + ('g', 'o'): 0x3054, + ('s', 'a'): 0x3055, + ('z', 'a'): 0x3056, + ('s', 'i'): 0x3057, + ('z', 'i'): 0x3058, + ('s', 'u'): 0x3059, + ('z', 'u'): 0x305a, + ('s', 'e'): 0x305b, + ('z', 'e'): 0x305c, + ('s', 'o'): 0x305d, + ('z', 'o'): 0x305e, + ('t', 'a'): 0x305f, + ('d', 'a'): 0x3060, + ('t', 'i'): 0x3061, + ('d', 'i'): 0x3062, + ('t', 'U'): 0x3063, + ('t', 'u'): 0x3064, + ('d', 'u'): 0x3065, + ('t', 'e'): 0x3066, + ('d', 'e'): 0x3067, + ('t', 'o'): 0x3068, + ('d', 'o'): 0x3069, + ('n', 'a'): 0x306a, + ('n', 'i'): 0x306b, + ('n', 'u'): 0x306c, + ('n', 'e'): 0x306d, + ('n', 'o'): 0x306e, + ('h', 'a'): 0x306f, + ('b', 'a'): 0x3070, + ('p', 'a'): 0x3071, + ('h', 'i'): 0x3072, + ('b', 'i'): 0x3073, + ('p', 'i'): 0x3074, + ('h', 'u'): 0x3075, + ('b', 'u'): 0x3076, + ('p', 'u'): 0x3077, + ('h', 'e'): 0x3078, + ('b', 'e'): 0x3079, + ('p', 'e'): 0x307a, + ('h', 'o'): 0x307b, + ('b', 'o'): 0x307c, + ('p', 'o'): 0x307d, + ('m', 'a'): 0x307e, + ('m', 'i'): 0x307f, + ('m', 'u'): 0x3080, + ('m', 'e'): 0x3081, + ('m', 'o'): 0x3082, + ('y', 'A'): 0x3083, + ('y', 'a'): 0x3084, + ('y', 'U'): 0x3085, + ('y', 'u'): 0x3086, + ('y', 'O'): 0x3087, + ('y', 'o'): 0x3088, + ('r', 'a'): 0x3089, + ('r', 'i'): 0x308a, + ('r', 'u'): 0x308b, + ('r', 'e'): 0x308c, + ('r', 'o'): 0x308d, + ('w', 'A'): 0x308e, + ('w', 'a'): 0x308f, + ('w', 'i'): 0x3090, + ('w', 'e'): 0x3091, + ('w', 'o'): 0x3092, + ('n', '5'): 0x3093, + ('v', 'u'): 0x3094, + ('"', '5'): 0x309b, + ('0', '5'): 0x309c, + ('*', '5'): 0x309d, + ('+', '5'): 0x309e, + ('a', '6'): 0x30a1, + ('A', '6'): 0x30a2, + ('i', '6'): 0x30a3, + ('I', '6'): 0x30a4, + ('u', '6'): 0x30a5, + ('U', '6'): 0x30a6, + ('e', '6'): 0x30a7, + ('E', '6'): 0x30a8, + ('o', '6'): 0x30a9, + ('O', '6'): 0x30aa, + ('K', 'a'): 0x30ab, + ('G', 'a'): 0x30ac, + ('K', 'i'): 0x30ad, + ('G', 'i'): 0x30ae, + ('K', 'u'): 0x30af, + ('G', 'u'): 0x30b0, + ('K', 'e'): 0x30b1, + ('G', 'e'): 0x30b2, + ('K', 'o'): 0x30b3, + ('G', 'o'): 0x30b4, + ('S', 'a'): 0x30b5, + ('Z', 'a'): 0x30b6, + ('S', 'i'): 0x30b7, + ('Z', 'i'): 0x30b8, + ('S', 'u'): 0x30b9, + ('Z', 'u'): 0x30ba, + ('S', 'e'): 0x30bb, + ('Z', 'e'): 0x30bc, + ('S', 'o'): 0x30bd, + ('Z', 'o'): 0x30be, + ('T', 'a'): 0x30bf, + ('D', 'a'): 0x30c0, + ('T', 'i'): 0x30c1, + ('D', 'i'): 0x30c2, + ('T', 'U'): 0x30c3, + ('T', 'u'): 0x30c4, + ('D', 'u'): 0x30c5, + ('T', 'e'): 0x30c6, + ('D', 'e'): 0x30c7, + ('T', 'o'): 0x30c8, + ('D', 'o'): 0x30c9, + ('N', 'a'): 0x30ca, + ('N', 'i'): 0x30cb, + ('N', 'u'): 0x30cc, + ('N', 'e'): 0x30cd, + ('N', 'o'): 0x30ce, + ('H', 'a'): 0x30cf, + ('B', 'a'): 0x30d0, + ('P', 'a'): 0x30d1, + ('H', 'i'): 0x30d2, + ('B', 'i'): 0x30d3, + ('P', 'i'): 0x30d4, + ('H', 'u'): 0x30d5, + ('B', 'u'): 0x30d6, + ('P', 'u'): 0x30d7, + ('H', 'e'): 0x30d8, + ('B', 'e'): 0x30d9, + ('P', 'e'): 0x30da, + ('H', 'o'): 0x30db, + ('B', 'o'): 0x30dc, + ('P', 'o'): 0x30dd, + ('M', 'a'): 0x30de, + ('M', 'i'): 0x30df, + ('M', 'u'): 0x30e0, + ('M', 'e'): 0x30e1, + ('M', 'o'): 0x30e2, + ('Y', 'A'): 0x30e3, + ('Y', 'a'): 0x30e4, + ('Y', 'U'): 0x30e5, + ('Y', 'u'): 0x30e6, + ('Y', 'O'): 0x30e7, + ('Y', 'o'): 0x30e8, + ('R', 'a'): 0x30e9, + ('R', 'i'): 0x30ea, + ('R', 'u'): 0x30eb, + ('R', 'e'): 0x30ec, + ('R', 'o'): 0x30ed, + ('W', 'A'): 0x30ee, + ('W', 'a'): 0x30ef, + ('W', 'i'): 0x30f0, + ('W', 'e'): 0x30f1, + ('W', 'o'): 0x30f2, + ('N', '6'): 0x30f3, + ('V', 'u'): 0x30f4, + ('K', 'A'): 0x30f5, + ('K', 'E'): 0x30f6, + ('V', 'a'): 0x30f7, + ('V', 'i'): 0x30f8, + ('V', 'e'): 0x30f9, + ('V', 'o'): 0x30fa, + ('.', '6'): 0x30fb, + ('-', '6'): 0x30fc, + ('*', '6'): 0x30fd, + ('+', '6'): 0x30fe, + ('b', '4'): 0x3105, + ('p', '4'): 0x3106, + ('m', '4'): 0x3107, + ('f', '4'): 0x3108, + ('d', '4'): 0x3109, + ('t', '4'): 0x310a, + ('n', '4'): 0x310b, + ('l', '4'): 0x310c, + ('g', '4'): 0x310d, + ('k', '4'): 0x310e, + ('h', '4'): 0x310f, + ('j', '4'): 0x3110, + ('q', '4'): 0x3111, + ('x', '4'): 0x3112, + ('z', 'h'): 0x3113, + ('c', 'h'): 0x3114, + ('s', 'h'): 0x3115, + ('r', '4'): 0x3116, + ('z', '4'): 0x3117, + ('c', '4'): 0x3118, + ('s', '4'): 0x3119, + ('a', '4'): 0x311a, + ('o', '4'): 0x311b, + ('e', '4'): 0x311c, + ('a', 'i'): 0x311e, + ('e', 'i'): 0x311f, + ('a', 'u'): 0x3120, + ('o', 'u'): 0x3121, + ('a', 'n'): 0x3122, + ('e', 'n'): 0x3123, + ('a', 'N'): 0x3124, + ('e', 'N'): 0x3125, + ('e', 'r'): 0x3126, + ('i', '4'): 0x3127, + ('u', '4'): 0x3128, + ('i', 'u'): 0x3129, + ('v', '4'): 0x312a, + ('n', 'G'): 0x312b, + ('g', 'n'): 0x312c, + ('1', 'c'): 0x3220, + ('2', 'c'): 0x3221, + ('3', 'c'): 0x3222, + ('4', 'c'): 0x3223, + ('5', 'c'): 0x3224, + ('6', 'c'): 0x3225, + ('7', 'c'): 0x3226, + ('8', 'c'): 0x3227, + ('9', 'c'): 0x3228, + + # code points 0xe000 - 0xefff excluded, they have no assigned + # characters, only used in proposals. + ('f', 'f'): 0xfb00, + ('f', 'i'): 0xfb01, + ('f', 'l'): 0xfb02, + ('f', 't'): 0xfb05, + ('s', 't'): 0xfb06, + + # Vim 5.x compatible digraphs that don't conflict with the above + ('~', '!'): 161, + ('c', '|'): 162, + ('$', '$'): 163, + ('o', 'x'): 164, # currency symbol in ISO 8859-1 + ('Y', '-'): 165, + ('|', '|'): 166, + ('c', 'O'): 169, + ('-', ','): 172, + ('-', '='): 175, + ('~', 'o'): 176, + ('2', '2'): 178, + ('3', '3'): 179, + ('p', 'p'): 182, + ('~', '.'): 183, + ('1', '1'): 185, + ('~', '?'): 191, + ('A', '`'): 192, + ('A', '^'): 194, + ('A', '~'): 195, + ('A', '"'): 196, + ('A', '@'): 197, + ('E', '`'): 200, + ('E', '^'): 202, + ('E', '"'): 203, + ('I', '`'): 204, + ('I', '^'): 206, + ('I', '"'): 207, + ('N', '~'): 209, + ('O', '`'): 210, + ('O', '^'): 212, + ('O', '~'): 213, + ('/', '\\'): 215, # multiplication symbol in ISO 8859-1 + ('U', '`'): 217, + ('U', '^'): 219, + ('I', 'p'): 222, + ('a', '`'): 224, + ('a', '^'): 226, + ('a', '~'): 227, + ('a', '"'): 228, + ('a', '@'): 229, + ('e', '`'): 232, + ('e', '^'): 234, + ('e', '"'): 235, + ('i', '`'): 236, + ('i', '^'): 238, + ('n', '~'): 241, + ('o', '`'): 242, + ('o', '^'): 244, + ('o', '~'): 245, + ('u', '`'): 249, + ('u', '^'): 251, + ('y', '"'): 255, +} diff --git a/contrib/python/prompt-toolkit/py2/prompt_toolkit/key_binding/input_processor.py b/contrib/python/prompt-toolkit/py2/prompt_toolkit/key_binding/input_processor.py index 51a3110827..e2d706d915 100644 --- a/contrib/python/prompt-toolkit/py2/prompt_toolkit/key_binding/input_processor.py +++ b/contrib/python/prompt-toolkit/py2/prompt_toolkit/key_binding/input_processor.py @@ -4,20 +4,20 @@ An :class:`~.InputProcessor` receives callbacks for the keystrokes parsed from the input in the :class:`~prompt_toolkit.inputstream.InputStream` instance. The `InputProcessor` will according to the implemented keybindings call the -correct callbacks when new key presses are feed through `feed`. +correct callbacks when new key presses are feed through `feed`. """ from __future__ import unicode_literals from prompt_toolkit.buffer import EditReadOnlyBuffer -from prompt_toolkit.filters.cli import ViNavigationMode -from prompt_toolkit.keys import Keys, Key -from prompt_toolkit.utils import Event +from prompt_toolkit.filters.cli import ViNavigationMode +from prompt_toolkit.keys import Keys, Key +from prompt_toolkit.utils import Event from .registry import BaseRegistry - -from collections import deque -from six.moves import range + +from collections import deque +from six.moves import range import weakref -import six +import six __all__ = ( 'InputProcessor', @@ -27,16 +27,16 @@ __all__ = ( class KeyPress(object): """ - :param key: A `Keys` instance or text (one character). + :param key: A `Keys` instance or text (one character). :param data: The received string on stdin. (Often vt100 escape codes.) """ - def __init__(self, key, data=None): - assert isinstance(key, (six.text_type, Key)) - assert data is None or isinstance(data, six.text_type) - - if data is None: - data = key.name if isinstance(key, Key) else key - + def __init__(self, key, data=None): + assert isinstance(key, (six.text_type, Key)) + assert data is None or isinstance(data, six.text_type) + + if data is None: + data = key.name if isinstance(key, Key) else key + self.key = key self.data = data @@ -58,12 +58,12 @@ class InputProcessor(object): p = InputProcessor(registry) # Send keys into the processor. - p.feed(KeyPress(Keys.ControlX, '\x18')) - p.feed(KeyPress(Keys.ControlC, '\x03') - - # Process all the keys in the queue. - p.process_keys() + p.feed(KeyPress(Keys.ControlX, '\x18')) + p.feed(KeyPress(Keys.ControlC, '\x03') + # Process all the keys in the queue. + p.process_keys() + # Now the ControlX-ControlC callback will be called if this sequence is # registered in the registry. @@ -72,20 +72,20 @@ class InputProcessor(object): """ def __init__(self, registry, cli_ref): assert isinstance(registry, BaseRegistry) - + self._registry = registry self._cli_ref = cli_ref - - self.beforeKeyPress = Event(self) - self.afterKeyPress = Event(self) - - # The queue of keys not yet send to our _process generator/state machine. - self.input_queue = deque() - - # The key buffer that is matched in the generator state machine. - # (This is at at most the amount of keys that make up for one key binding.) - self.key_buffer = [] - + + self.beforeKeyPress = Event(self) + self.afterKeyPress = Event(self) + + # The queue of keys not yet send to our _process generator/state machine. + self.input_queue = deque() + + # The key buffer that is matched in the generator state machine. + # (This is at at most the amount of keys that make up for one key binding.) + self.key_buffer = [] + # Simple macro recording. (Like readline does.) self.record_macro = False self.macro = [] @@ -125,7 +125,7 @@ class InputProcessor(object): cli = self._cli_ref() # Try match, with mode flag - return [b for b in self._registry.get_bindings_for_keys(keys) if b.filter(cli)] + return [b for b in self._registry.get_bindings_for_keys(keys) if b.filter(cli)] def _is_prefix_of_longer_match(self, key_presses): """ @@ -149,7 +149,7 @@ class InputProcessor(object): Coroutine implementing the key match algorithm. Key strokes are sent into this generator, and it calls the appropriate handlers. """ - buffer = self.key_buffer + buffer = self.key_buffer retry = False while True: @@ -174,7 +174,7 @@ class InputProcessor(object): # Exact matches found, call handler. if not is_prefix_of_longer_match and matches: self._call_handler(matches[-1], key_sequence=buffer[:]) - del buffer[:] # Keep reference. + del buffer[:] # Keep reference. # No match found. elif not is_prefix_of_longer_match and not matches: @@ -186,70 +186,70 @@ class InputProcessor(object): matches = self._get_matches(buffer[:i]) if matches: self._call_handler(matches[-1], key_sequence=buffer[:i]) - del buffer[:i] + del buffer[:i] found = True - break + break if not found: - del buffer[:1] + del buffer[:1] - def feed(self, key_press): + def feed(self, key_press): """ - Add a new :class:`KeyPress` to the input queue. - (Don't forget to call `process_keys` in order to process the queue.) + Add a new :class:`KeyPress` to the input queue. + (Don't forget to call `process_keys` in order to process the queue.) """ assert isinstance(key_press, KeyPress) - self.input_queue.append(key_press) - - def process_keys(self): - """ - Process all the keys in the `input_queue`. - (To be called after `feed`.) - - Note: because of the `feed`/`process_keys` separation, it is - possible to call `feed` from inside a key binding. - This function keeps looping until the queue is empty. - """ - while self.input_queue: - key_press = self.input_queue.popleft() - - if key_press.key != Keys.CPRResponse: - self.beforeKeyPress.fire() - - self._process_coroutine.send(key_press) - - if key_press.key != Keys.CPRResponse: - self.afterKeyPress.fire() - - # Invalidate user interface. - cli = self._cli_ref() - if cli: - cli.invalidate() - + self.input_queue.append(key_press) + + def process_keys(self): + """ + Process all the keys in the `input_queue`. + (To be called after `feed`.) + + Note: because of the `feed`/`process_keys` separation, it is + possible to call `feed` from inside a key binding. + This function keeps looping until the queue is empty. + """ + while self.input_queue: + key_press = self.input_queue.popleft() + + if key_press.key != Keys.CPRResponse: + self.beforeKeyPress.fire() + + self._process_coroutine.send(key_press) + + if key_press.key != Keys.CPRResponse: + self.afterKeyPress.fire() + + # Invalidate user interface. + cli = self._cli_ref() + if cli: + cli.invalidate() + def _call_handler(self, handler, key_sequence=None): was_recording = self.record_macro arg = self.arg self.arg = None - event = KeyPressEvent( - weakref.ref(self), arg=arg, key_sequence=key_sequence, - previous_key_sequence=self._previous_key_sequence, - is_repeat=(handler == self._previous_handler)) - - # Save the state of the current buffer. - cli = event.cli # Can be `None` (In unit-tests only.) - - if handler.save_before(event) and cli: - cli.current_buffer.save_to_undo_stack() - - # Call handler. + event = KeyPressEvent( + weakref.ref(self), arg=arg, key_sequence=key_sequence, + previous_key_sequence=self._previous_key_sequence, + is_repeat=(handler == self._previous_handler)) + + # Save the state of the current buffer. + cli = event.cli # Can be `None` (In unit-tests only.) + + if handler.save_before(event) and cli: + cli.current_buffer.save_to_undo_stack() + + # Call handler. try: handler.call(event) - self._fix_vi_cursor_position(event) + self._fix_vi_cursor_position(event) except EditReadOnlyBuffer: - # When a key binding does an attempt to change a buffer which is - # read-only, we can just silently ignore that. + # When a key binding does an attempt to change a buffer which is + # read-only, we can just silently ignore that. pass self._previous_key_sequence = key_sequence @@ -260,29 +260,29 @@ class InputProcessor(object): if self.record_macro and was_recording: self.macro.extend(key_sequence) - def _fix_vi_cursor_position(self, event): - """ - After every command, make sure that if we are in Vi navigation mode, we - never put the cursor after the last character of a line. (Unless it's - an empty line.) - """ + def _fix_vi_cursor_position(self, event): + """ + After every command, make sure that if we are in Vi navigation mode, we + never put the cursor after the last character of a line. (Unless it's + an empty line.) + """ cli = self._cli_ref() - if cli: - buff = cli.current_buffer - preferred_column = buff.preferred_column - - if (ViNavigationMode()(event.cli) and - buff.document.is_cursor_at_the_end_of_line and - len(buff.document.current_line) > 0): - buff.cursor_position -= 1 - - # Set the preferred_column for arrow up/down again. - # (This was cleared after changing the cursor position.) - buff.preferred_column = preferred_column - - - -class KeyPressEvent(object): + if cli: + buff = cli.current_buffer + preferred_column = buff.preferred_column + + if (ViNavigationMode()(event.cli) and + buff.document.is_cursor_at_the_end_of_line and + len(buff.document.current_line) > 0): + buff.cursor_position -= 1 + + # Set the preferred_column for arrow up/down again. + # (This was cleared after changing the cursor position.) + buff.preferred_column = preferred_column + + + +class KeyPressEvent(object): """ Key press event, delivered to key bindings. @@ -304,7 +304,7 @@ class KeyPressEvent(object): self._arg = arg def __repr__(self): - return 'KeyPressEvent(arg=%r, key_sequence=%r, is_repeat=%r)' % ( + return 'KeyPressEvent(arg=%r, key_sequence=%r, is_repeat=%r)' % ( self.arg, self.key_sequence, self.is_repeat) @property @@ -334,24 +334,24 @@ class KeyPressEvent(object): """ Repetition argument. """ - if self._arg == '-': - return -1 - - result = int(self._arg or 1) - - # Don't exceed a million. - if int(result) >= 1000000: - result = 1 - - return result - - @property - def arg_present(self): - """ - True if repetition argument was explicitly provided. - """ - return self._arg is not None - + if self._arg == '-': + return -1 + + result = int(self._arg or 1) + + # Don't exceed a million. + if int(result) >= 1000000: + result = 1 + + return result + + @property + def arg_present(self): + """ + True if repetition argument was explicitly provided. + """ + return self._arg is not None + def append_to_arg_count(self, data): """ Add digit to the input argument. @@ -361,12 +361,12 @@ class KeyPressEvent(object): assert data in '-0123456789' current = self._arg - if data == '-': - assert current is None or current == '-' - result = data - elif current is None: - result = data + if data == '-': + assert current is None or current == '-' + result = data + elif current is None: + result = data else: - result = "%s%s" % (current, data) + result = "%s%s" % (current, data) self.input_processor.arg = result diff --git a/contrib/python/prompt-toolkit/py2/prompt_toolkit/key_binding/manager.py b/contrib/python/prompt-toolkit/py2/prompt_toolkit/key_binding/manager.py index 83612c2a5c..dc0e18e3cb 100644 --- a/contrib/python/prompt-toolkit/py2/prompt_toolkit/key_binding/manager.py +++ b/contrib/python/prompt-toolkit/py2/prompt_toolkit/key_binding/manager.py @@ -37,12 +37,12 @@ class KeyBindingManager(object): :param enable_extra_page_navigation: Filter for enabling extra page navigation. (Bindings for up/down scrolling through long pages, like in Emacs or Vi.) :param enable_auto_suggest_bindings: Filter to enable fish-style suggestions. - - :param enable_vi_mode: Deprecated! + + :param enable_vi_mode: Deprecated! """ def __init__(self, registry=None, # XXX: not used anymore. - enable_vi_mode=None, # (`enable_vi_mode` is deprecated.) + enable_vi_mode=None, # (`enable_vi_mode` is deprecated.) enable_all=True, # get_search_state=None, enable_abort_and_exit_bindings=False, @@ -76,7 +76,7 @@ class KeyBindingManager(object): def for_prompt(cls, **kw): """ Create a ``KeyBindingManager`` with the defaults for an input prompt. - This activates the key bindings for abort/exit (Ctrl-C/Ctrl-D), + This activates the key bindings for abort/exit (Ctrl-C/Ctrl-D), incremental search and auto suggestions. (Not for full screen applications.) @@ -88,9 +88,9 @@ class KeyBindingManager(object): return cls(**kw) def reset(self, cli): - # For backwards compatibility. - pass - - def get_vi_state(self, cli): - # Deprecated! - return cli.vi_state + # For backwards compatibility. + pass + + def get_vi_state(self, cli): + # Deprecated! + return cli.vi_state diff --git a/contrib/python/prompt-toolkit/py2/prompt_toolkit/key_binding/registry.py b/contrib/python/prompt-toolkit/py2/prompt_toolkit/key_binding/registry.py index 24d0e729a1..f7258a822d 100644 --- a/contrib/python/prompt-toolkit/py2/prompt_toolkit/key_binding/registry.py +++ b/contrib/python/prompt-toolkit/py2/prompt_toolkit/key_binding/registry.py @@ -26,9 +26,9 @@ key bindings at once. from __future__ import unicode_literals from abc import ABCMeta, abstractmethod -from prompt_toolkit.cache import SimpleCache -from prompt_toolkit.filters import CLIFilter, to_cli_filter, Never -from prompt_toolkit.keys import Key, Keys +from prompt_toolkit.cache import SimpleCache +from prompt_toolkit.filters import CLIFilter, to_cli_filter, Never +from prompt_toolkit.keys import Key, Keys from six import text_type, with_metaclass @@ -44,18 +44,18 @@ class _Binding(object): """ (Immutable binding class.) """ - def __init__(self, keys, handler, filter=None, eager=None, save_before=None): + def __init__(self, keys, handler, filter=None, eager=None, save_before=None): assert isinstance(keys, tuple) assert callable(handler) assert isinstance(filter, CLIFilter) assert isinstance(eager, CLIFilter) - assert callable(save_before) + assert callable(save_before) self.keys = keys self.handler = handler self.filter = filter self.eager = eager - self.save_before = save_before + self.save_before = save_before def call(self, event): return self.handler(event) @@ -89,14 +89,14 @@ class Registry(BaseRegistry): """ def __init__(self): self.key_bindings = [] - self._get_bindings_for_keys_cache = SimpleCache(maxsize=10000) - self._get_bindings_starting_with_keys_cache = SimpleCache(maxsize=1000) + self._get_bindings_for_keys_cache = SimpleCache(maxsize=10000) + self._get_bindings_starting_with_keys_cache = SimpleCache(maxsize=1000) self._version = 0 # For cache invalidation. - def _clear_cache(self): + def _clear_cache(self): self._version += 1 - self._get_bindings_for_keys_cache.clear() - self._get_bindings_starting_with_keys_cache.clear() + self._get_bindings_for_keys_cache.clear() + self._get_bindings_starting_with_keys_cache.clear() def add_binding(self, *keys, **kwargs): """ @@ -109,35 +109,35 @@ class Registry(BaseRegistry): hit. E.g. when there is an active eager key binding for Ctrl-X, execute the handler immediately and ignore the key binding for Ctrl-X Ctrl-E of which it is a prefix. - :param save_before: Callable that takes an `Event` and returns True if - we should save the current buffer, before handling the event. - (That's the default.) + :param save_before: Callable that takes an `Event` and returns True if + we should save the current buffer, before handling the event. + (That's the default.) """ filter = to_cli_filter(kwargs.pop('filter', True)) eager = to_cli_filter(kwargs.pop('eager', False)) - save_before = kwargs.pop('save_before', lambda e: True) - to_cli_filter(kwargs.pop('invalidate_ui', True)) # Deprecated! (ignored.) + save_before = kwargs.pop('save_before', lambda e: True) + to_cli_filter(kwargs.pop('invalidate_ui', True)) # Deprecated! (ignored.) assert not kwargs assert keys assert all(isinstance(k, (Key, text_type)) for k in keys), \ 'Key bindings should consist of Key and string (unicode) instances.' - assert callable(save_before) + assert callable(save_before) - if isinstance(filter, Never): + if isinstance(filter, Never): # When a filter is Never, it will always stay disabled, so in that case # don't bother putting it in the registry. It will slow down every key - # press otherwise. - def decorator(func): - return func - else: - def decorator(func): - self.key_bindings.append( - _Binding(keys, func, filter=filter, eager=eager, - save_before=save_before)) - self._clear_cache() - - return func + # press otherwise. + def decorator(func): + return func + else: + def decorator(func): + self.key_bindings.append( + _Binding(keys, func, filter=filter, eager=eager, + save_before=save_before)) + self._clear_cache() + + return func return decorator def remove_binding(self, function): @@ -153,7 +153,7 @@ class Registry(BaseRegistry): for b in self.key_bindings: if b.handler == function: self.key_bindings.remove(b) - self._clear_cache() + self._clear_cache() return # No key binding found for this function. Raise ValueError. @@ -167,31 +167,31 @@ class Registry(BaseRegistry): :param keys: tuple of keys. """ - def get(): - result = [] - for b in self.key_bindings: - if len(keys) == len(b.keys): - match = True - any_count = 0 - - for i, j in zip(b.keys, keys): - if i != j and i != Keys.Any: - match = False - break - - if i == Keys.Any: - any_count += 1 - - if match: - result.append((any_count, b)) - - # Place bindings that have more 'Any' occurences in them at the end. - result = sorted(result, key=lambda item: -item[0]) - - return [item[1] for item in result] - - return self._get_bindings_for_keys_cache.get(keys, get) - + def get(): + result = [] + for b in self.key_bindings: + if len(keys) == len(b.keys): + match = True + any_count = 0 + + for i, j in zip(b.keys, keys): + if i != j and i != Keys.Any: + match = False + break + + if i == Keys.Any: + any_count += 1 + + if match: + result.append((any_count, b)) + + # Place bindings that have more 'Any' occurences in them at the end. + result = sorted(result, key=lambda item: -item[0]) + + return [item[1] for item in result] + + return self._get_bindings_for_keys_cache.get(keys, get) + def get_bindings_starting_with_keys(self, keys): """ Return a list of key bindings that handle a key sequence starting with @@ -201,20 +201,20 @@ class Registry(BaseRegistry): :param keys: tuple of keys. """ - def get(): - result = [] - for b in self.key_bindings: - if len(keys) < len(b.keys): - match = True - for i, j in zip(b.keys, keys): - if i != j and i != Keys.Any: - match = False - break - if match: - result.append(b) - return result - - return self._get_bindings_starting_with_keys_cache.get(keys, get) + def get(): + result = [] + for b in self.key_bindings: + if len(keys) < len(b.keys): + match = True + for i, j in zip(b.keys, keys): + if i != j and i != Keys.Any: + match = False + break + if match: + result.append(b) + return result + + return self._get_bindings_starting_with_keys_cache.get(keys, get) class _AddRemoveMixin(BaseRegistry): diff --git a/contrib/python/prompt-toolkit/py2/prompt_toolkit/key_binding/vi_state.py b/contrib/python/prompt-toolkit/py2/prompt_toolkit/key_binding/vi_state.py index 92ce3cbd29..c99bef01b1 100644 --- a/contrib/python/prompt-toolkit/py2/prompt_toolkit/key_binding/vi_state.py +++ b/contrib/python/prompt-toolkit/py2/prompt_toolkit/key_binding/vi_state.py @@ -9,7 +9,7 @@ __all__ = ( class InputMode(object): INSERT = 'vi-insert' - INSERT_MULTIPLE = 'vi-insert-multiple' + INSERT_MULTIPLE = 'vi-insert-multiple' NAVIGATION = 'vi-navigation' REPLACE = 'vi-replace' @@ -29,33 +29,33 @@ class ViState(object): #: search in Vi mode, by pressing the 'n' or 'N' in navigation mode.) self.last_character_find = None - # When an operator is given and we are waiting for text object, - # -- e.g. in the case of 'dw', after the 'd' --, an operator callback - # is set here. - self.operator_func = None - self.operator_arg = None - - #: Named registers. Maps register name (e.g. 'a') to - #: :class:`ClipboardData` instances. - self.named_registers = {} - + # When an operator is given and we are waiting for text object, + # -- e.g. in the case of 'dw', after the 'd' --, an operator callback + # is set here. + self.operator_func = None + self.operator_arg = None + + #: Named registers. Maps register name (e.g. 'a') to + #: :class:`ClipboardData` instances. + self.named_registers = {} + #: The Vi mode we're currently in to. self.input_mode = InputMode.INSERT - #: Waiting for digraph. - self.waiting_for_digraph = False - self.digraph_symbol1 = None # (None or a symbol.) - - #: When true, make ~ act as an operator. - self.tilde_operator = False - - def reset(self, mode=InputMode.INSERT): - """ - Reset state, go back to the given mode. INSERT by default. - """ + #: Waiting for digraph. + self.waiting_for_digraph = False + self.digraph_symbol1 = None # (None or a symbol.) + + #: When true, make ~ act as an operator. + self.tilde_operator = False + + def reset(self, mode=InputMode.INSERT): + """ + Reset state, go back to the given mode. INSERT by default. + """ # Go back to insert mode. - self.input_mode = mode - - self.waiting_for_digraph = False - self.operator_func = None - self.operator_arg = None + self.input_mode = mode + + self.waiting_for_digraph = False + self.operator_func = None + self.operator_arg = None diff --git a/contrib/python/prompt-toolkit/py2/prompt_toolkit/keys.py b/contrib/python/prompt-toolkit/py2/prompt_toolkit/keys.py index d5df9bff41..b264fbdb0d 100644 --- a/contrib/python/prompt-toolkit/py2/prompt_toolkit/keys.py +++ b/contrib/python/prompt-toolkit/py2/prompt_toolkit/keys.py @@ -61,35 +61,35 @@ class Keys(object): Down = Key('<Down>') Right = Key('<Right>') Left = Key('<Left>') - - ShiftLeft = Key('<ShiftLeft>') - ShiftUp = Key('<ShiftUp>') - ShiftDown = Key('<ShiftDown>') - ShiftRight = Key('<ShiftRight>') - + + ShiftLeft = Key('<ShiftLeft>') + ShiftUp = Key('<ShiftUp>') + ShiftDown = Key('<ShiftDown>') + ShiftRight = Key('<ShiftRight>') + Home = Key('<Home>') End = Key('<End>') Delete = Key('<Delete>') ShiftDelete = Key('<ShiftDelete>') - ControlDelete = Key('<C-Delete>') + ControlDelete = Key('<C-Delete>') PageUp = Key('<PageUp>') PageDown = Key('<PageDown>') BackTab = Key('<BackTab>') # shift + tab Insert = Key('<Insert>') - Backspace = Key('<Backspace>') + Backspace = Key('<Backspace>') - # Aliases. + # Aliases. Tab = ControlI - Enter = ControlJ - # XXX: Actually Enter equals ControlM, not ControlJ, - # However, in prompt_toolkit, we made the mistake of translating - # \r into \n during the input, so everyone is now handling the - # enter key by binding ControlJ. - - # From now on, it's better to bind `Keys.Enter` everywhere, - # because that's future compatible, and will still work when we - # stop replacing \r by \n. - + Enter = ControlJ + # XXX: Actually Enter equals ControlM, not ControlJ, + # However, in prompt_toolkit, we made the mistake of translating + # \r into \n during the input, so everyone is now handling the + # enter key by binding ControlJ. + + # From now on, it's better to bind `Keys.Enter` everywhere, + # because that's future compatible, and will still work when we + # stop replacing \r by \n. + F1 = Key('<F1>') F2 = Key('<F2>') F3 = Key('<F3>') @@ -110,10 +110,10 @@ class Keys(object): F18 = Key('<F18>') F19 = Key('<F19>') F20 = Key('<F20>') - F21 = Key('<F21>') - F22 = Key('<F22>') - F23 = Key('<F23>') - F24 = Key('<F24>') + F21 = Key('<F21>') + F22 = Key('<F22>') + F23 = Key('<F23>') + F24 = Key('<F24>') # Matches any key. Any = Key('<Any>') @@ -123,7 +123,7 @@ class Keys(object): Vt100MouseEvent = Key('<Vt100-Mouse-Event>') WindowsMouseEvent = Key('<Windows-Mouse-Event>') BracketedPaste = Key('<Bracketed-Paste>') - - # Key which is ignored. (The key binding for this key should not do - # anything.) - Ignore = Key('<Ignore>') + + # Key which is ignored. (The key binding for this key should not do + # anything.) + Ignore = Key('<Ignore>') diff --git a/contrib/python/prompt-toolkit/py2/prompt_toolkit/layout/__init__.py b/contrib/python/prompt-toolkit/py2/prompt_toolkit/layout/__init__.py index 0dec5ecfaf..25590d8a2e 100644 --- a/contrib/python/prompt-toolkit/py2/prompt_toolkit/layout/__init__.py +++ b/contrib/python/prompt-toolkit/py2/prompt_toolkit/layout/__init__.py @@ -8,7 +8,7 @@ There are two main groups of classes here. Containers and controls: - A container can contain other containers or controls, it can have multiple children and it decides about the dimensions. - A control is responsible for rendering the actual content to a screen. - A control can propose some dimensions, but it's the container who decides + A control can propose some dimensions, but it's the container who decides about the dimensions -- or when the control consumes more space -- which part of the control will be visible. diff --git a/contrib/python/prompt-toolkit/py2/prompt_toolkit/layout/containers.py b/contrib/python/prompt-toolkit/py2/prompt_toolkit/layout/containers.py index 0bdafe18e0..2901461e88 100644 --- a/contrib/python/prompt-toolkit/py2/prompt_toolkit/layout/containers.py +++ b/contrib/python/prompt-toolkit/py2/prompt_toolkit/layout/containers.py @@ -6,19 +6,19 @@ from __future__ import unicode_literals from abc import ABCMeta, abstractmethod from six import with_metaclass -from six.moves import range +from six.moves import range -from .controls import UIControl, TokenListControl, UIContent +from .controls import UIControl, TokenListControl, UIContent from .dimension import LayoutDimension, sum_layout_dimensions, max_layout_dimensions from .margins import Margin -from .screen import Point, WritePosition, _CHAR_CACHE -from .utils import token_list_to_text, explode_tokens -from prompt_toolkit.cache import SimpleCache -from prompt_toolkit.filters import to_cli_filter, ViInsertMode, EmacsInsertMode -from prompt_toolkit.mouse_events import MouseEvent, MouseEventType -from prompt_toolkit.reactive import Integer -from prompt_toolkit.token import Token -from prompt_toolkit.utils import take_using_weights, get_cwidth +from .screen import Point, WritePosition, _CHAR_CACHE +from .utils import token_list_to_text, explode_tokens +from prompt_toolkit.cache import SimpleCache +from prompt_toolkit.filters import to_cli_filter, ViInsertMode, EmacsInsertMode +from prompt_toolkit.mouse_events import MouseEvent, MouseEventType +from prompt_toolkit.reactive import Integer +from prompt_toolkit.token import Token +from prompt_toolkit.utils import take_using_weights, get_cwidth __all__ = ( 'Container', @@ -29,8 +29,8 @@ __all__ = ( 'Window', 'WindowRenderInfo', 'ConditionalContainer', - 'ScrollOffsets', - 'ColorColumn', + 'ScrollOffsets', + 'ColorColumn', ) Transparent = Token.Transparent @@ -57,7 +57,7 @@ class Container(with_metaclass(ABCMeta, object)): """ @abstractmethod - def preferred_height(self, cli, width, max_available_height): + def preferred_height(self, cli, width, max_available_height): """ Return a :class:`~prompt_toolkit.layout.dimension.LayoutDimension` that represents the desired height for this container. @@ -124,8 +124,8 @@ class HSplit(Container): else: return LayoutDimension(0) - def preferred_height(self, cli, width, max_available_height): - dimensions = [c.preferred_height(cli, width, max_available_height) for c in self.children] + def preferred_height(self, cli, width, max_available_height): + dimensions = [c.preferred_height(cli, width, max_available_height) for c in self.children] return sum_layout_dimensions(dimensions) def reset(self): @@ -172,7 +172,7 @@ class HSplit(Container): if given_dimensions and given_dimensions[index] is not None: return given_dimensions[index] else: - return c.preferred_height(cli, write_position.width, write_position.extended_height) + return c.preferred_height(cli, write_position.width, write_position.extended_height) dimensions = [get_dimension_for_child(c, index) for index, c in enumerate(self.children)] @@ -250,12 +250,12 @@ class VSplit(Container): dimensions = [c.preferred_width(cli, max_available_width) for c in self.children] return sum_layout_dimensions(dimensions) - def preferred_height(self, cli, width, max_available_height): + def preferred_height(self, cli, width, max_available_height): sizes = self._divide_widths(cli, width) if sizes is None: return LayoutDimension() else: - dimensions = [c.preferred_height(cli, s, max_available_height) + dimensions = [c.preferred_height(cli, s, max_available_height) for s, c in zip(sizes, self.children)] return max_layout_dimensions(dimensions) @@ -336,7 +336,7 @@ class VSplit(Container): return # Calculate heights, take the largest possible, but not larger than write_position.extended_height. - heights = [child.preferred_height(cli, width, write_position.extended_height).preferred + heights = [child.preferred_height(cli, width, write_position.extended_height).preferred for width, child in zip(sizes, self.children)] height = max(write_position.height, min(write_position.extended_height, max(heights))) @@ -386,13 +386,13 @@ class FloatContainer(Container): def preferred_width(self, cli, write_position): return self.content.preferred_width(cli, write_position) - def preferred_height(self, cli, width, max_available_height): + def preferred_height(self, cli, width, max_available_height): """ Return the preferred height of the float container. (We don't care about the height of the floats, they should always fit into the dimensions provided by the container.) """ - return self.content.preferred_height(cli, width, max_available_height) + return self.content.preferred_height(cli, width, max_available_height) def write_to_screen(self, cli, screen, mouse_handlers, write_position): self.content.write_to_screen(cli, screen, mouse_handlers, write_position) @@ -467,8 +467,8 @@ class FloatContainer(Container): height = fl_height if height is None: - height = fl.content.preferred_height( - cli, width, write_position.extended_height).preferred + height = fl.content.preferred_height( + cli, width, write_position.extended_height).preferred # Reduce height if not enough space. (We can use the # extended_height when the content requires it.) @@ -488,8 +488,8 @@ class FloatContainer(Container): height = fl_height # Otherwise, take preferred height from content. else: - height = fl.content.preferred_height( - cli, width, write_position.extended_height).preferred + height = fl.content.preferred_height( + cli, width, write_position.extended_height).preferred if fl.top is not None: ypos = fl.top @@ -508,28 +508,28 @@ class FloatContainer(Container): ypos=ypos + write_position.ypos, width=width, height=height) - if not fl.hide_when_covering_content or self._area_is_empty(screen, wp): - fl.content.write_to_screen(cli, screen, mouse_handlers, wp) - - def _area_is_empty(self, screen, write_position): - """ - Return True when the area below the write position is still empty. - (For floats that should not hide content underneath.) - """ - wp = write_position - Transparent = Token.Transparent - - for y in range(wp.ypos, wp.ypos + wp.height): - if y in screen.data_buffer: - row = screen.data_buffer[y] - - for x in range(wp.xpos, wp.xpos + wp.width): - c = row[x] - if c.char != ' ' or c.token != Transparent: - return False - - return True - + if not fl.hide_when_covering_content or self._area_is_empty(screen, wp): + fl.content.write_to_screen(cli, screen, mouse_handlers, wp) + + def _area_is_empty(self, screen, write_position): + """ + Return True when the area below the write position is still empty. + (For floats that should not hide content underneath.) + """ + wp = write_position + Transparent = Token.Transparent + + for y in range(wp.ypos, wp.ypos + wp.height): + if y in screen.data_buffer: + row = screen.data_buffer[y] + + for x in range(wp.xpos, wp.xpos + wp.width): + c = row[x] + if c.char != ' ' or c.token != Transparent: + return False + + return True + def walk(self, cli): """ Walk through children. """ yield self @@ -547,12 +547,12 @@ class Float(object): Float for use in a :class:`.FloatContainer`. :param content: :class:`.Container` instance. - :param hide_when_covering_content: Hide the float when it covers content underneath. + :param hide_when_covering_content: Hide the float when it covers content underneath. """ def __init__(self, top=None, right=None, bottom=None, left=None, width=None, height=None, get_width=None, get_height=None, - xcursor=False, ycursor=False, content=None, - hide_when_covering_content=False): + xcursor=False, ycursor=False, content=None, + hide_when_covering_content=False): assert isinstance(content, Container) assert width is None or get_width is None assert height is None or get_height is None @@ -572,7 +572,7 @@ class Float(object): self.ycursor = ycursor self.content = content - self.hide_when_covering_content = hide_when_covering_content + self.hide_when_covering_content = hide_when_covering_content def get_width(self, cli): if self._width: @@ -600,135 +600,135 @@ class WindowRenderInfo(object): (Could be used for implementation of the Vi 'H' and 'L' key bindings as well as implementing mouse support.) - :param ui_content: The original :class:`.UIContent` instance that contains - the whole input, without clipping. (ui_content) + :param ui_content: The original :class:`.UIContent` instance that contains + the whole input, without clipping. (ui_content) :param horizontal_scroll: The horizontal scroll of the :class:`.Window` instance. :param vertical_scroll: The vertical scroll of the :class:`.Window` instance. - :param window_width: The width of the window that displays the content, - without the margins. - :param window_height: The height of the window that displays the content. - :param configured_scroll_offsets: The scroll offsets as configured for the - :class:`Window` instance. - :param visible_line_to_row_col: Mapping that maps the row numbers on the - displayed screen (starting from zero for the first visible line) to - (row, col) tuples pointing to the row and column of the :class:`.UIContent`. - :param rowcol_to_yx: Mapping that maps (row, column) tuples representing - coordinates of the :class:`UIContent` to (y, x) absolute coordinates at - the rendered screen. + :param window_width: The width of the window that displays the content, + without the margins. + :param window_height: The height of the window that displays the content. + :param configured_scroll_offsets: The scroll offsets as configured for the + :class:`Window` instance. + :param visible_line_to_row_col: Mapping that maps the row numbers on the + displayed screen (starting from zero for the first visible line) to + (row, col) tuples pointing to the row and column of the :class:`.UIContent`. + :param rowcol_to_yx: Mapping that maps (row, column) tuples representing + coordinates of the :class:`UIContent` to (y, x) absolute coordinates at + the rendered screen. """ - def __init__(self, ui_content, horizontal_scroll, vertical_scroll, - window_width, window_height, - configured_scroll_offsets, - visible_line_to_row_col, rowcol_to_yx, - x_offset, y_offset, wrap_lines): - assert isinstance(ui_content, UIContent) - assert isinstance(horizontal_scroll, int) - assert isinstance(vertical_scroll, int) - assert isinstance(window_width, int) - assert isinstance(window_height, int) - assert isinstance(configured_scroll_offsets, ScrollOffsets) - assert isinstance(visible_line_to_row_col, dict) - assert isinstance(rowcol_to_yx, dict) - assert isinstance(x_offset, int) - assert isinstance(y_offset, int) - assert isinstance(wrap_lines, bool) - - self.ui_content = ui_content + def __init__(self, ui_content, horizontal_scroll, vertical_scroll, + window_width, window_height, + configured_scroll_offsets, + visible_line_to_row_col, rowcol_to_yx, + x_offset, y_offset, wrap_lines): + assert isinstance(ui_content, UIContent) + assert isinstance(horizontal_scroll, int) + assert isinstance(vertical_scroll, int) + assert isinstance(window_width, int) + assert isinstance(window_height, int) + assert isinstance(configured_scroll_offsets, ScrollOffsets) + assert isinstance(visible_line_to_row_col, dict) + assert isinstance(rowcol_to_yx, dict) + assert isinstance(x_offset, int) + assert isinstance(y_offset, int) + assert isinstance(wrap_lines, bool) + + self.ui_content = ui_content self.vertical_scroll = vertical_scroll - self.window_width = window_width # Width without margins. + self.window_width = window_width # Width without margins. self.window_height = window_height - + self.configured_scroll_offsets = configured_scroll_offsets - self.visible_line_to_row_col = visible_line_to_row_col - self.wrap_lines = wrap_lines - - self._rowcol_to_yx = rowcol_to_yx # row/col from input to absolute y/x - # screen coordinates. - self._x_offset = x_offset - self._y_offset = y_offset - + self.visible_line_to_row_col = visible_line_to_row_col + self.wrap_lines = wrap_lines + + self._rowcol_to_yx = rowcol_to_yx # row/col from input to absolute y/x + # screen coordinates. + self._x_offset = x_offset + self._y_offset = y_offset + @property - def visible_line_to_input_line(self): - return dict( - (visible_line, rowcol[0]) - for visible_line, rowcol in self.visible_line_to_row_col.items()) - - @property - def cursor_position(self): + def visible_line_to_input_line(self): + return dict( + (visible_line, rowcol[0]) + for visible_line, rowcol in self.visible_line_to_row_col.items()) + + @property + def cursor_position(self): """ - Return the cursor position coordinates, relative to the left/top corner - of the rendered screen. + Return the cursor position coordinates, relative to the left/top corner + of the rendered screen. """ - cpos = self.ui_content.cursor_position - y, x = self._rowcol_to_yx[cpos.y, cpos.x] - return Point(x=x - self._x_offset, y=y - self._y_offset) + cpos = self.ui_content.cursor_position + y, x = self._rowcol_to_yx[cpos.y, cpos.x] + return Point(x=x - self._x_offset, y=y - self._y_offset) @property - def applied_scroll_offsets(self): - """ - Return a :class:`.ScrollOffsets` instance that indicates the actual - offset. This can be less than or equal to what's configured. E.g, when - the cursor is completely at the top, the top offset will be zero rather - than what's configured. - """ - if self.displayed_lines[0] == 0: - top = 0 - else: - # Get row where the cursor is displayed. - y = self.input_line_to_visible_line[self.ui_content.cursor_position.y] - top = min(y, self.configured_scroll_offsets.top) - - return ScrollOffsets( - top=top, - bottom=min(self.ui_content.line_count - self.displayed_lines[-1] - 1, - self.configured_scroll_offsets.bottom), - - # For left/right, it probably doesn't make sense to return something. - # (We would have to calculate the widths of all the lines and keep - # double width characters in mind.) - left=0, right=0) - + def applied_scroll_offsets(self): + """ + Return a :class:`.ScrollOffsets` instance that indicates the actual + offset. This can be less than or equal to what's configured. E.g, when + the cursor is completely at the top, the top offset will be zero rather + than what's configured. + """ + if self.displayed_lines[0] == 0: + top = 0 + else: + # Get row where the cursor is displayed. + y = self.input_line_to_visible_line[self.ui_content.cursor_position.y] + top = min(y, self.configured_scroll_offsets.top) + + return ScrollOffsets( + top=top, + bottom=min(self.ui_content.line_count - self.displayed_lines[-1] - 1, + self.configured_scroll_offsets.bottom), + + # For left/right, it probably doesn't make sense to return something. + # (We would have to calculate the widths of all the lines and keep + # double width characters in mind.) + left=0, right=0) + @property - def displayed_lines(self): - """ - List of all the visible rows. (Line numbers of the input buffer.) - The last line may not be entirely visible. - """ - return sorted(row for row, col in self.visible_line_to_row_col.values()) - - @property - def input_line_to_visible_line(self): - """ - Return the dictionary mapping the line numbers of the input buffer to - the lines of the screen. When a line spans several rows at the screen, - the first row appears in the dictionary. - """ - result = {} - for k, v in self.visible_line_to_input_line.items(): - if v in result: - result[v] = min(result[v], k) - else: - result[v] = k - return result - + def displayed_lines(self): + """ + List of all the visible rows. (Line numbers of the input buffer.) + The last line may not be entirely visible. + """ + return sorted(row for row, col in self.visible_line_to_row_col.values()) + + @property + def input_line_to_visible_line(self): + """ + Return the dictionary mapping the line numbers of the input buffer to + the lines of the screen. When a line spans several rows at the screen, + the first row appears in the dictionary. + """ + result = {} + for k, v in self.visible_line_to_input_line.items(): + if v in result: + result[v] = min(result[v], k) + else: + result[v] = k + return result + def first_visible_line(self, after_scroll_offset=False): """ Return the line number (0 based) of the input document that corresponds with the first visible line. """ if after_scroll_offset: - return self.displayed_lines[self.applied_scroll_offsets.top] - else: - return self.displayed_lines[0] + return self.displayed_lines[self.applied_scroll_offsets.top] + else: + return self.displayed_lines[0] def last_visible_line(self, before_scroll_offset=False): """ Like `first_visible_line`, but for the last visible line. """ if before_scroll_offset: - return self.displayed_lines[-1 - self.applied_scroll_offsets.bottom] - else: - return self.displayed_lines[-1] + return self.displayed_lines[-1 - self.applied_scroll_offsets.bottom] + else: + return self.displayed_lines[-1] def center_visible_line(self, before_scroll_offset=False, after_scroll_offset=False): @@ -737,7 +737,7 @@ class WindowRenderInfo(object): """ return (self.first_visible_line(after_scroll_offset) + (self.last_visible_line(before_scroll_offset) - - self.first_visible_line(after_scroll_offset)) // 2 + self.first_visible_line(after_scroll_offset)) // 2 ) @property @@ -745,14 +745,14 @@ class WindowRenderInfo(object): """ The full height of the user control. """ - return self.ui_content.line_count + return self.ui_content.line_count @property def full_height_visible(self): """ True when the full height is visible (There is no vertical scroll.) """ - return self.vertical_scroll == 0 and self.last_visible_line() == self.content_height + return self.vertical_scroll == 0 and self.last_visible_line() == self.content_height @property def top_visible(self): @@ -766,7 +766,7 @@ class WindowRenderInfo(object): """ True when the bottom of the buffer is visible. """ - return self.last_visible_line() == self.content_height - 1 + return self.last_visible_line() == self.content_height - 1 @property def vertical_scroll_percentage(self): @@ -774,22 +774,22 @@ class WindowRenderInfo(object): Vertical scroll as a percentage. (0 means: the top is visible, 100 means: the bottom is visible.) """ - if self.bottom_visible: - return 100 - else: - return (100 * self.vertical_scroll // self.content_height) - - def get_height_for_line(self, lineno): - """ - Return the height of the given line. - (The height that it would take, if this line became visible.) - """ - if self.wrap_lines: - return self.ui_content.get_height_for_line(lineno, self.window_width) - else: - return 1 - - + if self.bottom_visible: + return 100 + else: + return (100 * self.vertical_scroll // self.content_height) + + def get_height_for_line(self, lineno): + """ + Return the height of the given line. + (The height that it would take, if this line became visible.) + """ + if self.wrap_lines: + return self.ui_content.get_height_for_line(lineno, self.window_width) + else: + return 1 + + class ScrollOffsets(object): """ Scroll offsets for the :class:`.Window` class. @@ -797,46 +797,46 @@ class ScrollOffsets(object): Note that left/right offsets only make sense if line wrapping is disabled. """ def __init__(self, top=0, bottom=0, left=0, right=0): - assert isinstance(top, Integer) - assert isinstance(bottom, Integer) - assert isinstance(left, Integer) - assert isinstance(right, Integer) - - self._top = top - self._bottom = bottom - self._left = left - self._right = right - - @property - def top(self): - return int(self._top) - - @property - def bottom(self): - return int(self._bottom) - - @property - def left(self): - return int(self._left) - - @property - def right(self): - return int(self._right) - + assert isinstance(top, Integer) + assert isinstance(bottom, Integer) + assert isinstance(left, Integer) + assert isinstance(right, Integer) + + self._top = top + self._bottom = bottom + self._left = left + self._right = right + + @property + def top(self): + return int(self._top) + + @property + def bottom(self): + return int(self._bottom) + + @property + def left(self): + return int(self._left) + + @property + def right(self): + return int(self._right) + def __repr__(self): return 'ScrollOffsets(top=%r, bottom=%r, left=%r, right=%r)' % ( self.top, self.bottom, self.left, self.right) -class ColorColumn(object): - def __init__(self, position, token=Token.ColorColumn): - self.position = position - self.token = token - - -_in_insert_mode = ViInsertMode() | EmacsInsertMode() - - +class ColorColumn(object): + def __init__(self, position, token=Token.ColorColumn): + self.position = position + self.token = token + + +_in_insert_mode = ViInsertMode() | EmacsInsertMode() + + class Window(Container): """ Container that holds a control. @@ -865,8 +865,8 @@ class Window(Container): anymore, while there is still empty space available at the bottom of the window. In the Vi editor for instance, this is possible. You will see tildes while the top part of the body is hidden. - :param wrap_lines: A `bool` or :class:`~prompt_toolkit.filters.CLIFilter` - instance. When True, don't scroll horizontally, but wrap lines instead. + :param wrap_lines: A `bool` or :class:`~prompt_toolkit.filters.CLIFilter` + instance. When True, don't scroll horizontally, but wrap lines instead. :param get_vertical_scroll: Callable that takes this window instance as input and returns a preferred vertical scroll. (When this is `None`, the scroll is only determined by the last and @@ -877,25 +877,25 @@ class Window(Container): :class:`~prompt_toolkit.filters.CLIFilter` instance. When True, never display the cursor, even when the user control specifies a cursor position. - :param cursorline: A `bool` or :class:`~prompt_toolkit.filters.CLIFilter` - instance. When True, display a cursorline. - :param cursorcolumn: A `bool` or :class:`~prompt_toolkit.filters.CLIFilter` - instance. When True, display a cursorcolumn. - :param get_colorcolumns: A callable that takes a `CommandLineInterface` and - returns a a list of :class:`.ColorColumn` instances that describe the - columns to be highlighted. - :param cursorline_token: The token to be used for highlighting the current line, - if `cursorline` is True. - :param cursorcolumn_token: The token to be used for highlighting the current line, - if `cursorcolumn` is True. + :param cursorline: A `bool` or :class:`~prompt_toolkit.filters.CLIFilter` + instance. When True, display a cursorline. + :param cursorcolumn: A `bool` or :class:`~prompt_toolkit.filters.CLIFilter` + instance. When True, display a cursorcolumn. + :param get_colorcolumns: A callable that takes a `CommandLineInterface` and + returns a a list of :class:`.ColorColumn` instances that describe the + columns to be highlighted. + :param cursorline_token: The token to be used for highlighting the current line, + if `cursorline` is True. + :param cursorcolumn_token: The token to be used for highlighting the current line, + if `cursorcolumn` is True. """ def __init__(self, content, width=None, height=None, get_width=None, get_height=None, dont_extend_width=False, dont_extend_height=False, left_margins=None, right_margins=None, scroll_offsets=None, - allow_scroll_beyond_bottom=False, wrap_lines=False, - get_vertical_scroll=None, get_horizontal_scroll=None, always_hide_cursor=False, - cursorline=False, cursorcolumn=False, get_colorcolumns=None, - cursorline_token=Token.CursorLine, cursorcolumn_token=Token.CursorColumn): + allow_scroll_beyond_bottom=False, wrap_lines=False, + get_vertical_scroll=None, get_horizontal_scroll=None, always_hide_cursor=False, + cursorline=False, cursorcolumn=False, get_colorcolumns=None, + cursorline_token=Token.CursorLine, cursorcolumn_token=Token.CursorColumn): assert isinstance(content, UIControl) assert width is None or isinstance(width, LayoutDimension) assert height is None or isinstance(height, LayoutDimension) @@ -908,13 +908,13 @@ class Window(Container): assert right_margins is None or all(isinstance(m, Margin) for m in right_margins) assert get_vertical_scroll is None or callable(get_vertical_scroll) assert get_horizontal_scroll is None or callable(get_horizontal_scroll) - assert get_colorcolumns is None or callable(get_colorcolumns) + assert get_colorcolumns is None or callable(get_colorcolumns) self.allow_scroll_beyond_bottom = to_cli_filter(allow_scroll_beyond_bottom) self.always_hide_cursor = to_cli_filter(always_hide_cursor) - self.wrap_lines = to_cli_filter(wrap_lines) - self.cursorline = to_cli_filter(cursorline) - self.cursorcolumn = to_cli_filter(cursorcolumn) + self.wrap_lines = to_cli_filter(wrap_lines) + self.cursorline = to_cli_filter(cursorline) + self.cursorcolumn = to_cli_filter(cursorcolumn) self.content = content self.dont_extend_width = dont_extend_width @@ -926,13 +926,13 @@ class Window(Container): self.get_horizontal_scroll = get_horizontal_scroll self._width = get_width or (lambda cli: width) self._height = get_height or (lambda cli: height) - self.get_colorcolumns = get_colorcolumns or (lambda cli: []) - self.cursorline_token = cursorline_token - self.cursorcolumn_token = cursorcolumn_token + self.get_colorcolumns = get_colorcolumns or (lambda cli: []) + self.cursorline_token = cursorline_token + self.cursorcolumn_token = cursorcolumn_token # Cache for the screens generated by the margin. - self._ui_content_cache = SimpleCache(maxsize=8) - self._margin_width_cache = SimpleCache(maxsize=1) + self._ui_content_cache = SimpleCache(maxsize=8) + self._margin_width_cache = SimpleCache(maxsize=1) self.reset() @@ -946,41 +946,41 @@ class Window(Container): self.vertical_scroll = 0 self.horizontal_scroll = 0 - # Vertical scroll 2: this is the vertical offset that a line is - # scrolled if a single line (the one that contains the cursor) consumes - # all of the vertical space. - self.vertical_scroll_2 = 0 - + # Vertical scroll 2: this is the vertical offset that a line is + # scrolled if a single line (the one that contains the cursor) consumes + # all of the vertical space. + self.vertical_scroll_2 = 0 + #: Keep render information (mappings between buffer input and render #: output.) self.render_info = None - def _get_margin_width(self, cli, margin): - """ - Return the width for this margin. - (Calculate only once per render time.) - """ - # Margin.get_width, needs to have a UIContent instance. - def get_ui_content(): - return self._get_ui_content(cli, width=0, height=0) - - def get_width(): - return margin.get_width(cli, get_ui_content) - - key = (margin, cli.render_counter) - return self._margin_width_cache.get(key, get_width) - + def _get_margin_width(self, cli, margin): + """ + Return the width for this margin. + (Calculate only once per render time.) + """ + # Margin.get_width, needs to have a UIContent instance. + def get_ui_content(): + return self._get_ui_content(cli, width=0, height=0) + + def get_width(): + return margin.get_width(cli, get_ui_content) + + key = (margin, cli.render_counter) + return self._margin_width_cache.get(key, get_width) + def preferred_width(self, cli, max_available_width): - # Calculate the width of the margin. - total_margin_width = sum(self._get_margin_width(cli, m) for m in + # Calculate the width of the margin. + total_margin_width = sum(self._get_margin_width(cli, m) for m in self.left_margins + self.right_margins) - # Window of the content. (Can be `None`.) + # Window of the content. (Can be `None`.) preferred_width = self.content.preferred_width( cli, max_available_width - total_margin_width) if preferred_width is not None: - # Include width of the margins. + # Include width of the margins. preferred_width += total_margin_width # Merge. @@ -989,15 +989,15 @@ class Window(Container): preferred=preferred_width, dont_extend=self.dont_extend_width) - def preferred_height(self, cli, width, max_available_height): - total_margin_width = sum(self._get_margin_width(cli, m) for m in - self.left_margins + self.right_margins) - wrap_lines = self.wrap_lines(cli) - + def preferred_height(self, cli, width, max_available_height): + total_margin_width = sum(self._get_margin_width(cli, m) for m in + self.left_margins + self.right_margins) + wrap_lines = self.wrap_lines(cli) + return self._merge_dimensions( dimension=self._height(cli), - preferred=self.content.preferred_height( - cli, width - total_margin_width, max_available_height, wrap_lines), + preferred=self.content.preferred_height( + cli, width - total_margin_width, max_available_height, wrap_lines), dont_extend=self.dont_extend_height) @staticmethod @@ -1030,115 +1030,115 @@ class Window(Container): else: max_ = dimension.max - return LayoutDimension( - min=dimension.min, max=max_, - preferred=preferred, weight=dimension.weight) - - def _get_ui_content(self, cli, width, height): - """ - Create a `UIContent` instance. - """ - def get_content(): - return self.content.create_content(cli, width=width, height=height) - - key = (cli.render_counter, width, height) - return self._ui_content_cache.get(key, get_content) - - def _get_digraph_char(self, cli): - " Return `False`, or the Digraph symbol to be used. " + return LayoutDimension( + min=dimension.min, max=max_, + preferred=preferred, weight=dimension.weight) + + def _get_ui_content(self, cli, width, height): + """ + Create a `UIContent` instance. + """ + def get_content(): + return self.content.create_content(cli, width=width, height=height) + + key = (cli.render_counter, width, height) + return self._ui_content_cache.get(key, get_content) + + def _get_digraph_char(self, cli): + " Return `False`, or the Digraph symbol to be used. " if cli.quoted_insert: return '^' - if cli.vi_state.waiting_for_digraph: - if cli.vi_state.digraph_symbol1: - return cli.vi_state.digraph_symbol1 - return '?' - return False - + if cli.vi_state.waiting_for_digraph: + if cli.vi_state.digraph_symbol1: + return cli.vi_state.digraph_symbol1 + return '?' + return False + def write_to_screen(self, cli, screen, mouse_handlers, write_position): """ Write window to screen. This renders the user control, the margins and copies everything over to the absolute position at the given screen. """ # Calculate margin sizes. - left_margin_widths = [self._get_margin_width(cli, m) for m in self.left_margins] - right_margin_widths = [self._get_margin_width(cli, m) for m in self.right_margins] + left_margin_widths = [self._get_margin_width(cli, m) for m in self.left_margins] + right_margin_widths = [self._get_margin_width(cli, m) for m in self.right_margins] total_margin_width = sum(left_margin_widths + right_margin_widths) # Render UserControl. - ui_content = self.content.create_content( + ui_content = self.content.create_content( cli, write_position.width - total_margin_width, write_position.height) - assert isinstance(ui_content, UIContent) + assert isinstance(ui_content, UIContent) # Scroll content. - wrap_lines = self.wrap_lines(cli) - scroll_func = self._scroll_when_linewrapping if wrap_lines else self._scroll_without_linewrapping - - scroll_func( - ui_content, write_position.width - total_margin_width, write_position.height, cli) - - # Write body - visible_line_to_row_col, rowcol_to_yx = self._copy_body( - cli, ui_content, screen, write_position, - sum(left_margin_widths), write_position.width - total_margin_width, - self.vertical_scroll, self.horizontal_scroll, - has_focus=self.content.has_focus(cli), - wrap_lines=wrap_lines, highlight_lines=True, - vertical_scroll_2=self.vertical_scroll_2, - always_hide_cursor=self.always_hide_cursor(cli)) - + wrap_lines = self.wrap_lines(cli) + scroll_func = self._scroll_when_linewrapping if wrap_lines else self._scroll_without_linewrapping + + scroll_func( + ui_content, write_position.width - total_margin_width, write_position.height, cli) + + # Write body + visible_line_to_row_col, rowcol_to_yx = self._copy_body( + cli, ui_content, screen, write_position, + sum(left_margin_widths), write_position.width - total_margin_width, + self.vertical_scroll, self.horizontal_scroll, + has_focus=self.content.has_focus(cli), + wrap_lines=wrap_lines, highlight_lines=True, + vertical_scroll_2=self.vertical_scroll_2, + always_hide_cursor=self.always_hide_cursor(cli)) + # Remember render info. (Set before generating the margins. They need this.) - x_offset=write_position.xpos + sum(left_margin_widths) - y_offset=write_position.ypos - + x_offset=write_position.xpos + sum(left_margin_widths) + y_offset=write_position.ypos + self.render_info = WindowRenderInfo( - ui_content=ui_content, + ui_content=ui_content, horizontal_scroll=self.horizontal_scroll, vertical_scroll=self.vertical_scroll, - window_width=write_position.width - total_margin_width, + window_width=write_position.width - total_margin_width, window_height=write_position.height, configured_scroll_offsets=self.scroll_offsets, - visible_line_to_row_col=visible_line_to_row_col, - rowcol_to_yx=rowcol_to_yx, - x_offset=x_offset, - y_offset=y_offset, - wrap_lines=wrap_lines) + visible_line_to_row_col=visible_line_to_row_col, + rowcol_to_yx=rowcol_to_yx, + x_offset=x_offset, + y_offset=y_offset, + wrap_lines=wrap_lines) # Set mouse handlers. def mouse_handler(cli, mouse_event): """ Wrapper around the mouse_handler of the `UIControl` that turns - screen coordinates into line coordinates. """ - # Find row/col position first. - yx_to_rowcol = dict((v, k) for k, v in rowcol_to_yx.items()) - y = mouse_event.position.y - x = mouse_event.position.x - - # If clicked below the content area, look for a position in the - # last line instead. - max_y = write_position.ypos + len(visible_line_to_row_col) - 1 - y = min(max_y, y) - - while x >= 0: - try: - row, col = yx_to_rowcol[y, x] - except KeyError: - # Try again. (When clicking on the right side of double - # width characters, or on the right side of the input.) - x -= 1 - else: - # Found position, call handler of UIControl. - result = self.content.mouse_handler( - cli, MouseEvent(position=Point(x=col, y=row), - event_type=mouse_event.event_type)) - break - else: - # nobreak. - # (No x/y coordinate found for the content. This happens in - # case of a FillControl, that only specifies a background, but - # doesn't have a content. Report (0,0) instead.) - result = self.content.mouse_handler( - cli, MouseEvent(position=Point(x=0, y=0), - event_type=mouse_event.event_type)) - + screen coordinates into line coordinates. """ + # Find row/col position first. + yx_to_rowcol = dict((v, k) for k, v in rowcol_to_yx.items()) + y = mouse_event.position.y + x = mouse_event.position.x + + # If clicked below the content area, look for a position in the + # last line instead. + max_y = write_position.ypos + len(visible_line_to_row_col) - 1 + y = min(max_y, y) + + while x >= 0: + try: + row, col = yx_to_rowcol[y, x] + except KeyError: + # Try again. (When clicking on the right side of double + # width characters, or on the right side of the input.) + x -= 1 + else: + # Found position, call handler of UIControl. + result = self.content.mouse_handler( + cli, MouseEvent(position=Point(x=col, y=row), + event_type=mouse_event.event_type)) + break + else: + # nobreak. + # (No x/y coordinate found for the content. This happens in + # case of a FillControl, that only specifies a background, but + # doesn't have a content. Report (0,0) instead.) + result = self.content.mouse_handler( + cli, MouseEvent(position=Point(x=0, y=0), + event_type=mouse_event.event_type)) + # If it returns NotImplemented, handle it here. if result == NotImplemented: return self._mouse_handler(cli, mouse_event) @@ -1160,17 +1160,17 @@ class Window(Container): # Retrieve margin tokens. tokens = m.create_margin(cli, self.render_info, width, write_position.height) - # Turn it into a UIContent object. + # Turn it into a UIContent object. # already rendered those tokens using this size.) - return TokenListControl.static(tokens).create_content( - cli, width + 1, write_position.height) + return TokenListControl.static(tokens).create_content( + cli, width + 1, write_position.height) for m, width in zip(self.left_margins, left_margin_widths): # Create screen for margin. margin_screen = render_margin(m, width) # Copy and shift X. - self._copy_margin(cli, margin_screen, screen, write_position, move_x, width) + self._copy_margin(cli, margin_screen, screen, write_position, move_x, width) move_x += width move_x = write_position.width - sum(right_margin_widths) @@ -1180,351 +1180,351 @@ class Window(Container): margin_screen = render_margin(m, width) # Copy and shift X. - self._copy_margin(cli, margin_screen, screen, write_position, move_x, width) + self._copy_margin(cli, margin_screen, screen, write_position, move_x, width) move_x += width - def _copy_body(self, cli, ui_content, new_screen, write_position, move_x, - width, vertical_scroll=0, horizontal_scroll=0, - has_focus=False, wrap_lines=False, highlight_lines=False, - vertical_scroll_2=0, always_hide_cursor=False): + def _copy_body(self, cli, ui_content, new_screen, write_position, move_x, + width, vertical_scroll=0, horizontal_scroll=0, + has_focus=False, wrap_lines=False, highlight_lines=False, + vertical_scroll_2=0, always_hide_cursor=False): """ - Copy the UIContent into the output screen. + Copy the UIContent into the output screen. """ xpos = write_position.xpos + move_x ypos = write_position.ypos - line_count = ui_content.line_count + line_count = ui_content.line_count new_buffer = new_screen.data_buffer - empty_char = _CHAR_CACHE['', Token] - ZeroWidthEscape = Token.ZeroWidthEscape - - # Map visible line number to (row, col) of input. - # 'col' will always be zero if line wrapping is off. - visible_line_to_row_col = {} - rowcol_to_yx = {} # Maps (row, col) from the input to (y, x) screen coordinates. - - # Fill background with default_char first. - default_char = ui_content.default_char - - if default_char: - for y in range(ypos, ypos + write_position.height): - new_buffer_row = new_buffer[y] - for x in range(xpos, xpos + width): - new_buffer_row[x] = default_char - - # Copy content. - def copy(): - y = - vertical_scroll_2 - lineno = vertical_scroll - - while y < write_position.height and lineno < line_count: - # Take the next line and copy it in the real screen. - line = ui_content.get_line(lineno) - - col = 0 - x = -horizontal_scroll - - visible_line_to_row_col[y] = (lineno, horizontal_scroll) - new_buffer_row = new_buffer[y + ypos] - - for token, text in line: - # Remember raw VT escape sequences. (E.g. FinalTerm's - # escape sequences.) - if token == ZeroWidthEscape: - new_screen.zero_width_escapes[y + ypos][x + xpos] += text - continue - - for c in text: - char = _CHAR_CACHE[c, token] - char_width = char.width - - # Wrap when the line width is exceeded. - if wrap_lines and x + char_width > width: - visible_line_to_row_col[y + 1] = ( - lineno, visible_line_to_row_col[y][1] + x) - y += 1 - x = -horizontal_scroll # This would be equal to zero. - # (horizontal_scroll=0 when wrap_lines.) - new_buffer_row = new_buffer[y + ypos] - - if y >= write_position.height: - return y # Break out of all for loops. - - # Set character in screen and shift 'x'. - if x >= 0 and y >= 0 and x < write_position.width: - new_buffer_row[x + xpos] = char - - # When we print a multi width character, make sure - # to erase the neighbous positions in the screen. - # (The empty string if different from everything, - # so next redraw this cell will repaint anyway.) - if char_width > 1: - for i in range(1, char_width): - new_buffer_row[x + xpos + i] = empty_char - - # If this is a zero width characters, then it's - # probably part of a decomposed unicode character. - # See: https://en.wikipedia.org/wiki/Unicode_equivalence - # Merge it in the previous cell. - elif char_width == 0 and x - 1 >= 0: - prev_char = new_buffer_row[x + xpos - 1] - char2 = _CHAR_CACHE[prev_char.char + c, prev_char.token] - new_buffer_row[x + xpos - 1] = char2 - - # Keep track of write position for each character. - rowcol_to_yx[lineno, col] = (y + ypos, x + xpos) - - col += 1 - x += char_width - - lineno += 1 - y += 1 - return y - - y = copy() - - def cursor_pos_to_screen_pos(row, col): - " Translate row/col from UIContent to real Screen coordinates. " - try: - y, x = rowcol_to_yx[row, col] - except KeyError: - # Normally this should never happen. (It is a bug, if it happens.) - # But to be sure, return (0, 0) - return Point(y=0, x=0) - - # raise ValueError( - # 'Invalid position. row=%r col=%r, vertical_scroll=%r, ' - # 'horizontal_scroll=%r, height=%r' % - # (row, col, vertical_scroll, horizontal_scroll, write_position.height)) + empty_char = _CHAR_CACHE['', Token] + ZeroWidthEscape = Token.ZeroWidthEscape + + # Map visible line number to (row, col) of input. + # 'col' will always be zero if line wrapping is off. + visible_line_to_row_col = {} + rowcol_to_yx = {} # Maps (row, col) from the input to (y, x) screen coordinates. + + # Fill background with default_char first. + default_char = ui_content.default_char + + if default_char: + for y in range(ypos, ypos + write_position.height): + new_buffer_row = new_buffer[y] + for x in range(xpos, xpos + width): + new_buffer_row[x] = default_char + + # Copy content. + def copy(): + y = - vertical_scroll_2 + lineno = vertical_scroll + + while y < write_position.height and lineno < line_count: + # Take the next line and copy it in the real screen. + line = ui_content.get_line(lineno) + + col = 0 + x = -horizontal_scroll + + visible_line_to_row_col[y] = (lineno, horizontal_scroll) + new_buffer_row = new_buffer[y + ypos] + + for token, text in line: + # Remember raw VT escape sequences. (E.g. FinalTerm's + # escape sequences.) + if token == ZeroWidthEscape: + new_screen.zero_width_escapes[y + ypos][x + xpos] += text + continue + + for c in text: + char = _CHAR_CACHE[c, token] + char_width = char.width + + # Wrap when the line width is exceeded. + if wrap_lines and x + char_width > width: + visible_line_to_row_col[y + 1] = ( + lineno, visible_line_to_row_col[y][1] + x) + y += 1 + x = -horizontal_scroll # This would be equal to zero. + # (horizontal_scroll=0 when wrap_lines.) + new_buffer_row = new_buffer[y + ypos] + + if y >= write_position.height: + return y # Break out of all for loops. + + # Set character in screen and shift 'x'. + if x >= 0 and y >= 0 and x < write_position.width: + new_buffer_row[x + xpos] = char + + # When we print a multi width character, make sure + # to erase the neighbous positions in the screen. + # (The empty string if different from everything, + # so next redraw this cell will repaint anyway.) + if char_width > 1: + for i in range(1, char_width): + new_buffer_row[x + xpos + i] = empty_char + + # If this is a zero width characters, then it's + # probably part of a decomposed unicode character. + # See: https://en.wikipedia.org/wiki/Unicode_equivalence + # Merge it in the previous cell. + elif char_width == 0 and x - 1 >= 0: + prev_char = new_buffer_row[x + xpos - 1] + char2 = _CHAR_CACHE[prev_char.char + c, prev_char.token] + new_buffer_row[x + xpos - 1] = char2 + + # Keep track of write position for each character. + rowcol_to_yx[lineno, col] = (y + ypos, x + xpos) + + col += 1 + x += char_width + + lineno += 1 + y += 1 + return y + + y = copy() + + def cursor_pos_to_screen_pos(row, col): + " Translate row/col from UIContent to real Screen coordinates. " + try: + y, x = rowcol_to_yx[row, col] + except KeyError: + # Normally this should never happen. (It is a bug, if it happens.) + # But to be sure, return (0, 0) + return Point(y=0, x=0) + + # raise ValueError( + # 'Invalid position. row=%r col=%r, vertical_scroll=%r, ' + # 'horizontal_scroll=%r, height=%r' % + # (row, col, vertical_scroll, horizontal_scroll, write_position.height)) else: - return Point(y=y, x=x) - - # Set cursor and menu positions. - if ui_content.cursor_position: - screen_cursor_position = cursor_pos_to_screen_pos( - ui_content.cursor_position.y, ui_content.cursor_position.x) - - if has_focus: - new_screen.cursor_position = screen_cursor_position - - if always_hide_cursor: - new_screen.show_cursor = False - else: - new_screen.show_cursor = ui_content.show_cursor - - self._highlight_digraph(cli, new_screen) - - if highlight_lines: - self._highlight_cursorlines( - cli, new_screen, screen_cursor_position, xpos, ypos, width, - write_position.height) - - # Draw input characters from the input processor queue. - if has_focus and ui_content.cursor_position: - self._show_input_processor_key_buffer(cli, new_screen) - - # Set menu position. - if not new_screen.menu_position and ui_content.menu_position: - new_screen.menu_position = cursor_pos_to_screen_pos( - ui_content.menu_position.y, ui_content.menu_position.x) - - # Update output screne height. - new_screen.height = max(new_screen.height, ypos + write_position.height) - - return visible_line_to_row_col, rowcol_to_yx - - def _highlight_digraph(self, cli, new_screen): - """ - When we are in Vi digraph mode, put a question mark underneath the - cursor. - """ - digraph_char = self._get_digraph_char(cli) - if digraph_char: - cpos = new_screen.cursor_position - new_screen.data_buffer[cpos.y][cpos.x] = \ - _CHAR_CACHE[digraph_char, Token.Digraph] - - def _show_input_processor_key_buffer(self, cli, new_screen): - """ - When the user is typing a key binding that consists of several keys, - display the last pressed key if the user is in insert mode and the key - is meaningful to be displayed. - E.g. Some people want to bind 'jj' to escape in Vi insert mode. But the - first 'j' needs to be displayed in order to get some feedback. - """ - key_buffer = cli.input_processor.key_buffer - - if key_buffer and _in_insert_mode(cli) and not cli.is_done: - # The textual data for the given key. (Can be a VT100 escape - # sequence.) - data = key_buffer[-1].data - - # Display only if this is a 1 cell width character. - if get_cwidth(data) == 1: - cpos = new_screen.cursor_position - new_screen.data_buffer[cpos.y][cpos.x] = \ - _CHAR_CACHE[data, Token.PartialKeyBinding] - - def _highlight_cursorlines(self, cli, new_screen, cpos, x, y, width, height): - """ - Highlight cursor row/column. - """ - cursor_line_token = (':', ) + self.cursorline_token - cursor_column_token = (':', ) + self.cursorcolumn_token - - data_buffer = new_screen.data_buffer - - # Highlight cursor line. - if self.cursorline(cli): - row = data_buffer[cpos.y] - for x in range(x, x + width): - original_char = row[x] - row[x] = _CHAR_CACHE[ - original_char.char, original_char.token + cursor_line_token] - - # Highlight cursor column. - if self.cursorcolumn(cli): - for y2 in range(y, y + height): - row = data_buffer[y2] - original_char = row[cpos.x] - row[cpos.x] = _CHAR_CACHE[ - original_char.char, original_char.token + cursor_column_token] - - # Highlight color columns - for cc in self.get_colorcolumns(cli): - assert isinstance(cc, ColorColumn) - color_column_token = (':', ) + cc.token - column = cc.position - - for y2 in range(y, y + height): - row = data_buffer[y2] - original_char = row[column] - row[column] = _CHAR_CACHE[ - original_char.char, original_char.token + color_column_token] - - def _copy_margin(self, cli, lazy_screen, new_screen, write_position, move_x, width): - """ + return Point(y=y, x=x) + + # Set cursor and menu positions. + if ui_content.cursor_position: + screen_cursor_position = cursor_pos_to_screen_pos( + ui_content.cursor_position.y, ui_content.cursor_position.x) + + if has_focus: + new_screen.cursor_position = screen_cursor_position + + if always_hide_cursor: + new_screen.show_cursor = False + else: + new_screen.show_cursor = ui_content.show_cursor + + self._highlight_digraph(cli, new_screen) + + if highlight_lines: + self._highlight_cursorlines( + cli, new_screen, screen_cursor_position, xpos, ypos, width, + write_position.height) + + # Draw input characters from the input processor queue. + if has_focus and ui_content.cursor_position: + self._show_input_processor_key_buffer(cli, new_screen) + + # Set menu position. + if not new_screen.menu_position and ui_content.menu_position: + new_screen.menu_position = cursor_pos_to_screen_pos( + ui_content.menu_position.y, ui_content.menu_position.x) + + # Update output screne height. + new_screen.height = max(new_screen.height, ypos + write_position.height) + + return visible_line_to_row_col, rowcol_to_yx + + def _highlight_digraph(self, cli, new_screen): + """ + When we are in Vi digraph mode, put a question mark underneath the + cursor. + """ + digraph_char = self._get_digraph_char(cli) + if digraph_char: + cpos = new_screen.cursor_position + new_screen.data_buffer[cpos.y][cpos.x] = \ + _CHAR_CACHE[digraph_char, Token.Digraph] + + def _show_input_processor_key_buffer(self, cli, new_screen): + """ + When the user is typing a key binding that consists of several keys, + display the last pressed key if the user is in insert mode and the key + is meaningful to be displayed. + E.g. Some people want to bind 'jj' to escape in Vi insert mode. But the + first 'j' needs to be displayed in order to get some feedback. + """ + key_buffer = cli.input_processor.key_buffer + + if key_buffer and _in_insert_mode(cli) and not cli.is_done: + # The textual data for the given key. (Can be a VT100 escape + # sequence.) + data = key_buffer[-1].data + + # Display only if this is a 1 cell width character. + if get_cwidth(data) == 1: + cpos = new_screen.cursor_position + new_screen.data_buffer[cpos.y][cpos.x] = \ + _CHAR_CACHE[data, Token.PartialKeyBinding] + + def _highlight_cursorlines(self, cli, new_screen, cpos, x, y, width, height): + """ + Highlight cursor row/column. + """ + cursor_line_token = (':', ) + self.cursorline_token + cursor_column_token = (':', ) + self.cursorcolumn_token + + data_buffer = new_screen.data_buffer + + # Highlight cursor line. + if self.cursorline(cli): + row = data_buffer[cpos.y] + for x in range(x, x + width): + original_char = row[x] + row[x] = _CHAR_CACHE[ + original_char.char, original_char.token + cursor_line_token] + + # Highlight cursor column. + if self.cursorcolumn(cli): + for y2 in range(y, y + height): + row = data_buffer[y2] + original_char = row[cpos.x] + row[cpos.x] = _CHAR_CACHE[ + original_char.char, original_char.token + cursor_column_token] + + # Highlight color columns + for cc in self.get_colorcolumns(cli): + assert isinstance(cc, ColorColumn) + color_column_token = (':', ) + cc.token + column = cc.position + + for y2 in range(y, y + height): + row = data_buffer[y2] + original_char = row[column] + row[column] = _CHAR_CACHE[ + original_char.char, original_char.token + color_column_token] + + def _copy_margin(self, cli, lazy_screen, new_screen, write_position, move_x, width): + """ Copy characters from the margin screen to the real screen. """ xpos = write_position.xpos + move_x ypos = write_position.ypos - margin_write_position = WritePosition(xpos, ypos, width, write_position.height) - self._copy_body(cli, lazy_screen, new_screen, margin_write_position, 0, width) - - def _scroll_when_linewrapping(self, ui_content, width, height, cli): - """ - Scroll to make sure the cursor position is visible and that we maintain - the requested scroll offset. - - Set `self.horizontal_scroll/vertical_scroll`. - """ - scroll_offsets_bottom = self.scroll_offsets.bottom - scroll_offsets_top = self.scroll_offsets.top - - # We don't have horizontal scrolling. - self.horizontal_scroll = 0 - - # If the current line consumes more than the whole window height, - # then we have to scroll vertically inside this line. (We don't take - # the scroll offsets into account for this.) - # Also, ignore the scroll offsets in this case. Just set the vertical - # scroll to this line. - if ui_content.get_height_for_line(ui_content.cursor_position.y, width) > height - scroll_offsets_top: - # Calculate the height of the text before the cursor, with the line - # containing the cursor included, and the character belowe the - # cursor included as well. - line = explode_tokens(ui_content.get_line(ui_content.cursor_position.y)) - text_before_cursor = token_list_to_text(line[:ui_content.cursor_position.x + 1]) - text_before_height = UIContent.get_height_for_text(text_before_cursor, width) - - # Adjust scroll offset. - self.vertical_scroll = ui_content.cursor_position.y - self.vertical_scroll_2 = min(text_before_height - 1, self.vertical_scroll_2) - self.vertical_scroll_2 = max(0, text_before_height - height, self.vertical_scroll_2) - return - else: - self.vertical_scroll_2 = 0 - - # Current line doesn't consume the whole height. Take scroll offsets into account. - def get_min_vertical_scroll(): - # Make sure that the cursor line is not below the bottom. - # (Calculate how many lines can be shown between the cursor and the .) - used_height = 0 - prev_lineno = ui_content.cursor_position.y - - for lineno in range(ui_content.cursor_position.y, -1, -1): - used_height += ui_content.get_height_for_line(lineno, width) - - if used_height > height - scroll_offsets_bottom: - return prev_lineno - else: - prev_lineno = lineno - return 0 - - def get_max_vertical_scroll(): - # Make sure that the cursor line is not above the top. - prev_lineno = ui_content.cursor_position.y - used_height = 0 - - for lineno in range(ui_content.cursor_position.y - 1, -1, -1): - used_height += ui_content.get_height_for_line(lineno, width) - - if used_height > scroll_offsets_top: - return prev_lineno - else: - prev_lineno = lineno - return prev_lineno - - def get_topmost_visible(): - """ - Calculate the upper most line that can be visible, while the bottom - is still visible. We should not allow scroll more than this if - `allow_scroll_beyond_bottom` is false. - """ - prev_lineno = ui_content.line_count - 1 - used_height = 0 - for lineno in range(ui_content.line_count - 1, -1, -1): - used_height += ui_content.get_height_for_line(lineno, width) - if used_height > height: - return prev_lineno - else: - prev_lineno = lineno - return prev_lineno - - # Scroll vertically. (Make sure that the whole line which contains the - # cursor is visible. - topmost_visible = get_topmost_visible() - - # Note: the `min(topmost_visible, ...)` is to make sure that we - # don't require scrolling up because of the bottom scroll offset, - # when we are at the end of the document. - self.vertical_scroll = max(self.vertical_scroll, min(topmost_visible, get_min_vertical_scroll())) - self.vertical_scroll = min(self.vertical_scroll, get_max_vertical_scroll()) - - # Disallow scrolling beyond bottom? - if not self.allow_scroll_beyond_bottom(cli): - self.vertical_scroll = min(self.vertical_scroll, topmost_visible) - - def _scroll_without_linewrapping(self, ui_content, width, height, cli): - """ - Scroll to make sure the cursor position is visible and that we maintain - the requested scroll offset. - - Set `self.horizontal_scroll/vertical_scroll`. - """ - cursor_position = ui_content.cursor_position or Point(0, 0) - - # Without line wrapping, we will never have to scroll vertically inside - # a single line. - self.vertical_scroll_2 = 0 - - if ui_content.line_count == 0: - self.vertical_scroll = 0 - self.horizontal_scroll = 0 - return - else: - current_line_text = token_list_to_text(ui_content.get_line(cursor_position.y)) - + margin_write_position = WritePosition(xpos, ypos, width, write_position.height) + self._copy_body(cli, lazy_screen, new_screen, margin_write_position, 0, width) + + def _scroll_when_linewrapping(self, ui_content, width, height, cli): + """ + Scroll to make sure the cursor position is visible and that we maintain + the requested scroll offset. + + Set `self.horizontal_scroll/vertical_scroll`. + """ + scroll_offsets_bottom = self.scroll_offsets.bottom + scroll_offsets_top = self.scroll_offsets.top + + # We don't have horizontal scrolling. + self.horizontal_scroll = 0 + + # If the current line consumes more than the whole window height, + # then we have to scroll vertically inside this line. (We don't take + # the scroll offsets into account for this.) + # Also, ignore the scroll offsets in this case. Just set the vertical + # scroll to this line. + if ui_content.get_height_for_line(ui_content.cursor_position.y, width) > height - scroll_offsets_top: + # Calculate the height of the text before the cursor, with the line + # containing the cursor included, and the character belowe the + # cursor included as well. + line = explode_tokens(ui_content.get_line(ui_content.cursor_position.y)) + text_before_cursor = token_list_to_text(line[:ui_content.cursor_position.x + 1]) + text_before_height = UIContent.get_height_for_text(text_before_cursor, width) + + # Adjust scroll offset. + self.vertical_scroll = ui_content.cursor_position.y + self.vertical_scroll_2 = min(text_before_height - 1, self.vertical_scroll_2) + self.vertical_scroll_2 = max(0, text_before_height - height, self.vertical_scroll_2) + return + else: + self.vertical_scroll_2 = 0 + + # Current line doesn't consume the whole height. Take scroll offsets into account. + def get_min_vertical_scroll(): + # Make sure that the cursor line is not below the bottom. + # (Calculate how many lines can be shown between the cursor and the .) + used_height = 0 + prev_lineno = ui_content.cursor_position.y + + for lineno in range(ui_content.cursor_position.y, -1, -1): + used_height += ui_content.get_height_for_line(lineno, width) + + if used_height > height - scroll_offsets_bottom: + return prev_lineno + else: + prev_lineno = lineno + return 0 + + def get_max_vertical_scroll(): + # Make sure that the cursor line is not above the top. + prev_lineno = ui_content.cursor_position.y + used_height = 0 + + for lineno in range(ui_content.cursor_position.y - 1, -1, -1): + used_height += ui_content.get_height_for_line(lineno, width) + + if used_height > scroll_offsets_top: + return prev_lineno + else: + prev_lineno = lineno + return prev_lineno + + def get_topmost_visible(): + """ + Calculate the upper most line that can be visible, while the bottom + is still visible. We should not allow scroll more than this if + `allow_scroll_beyond_bottom` is false. + """ + prev_lineno = ui_content.line_count - 1 + used_height = 0 + for lineno in range(ui_content.line_count - 1, -1, -1): + used_height += ui_content.get_height_for_line(lineno, width) + if used_height > height: + return prev_lineno + else: + prev_lineno = lineno + return prev_lineno + + # Scroll vertically. (Make sure that the whole line which contains the + # cursor is visible. + topmost_visible = get_topmost_visible() + + # Note: the `min(topmost_visible, ...)` is to make sure that we + # don't require scrolling up because of the bottom scroll offset, + # when we are at the end of the document. + self.vertical_scroll = max(self.vertical_scroll, min(topmost_visible, get_min_vertical_scroll())) + self.vertical_scroll = min(self.vertical_scroll, get_max_vertical_scroll()) + + # Disallow scrolling beyond bottom? + if not self.allow_scroll_beyond_bottom(cli): + self.vertical_scroll = min(self.vertical_scroll, topmost_visible) + + def _scroll_without_linewrapping(self, ui_content, width, height, cli): + """ + Scroll to make sure the cursor position is visible and that we maintain + the requested scroll offset. + + Set `self.horizontal_scroll/vertical_scroll`. + """ + cursor_position = ui_content.cursor_position or Point(0, 0) + + # Without line wrapping, we will never have to scroll vertically inside + # a single line. + self.vertical_scroll_2 = 0 + + if ui_content.line_count == 0: + self.vertical_scroll = 0 + self.horizontal_scroll = 0 + return + else: + current_line_text = token_list_to_text(ui_content.get_line(cursor_position.y)) + def do_scroll(current_scroll, scroll_offset_start, scroll_offset_end, cursor_pos, window_size, content_size): " Scrolling algorithm. Used for both horizontal and vertical scrolling. " @@ -1552,7 +1552,7 @@ class Window(Container): if current_scroll < (cursor_pos + 1) - window_size + scroll_offset_end: current_scroll = (cursor_pos + 1) - window_size + scroll_offset_end - return current_scroll + return current_scroll # When a preferred scroll is given, take that first into account. if self.get_vertical_scroll: @@ -1566,32 +1566,32 @@ class Window(Container): # remains visible. offsets = self.scroll_offsets - self.vertical_scroll = do_scroll( + self.vertical_scroll = do_scroll( current_scroll=self.vertical_scroll, scroll_offset_start=offsets.top, scroll_offset_end=offsets.bottom, - cursor_pos=ui_content.cursor_position.y, + cursor_pos=ui_content.cursor_position.y, window_size=height, - content_size=ui_content.line_count) + content_size=ui_content.line_count) - self.horizontal_scroll = do_scroll( + self.horizontal_scroll = do_scroll( current_scroll=self.horizontal_scroll, scroll_offset_start=offsets.left, scroll_offset_end=offsets.right, - cursor_pos=get_cwidth(current_line_text[:ui_content.cursor_position.x]), + cursor_pos=get_cwidth(current_line_text[:ui_content.cursor_position.x]), window_size=width, - # We can only analyse the current line. Calculating the width off - # all the lines is too expensive. - content_size=max(get_cwidth(current_line_text), self.horizontal_scroll + width)) + # We can only analyse the current line. Calculating the width off + # all the lines is too expensive. + content_size=max(get_cwidth(current_line_text), self.horizontal_scroll + width)) def _mouse_handler(self, cli, mouse_event): """ Mouse handler. Called when the UI control doesn't handle this particular event. """ - if mouse_event.event_type == MouseEventType.SCROLL_DOWN: + if mouse_event.event_type == MouseEventType.SCROLL_DOWN: self._scroll_down(cli) - elif mouse_event.event_type == MouseEventType.SCROLL_UP: + elif mouse_event.event_type == MouseEventType.SCROLL_UP: self._scroll_up(cli) def _scroll_down(self, cli): @@ -1609,7 +1609,7 @@ class Window(Container): info = self.render_info if info.vertical_scroll > 0: - # TODO: not entirely correct yet in case of line wrapping and long lines. + # TODO: not entirely correct yet in case of line wrapping and long lines. if info.cursor_position.y >= info.window_height - 1 - info.configured_scroll_offsets.bottom: self.content.move_cursor_up(cli) @@ -1635,9 +1635,9 @@ class ConditionalContainer(Container): self.content = content self.filter = to_cli_filter(filter) - def __repr__(self): - return 'ConditionalContainer(%r, filter=%r)' % (self.content, self.filter) - + def __repr__(self): + return 'ConditionalContainer(%r, filter=%r)' % (self.content, self.filter) + def reset(self): self.content.reset() @@ -1647,9 +1647,9 @@ class ConditionalContainer(Container): else: return LayoutDimension.exact(0) - def preferred_height(self, cli, width, max_available_height): + def preferred_height(self, cli, width, max_available_height): if self.filter(cli): - return self.content.preferred_height(cli, width, max_available_height) + return self.content.preferred_height(cli, width, max_available_height) else: return LayoutDimension.exact(0) diff --git a/contrib/python/prompt-toolkit/py2/prompt_toolkit/layout/controls.py b/contrib/python/prompt-toolkit/py2/prompt_toolkit/layout/controls.py index ca74931dbc..951110f82b 100644 --- a/contrib/python/prompt-toolkit/py2/prompt_toolkit/layout/controls.py +++ b/contrib/python/prompt-toolkit/py2/prompt_toolkit/layout/controls.py @@ -4,34 +4,34 @@ User interface Controls for the layout. from __future__ import unicode_literals from abc import ABCMeta, abstractmethod -from collections import namedtuple +from collections import namedtuple from six import with_metaclass -from six.moves import range +from six.moves import range -from prompt_toolkit.cache import SimpleCache +from prompt_toolkit.cache import SimpleCache from prompt_toolkit.enums import DEFAULT_BUFFER, SEARCH_BUFFER from prompt_toolkit.filters import to_cli_filter -from prompt_toolkit.mouse_events import MouseEventType +from prompt_toolkit.mouse_events import MouseEventType from prompt_toolkit.search_state import SearchState from prompt_toolkit.selection import SelectionType -from prompt_toolkit.token import Token -from prompt_toolkit.utils import get_cwidth +from prompt_toolkit.token import Token +from prompt_toolkit.utils import get_cwidth from .lexers import Lexer, SimpleLexer -from .processors import Processor -from .screen import Char, Point -from .utils import token_list_width, split_lines, token_list_to_text +from .processors import Processor +from .screen import Char, Point +from .utils import token_list_width, split_lines, token_list_to_text -import six +import six import time - + __all__ = ( 'BufferControl', 'FillControl', 'TokenListControl', 'UIControl', - 'UIContent', + 'UIContent', ) @@ -46,7 +46,7 @@ class UIControl(with_metaclass(ABCMeta, object)): def preferred_width(self, cli, max_available_width): return None - def preferred_height(self, cli, width, max_available_height, wrap_lines): + def preferred_height(self, cli, width, max_available_height, wrap_lines): return None def has_focus(self, cli): @@ -54,18 +54,18 @@ class UIControl(with_metaclass(ABCMeta, object)): Return ``True`` when this user control has the focus. If so, the cursor will be displayed according to the cursor position - reported by :meth:`.UIControl.create_content`. If the created content - has the property ``show_cursor=False``, the cursor will be hidden from - the output. + reported by :meth:`.UIControl.create_content`. If the created content + has the property ``show_cursor=False``, the cursor will be hidden from + the output. """ return False @abstractmethod - def create_content(self, cli, width, height): + def create_content(self, cli, width, height): """ - Generate the content for this user control. + Generate the content for this user control. - Returns a :class:`.UIContent` instance. + Returns a :class:`.UIContent` instance. """ def mouse_handler(self, cli, mouse_event): @@ -94,78 +94,78 @@ class UIControl(with_metaclass(ABCMeta, object)): """ -class UIContent(object): - """ - Content generated by a user control. This content consists of a list of - lines. - - :param get_line: Callable that returns the current line. This is a list of - (Token, text) tuples. - :param line_count: The number of lines. - :param cursor_position: a :class:`.Point` for the cursor position. - :param menu_position: a :class:`.Point` for the menu position. - :param show_cursor: Make the cursor visible. - :param default_char: The default :class:`.Char` for filling the background. - """ - def __init__(self, get_line=None, line_count=0, - cursor_position=None, menu_position=None, show_cursor=True, - default_char=None): - assert callable(get_line) - assert isinstance(line_count, six.integer_types) - assert cursor_position is None or isinstance(cursor_position, Point) - assert menu_position is None or isinstance(menu_position, Point) - assert default_char is None or isinstance(default_char, Char) - - self.get_line = get_line - self.line_count = line_count - self.cursor_position = cursor_position or Point(0, 0) - self.menu_position = menu_position - self.show_cursor = show_cursor - self.default_char = default_char - - # Cache for line heights. Maps (lineno, width) -> height. - self._line_heights = {} - - def __getitem__(self, lineno): - " Make it iterable (iterate line by line). " - if lineno < self.line_count: - return self.get_line(lineno) - else: - raise IndexError - - def get_height_for_line(self, lineno, width): - """ - Return the height that a given line would need if it is rendered in a - space with the given width. - """ - try: - return self._line_heights[lineno, width] - except KeyError: - text = token_list_to_text(self.get_line(lineno)) - result = self.get_height_for_text(text, width) - - # Cache and return - self._line_heights[lineno, width] = result - return result - - @staticmethod - def get_height_for_text(text, width): - # Get text width for this line. - line_width = get_cwidth(text) - - # Calculate height. - try: - quotient, remainder = divmod(line_width, width) - except ZeroDivisionError: - # Return something very big. - # (This can happen, when the Window gets very small.) - return 10 ** 10 - else: - if remainder: - quotient += 1 # Like math.ceil. - return max(1, quotient) - - +class UIContent(object): + """ + Content generated by a user control. This content consists of a list of + lines. + + :param get_line: Callable that returns the current line. This is a list of + (Token, text) tuples. + :param line_count: The number of lines. + :param cursor_position: a :class:`.Point` for the cursor position. + :param menu_position: a :class:`.Point` for the menu position. + :param show_cursor: Make the cursor visible. + :param default_char: The default :class:`.Char` for filling the background. + """ + def __init__(self, get_line=None, line_count=0, + cursor_position=None, menu_position=None, show_cursor=True, + default_char=None): + assert callable(get_line) + assert isinstance(line_count, six.integer_types) + assert cursor_position is None or isinstance(cursor_position, Point) + assert menu_position is None or isinstance(menu_position, Point) + assert default_char is None or isinstance(default_char, Char) + + self.get_line = get_line + self.line_count = line_count + self.cursor_position = cursor_position or Point(0, 0) + self.menu_position = menu_position + self.show_cursor = show_cursor + self.default_char = default_char + + # Cache for line heights. Maps (lineno, width) -> height. + self._line_heights = {} + + def __getitem__(self, lineno): + " Make it iterable (iterate line by line). " + if lineno < self.line_count: + return self.get_line(lineno) + else: + raise IndexError + + def get_height_for_line(self, lineno, width): + """ + Return the height that a given line would need if it is rendered in a + space with the given width. + """ + try: + return self._line_heights[lineno, width] + except KeyError: + text = token_list_to_text(self.get_line(lineno)) + result = self.get_height_for_text(text, width) + + # Cache and return + self._line_heights[lineno, width] = result + return result + + @staticmethod + def get_height_for_text(text, width): + # Get text width for this line. + line_width = get_cwidth(text) + + # Calculate height. + try: + quotient, remainder = divmod(line_width, width) + except ZeroDivisionError: + # Return something very big. + # (This can happen, when the Window gets very small.) + return 10 ** 10 + else: + if remainder: + quotient += 1 # Like math.ceil. + return max(1, quotient) + + class TokenListControl(UIControl): """ Control that displays a list of (Token, text) tuples. @@ -195,8 +195,8 @@ class TokenListControl(UIControl): cursor will be shown there. """ def __init__(self, get_tokens, default_char=None, get_default_char=None, - align_right=False, align_center=False, has_focus=False): - assert callable(get_tokens) + align_right=False, align_center=False, has_focus=False): + assert callable(get_tokens) assert default_char is None or isinstance(default_char, Char) assert get_default_char is None or callable(get_default_char) assert not (default_char and get_default_char) @@ -211,21 +211,21 @@ class TokenListControl(UIControl): if default_char: get_default_char = lambda _: default_char elif not get_default_char: - get_default_char = lambda _: Char(' ', Token.Transparent) + get_default_char = lambda _: Char(' ', Token.Transparent) self.get_default_char = get_default_char - #: Cache for the content. - self._content_cache = SimpleCache(maxsize=18) - self._token_cache = SimpleCache(maxsize=1) + #: Cache for the content. + self._content_cache = SimpleCache(maxsize=18) + self._token_cache = SimpleCache(maxsize=1) # Only cache one token list. We don't need the previous item. # Render info for the mouse support. - self._tokens = None - - def reset(self): - self._tokens = None + self._tokens = None + def reset(self): + self._tokens = None + def __repr__(self): return '%s(%r)' % (self.__class__.__name__, self.get_tokens) @@ -235,7 +235,7 @@ class TokenListControl(UIControl): (This function is called several times during one rendering, because we also need those for calculating the dimensions.) """ - return self._token_cache.get( + return self._token_cache.get( cli.render_counter, lambda: self.get_tokens(cli)) def has_focus(self, cli): @@ -246,15 +246,15 @@ class TokenListControl(UIControl): Return the preferred width for this control. That is the width of the longest line. """ - text = token_list_to_text(self._get_tokens_cached(cli)) + text = token_list_to_text(self._get_tokens_cached(cli)) line_lengths = [get_cwidth(l) for l in text.split('\n')] return max(line_lengths) - def preferred_height(self, cli, width, max_available_height, wrap_lines): - content = self.create_content(cli, width, None) - return content.line_count + def preferred_height(self, cli, width, max_available_height, wrap_lines): + content = self.create_content(cli, width, None) + return content.line_count - def create_content(self, cli, width, height): + def create_content(self, cli, width, height): # Get tokens tokens_with_mouse_handlers = self._get_tokens_cached(cli) @@ -270,51 +270,51 @@ class TokenListControl(UIControl): padding = width - used_width if center: padding = int(padding / 2) - return [(default_char.token, default_char.char * padding)] + line + return [(default_char.token, default_char.char * padding)] + line if right or center: - token_lines_with_mouse_handlers = [] - + token_lines_with_mouse_handlers = [] + for line in split_lines(tokens_with_mouse_handlers): - token_lines_with_mouse_handlers.append(process_line(line)) - else: - token_lines_with_mouse_handlers = list(split_lines(tokens_with_mouse_handlers)) + token_lines_with_mouse_handlers.append(process_line(line)) + else: + token_lines_with_mouse_handlers = list(split_lines(tokens_with_mouse_handlers)) # Strip mouse handlers from tokens. - token_lines = [ - [tuple(item[:2]) for item in line] - for line in token_lines_with_mouse_handlers - ] + token_lines = [ + [tuple(item[:2]) for item in line] + for line in token_lines_with_mouse_handlers + ] - # Keep track of the tokens with mouse handler, for later use in - # `mouse_handler`. + # Keep track of the tokens with mouse handler, for later use in + # `mouse_handler`. self._tokens = tokens_with_mouse_handlers - # If there is a `Token.SetCursorPosition` in the token list, set the - # cursor position here. - def get_cursor_position(): - SetCursorPosition = Token.SetCursorPosition - - for y, line in enumerate(token_lines): - x = 0 - for token, text in line: - if token == SetCursorPosition: - return Point(x=x, y=y) - x += len(text) - return None - - # Create content, or take it from the cache. - key = (default_char.char, default_char.token, - tuple(tokens_with_mouse_handlers), width, right, center) - - def get_content(): - return UIContent(get_line=lambda i: token_lines[i], - line_count=len(token_lines), - default_char=default_char, - cursor_position=get_cursor_position()) - - return self._content_cache.get(key, get_content) - + # If there is a `Token.SetCursorPosition` in the token list, set the + # cursor position here. + def get_cursor_position(): + SetCursorPosition = Token.SetCursorPosition + + for y, line in enumerate(token_lines): + x = 0 + for token, text in line: + if token == SetCursorPosition: + return Point(x=x, y=y) + x += len(text) + return None + + # Create content, or take it from the cache. + key = (default_char.char, default_char.token, + tuple(tokens_with_mouse_handlers), width, right, center) + + def get_content(): + return UIContent(get_line=lambda i: token_lines[i], + line_count=len(token_lines), + default_char=default_char, + cursor_position=get_cursor_position()) + + return self._content_cache.get(key, get_content) + @classmethod def static(cls, tokens): def get_static_tokens(cli): @@ -330,29 +330,29 @@ class TokenListControl(UIControl): return `NotImplemented` in case we want the `Window` to handle this particular event.) """ - if self._tokens: - # Read the generator. - tokens_for_line = list(split_lines(self._tokens)) - - try: - tokens = tokens_for_line[mouse_event.position.y] - except IndexError: - return NotImplemented - else: - # Find position in the token list. - xpos = mouse_event.position.x - + if self._tokens: + # Read the generator. + tokens_for_line = list(split_lines(self._tokens)) + + try: + tokens = tokens_for_line[mouse_event.position.y] + except IndexError: + return NotImplemented + else: + # Find position in the token list. + xpos = mouse_event.position.x + # Find mouse handler for this character. count = 0 - for item in tokens: + for item in tokens: count += len(item[1]) - if count >= xpos: + if count >= xpos: if len(item) >= 3: # Handler found. Call it. - # (Handler can return NotImplemented, so return - # that result.) + # (Handler can return NotImplemented, so return + # that result.) handler = item[2] - return handler(cli, mouse_event) + return handler(cli, mouse_event) else: break @@ -364,38 +364,38 @@ class FillControl(UIControl): """ Fill whole control with characters with this token. (Also helpful for debugging.) - - :param char: :class:`.Char` instance to use for filling. - :param get_char: A callable that takes a CommandLineInterface and returns a - :class:`.Char` object. + + :param char: :class:`.Char` instance to use for filling. + :param get_char: A callable that takes a CommandLineInterface and returns a + :class:`.Char` object. """ - def __init__(self, character=None, token=Token, char=None, get_char=None): # 'character' and 'token' parameters are deprecated. - assert char is None or isinstance(char, Char) - assert get_char is None or callable(get_char) - assert not (char and get_char) - - self.char = char - - if character: - # Passing (character=' ', token=token) is deprecated. - self.character = character - self.token = token - - self.get_char = lambda cli: Char(character, token) - elif get_char: - # When 'get_char' is given. - self.get_char = get_char - else: - # When 'char' is given. - self.char = self.char or Char() - self.get_char = lambda cli: self.char - self.char = char - + def __init__(self, character=None, token=Token, char=None, get_char=None): # 'character' and 'token' parameters are deprecated. + assert char is None or isinstance(char, Char) + assert get_char is None or callable(get_char) + assert not (char and get_char) + + self.char = char + + if character: + # Passing (character=' ', token=token) is deprecated. + self.character = character + self.token = token + + self.get_char = lambda cli: Char(character, token) + elif get_char: + # When 'get_char' is given. + self.get_char = get_char + else: + # When 'char' is given. + self.char = self.char or Char() + self.get_char = lambda cli: self.char + self.char = char + def __repr__(self): - if self.char: - return '%s(char=%r)' % (self.__class__.__name__, self.char) - else: - return '%s(get_char=%r)' % (self.__class__.__name__, self.get_char) + if self.char: + return '%s(char=%r)' % (self.__class__.__name__, self.char) + else: + return '%s(get_char=%r)' % (self.__class__.__name__, self.get_char) def reset(self): pass @@ -403,19 +403,19 @@ class FillControl(UIControl): def has_focus(self, cli): return False - def create_content(self, cli, width, height): - def get_line(i): - return [] - - return UIContent( - get_line=get_line, - line_count=100 ** 100, # Something very big. - default_char=self.get_char(cli)) - - -_ProcessedLine = namedtuple('_ProcessedLine', 'tokens source_to_display display_to_source') + def create_content(self, cli, width, height): + def get_line(i): + return [] + return UIContent( + get_line=get_line, + line_count=100 ** 100, # Something very big. + default_char=self.get_char(cli)) + +_ProcessedLine = namedtuple('_ProcessedLine', 'tokens source_to_display display_to_source') + + class BufferControl(UIControl): """ Control for visualising the content of a `Buffer`. @@ -444,7 +444,7 @@ class BufferControl(UIControl): assert menu_position is None or callable(menu_position) assert lexer is None or isinstance(lexer, Lexer) assert get_search_state is None or callable(get_search_state) - assert default_char is None or isinstance(default_char, Char) + assert default_char is None or isinstance(default_char, Char) self.preview_search = to_cli_filter(preview_search) self.get_search_state = get_search_state @@ -457,15 +457,15 @@ class BufferControl(UIControl): self.default_char = default_char or Char(token=Token.Transparent) self.search_buffer_name = search_buffer_name - #: Cache for the lexer. + #: Cache for the lexer. #: Often, due to cursor movement, undo/redo and window resizing #: operations, it happens that a short time, the same document has to be #: lexed. This is a faily easy way to cache such an expensive operation. - self._token_cache = SimpleCache(maxsize=8) + self._token_cache = SimpleCache(maxsize=8) self._xy_to_cursor_position = None self._last_click_timestamp = None - self._last_get_processed_line = None + self._last_get_processed_line = None def _buffer(self, cli): """ @@ -483,114 +483,114 @@ class BufferControl(UIControl): any(i.has_focus(cli) for i in self.input_processors) def preferred_width(self, cli, max_available_width): + """ + This should return the preferred width. + + Note: We don't specify a preferred width according to the content, + because it would be too expensive. Calculating the preferred + width can be done by calculating the longest line, but this would + require applying all the processors to each line. This is + unfeasible for a larger document, and doing it for small + documents only would result in inconsistent behaviour. """ - This should return the preferred width. - - Note: We don't specify a preferred width according to the content, - because it would be too expensive. Calculating the preferred - width can be done by calculating the longest line, but this would - require applying all the processors to each line. This is - unfeasible for a larger document, and doing it for small - documents only would result in inconsistent behaviour. - """ - return None - - def preferred_height(self, cli, width, max_available_height, wrap_lines): - # Calculate the content height, if it was drawn on a screen with the - # given width. - height = 0 - content = self.create_content(cli, width, None) - - # When line wrapping is off, the height should be equal to the amount - # of lines. - if not wrap_lines: - return content.line_count - - # When the number of lines exceeds the max_available_height, just - # return max_available_height. No need to calculate anything. - if content.line_count >= max_available_height: - return max_available_height - - for i in range(content.line_count): - height += content.get_height_for_line(i, width) - - if height >= max_available_height: - return max_available_height - - return height - - def _get_tokens_for_line_func(self, cli, document): - """ - Create a function that returns the tokens for a given line. + return None + + def preferred_height(self, cli, width, max_available_height, wrap_lines): + # Calculate the content height, if it was drawn on a screen with the + # given width. + height = 0 + content = self.create_content(cli, width, None) + + # When line wrapping is off, the height should be equal to the amount + # of lines. + if not wrap_lines: + return content.line_count + + # When the number of lines exceeds the max_available_height, just + # return max_available_height. No need to calculate anything. + if content.line_count >= max_available_height: + return max_available_height + + for i in range(content.line_count): + height += content.get_height_for_line(i, width) + + if height >= max_available_height: + return max_available_height + + return height + + def _get_tokens_for_line_func(self, cli, document): """ - # Cache using `document.text`. - def get_tokens_for_line(): - return self.lexer.lex_document(cli, document) - - return self._token_cache.get(document.text, get_tokens_for_line) - - def _create_get_processed_line_func(self, cli, document): - """ - Create a function that takes a line number of the current document and - returns a _ProcessedLine(processed_tokens, source_to_display, display_to_source) - tuple. - """ - def transform(lineno, tokens): - " Transform the tokens for a given line number. " + Create a function that returns the tokens for a given line. + """ + # Cache using `document.text`. + def get_tokens_for_line(): + return self.lexer.lex_document(cli, document) + + return self._token_cache.get(document.text, get_tokens_for_line) + + def _create_get_processed_line_func(self, cli, document): + """ + Create a function that takes a line number of the current document and + returns a _ProcessedLine(processed_tokens, source_to_display, display_to_source) + tuple. + """ + def transform(lineno, tokens): + " Transform the tokens for a given line number. " source_to_display_functions = [] display_to_source_functions = [] - # Get cursor position at this line. - if document.cursor_position_row == lineno: - cursor_column = document.cursor_position_col - else: - cursor_column = None - - def source_to_display(i): - """ Translate x position from the buffer to the x position in the - processed token list. """ - for f in source_to_display_functions: - i = f(i) - return i - - # Apply each processor. + # Get cursor position at this line. + if document.cursor_position_row == lineno: + cursor_column = document.cursor_position_col + else: + cursor_column = None + + def source_to_display(i): + """ Translate x position from the buffer to the x position in the + processed token list. """ + for f in source_to_display_functions: + i = f(i) + return i + + # Apply each processor. for p in self.input_processors: - transformation = p.apply_transformation( - cli, document, lineno, source_to_display, tokens) + transformation = p.apply_transformation( + cli, document, lineno, source_to_display, tokens) tokens = transformation.tokens - if cursor_column: - cursor_column = transformation.source_to_display(cursor_column) + if cursor_column: + cursor_column = transformation.source_to_display(cursor_column) - display_to_source_functions.append(transformation.display_to_source) - source_to_display_functions.append(transformation.source_to_display) + display_to_source_functions.append(transformation.display_to_source) + source_to_display_functions.append(transformation.source_to_display) - def display_to_source(i): + def display_to_source(i): for f in reversed(display_to_source_functions): - i = f(i) - return i - - return _ProcessedLine(tokens, source_to_display, display_to_source) - - def create_func(): - get_line = self._get_tokens_for_line_func(cli, document) - cache = {} - - def get_processed_line(i): - try: - return cache[i] - except KeyError: - processed_line = transform(i, get_line(i)) - cache[i] = processed_line - return processed_line - return get_processed_line - - return create_func() - - def create_content(self, cli, width, height): - """ - Create a UIContent. - """ + i = f(i) + return i + + return _ProcessedLine(tokens, source_to_display, display_to_source) + + def create_func(): + get_line = self._get_tokens_for_line_func(cli, document) + cache = {} + + def get_processed_line(i): + try: + return cache[i] + except KeyError: + processed_line = transform(i, get_line(i)) + cache[i] = processed_line + return processed_line + return get_processed_line + + return create_func() + + def create_content(self, cli, width, height): + """ + Create a UIContent. + """ buffer = self._buffer(cli) # Get the document to be shown. If we are currently searching (the @@ -615,31 +615,31 @@ class BufferControl(UIControl): else: document = buffer.document - get_processed_line = self._create_get_processed_line_func(cli, document) - self._last_get_processed_line = get_processed_line + get_processed_line = self._create_get_processed_line_func(cli, document) + self._last_get_processed_line = get_processed_line - def translate_rowcol(row, col): - " Return the content column for this coordinate. " - return Point(y=row, x=get_processed_line(row).source_to_display(col)) + def translate_rowcol(row, col): + " Return the content column for this coordinate. " + return Point(y=row, x=get_processed_line(row).source_to_display(col)) - def get_line(i): - " Return the tokens for a given line number. " - tokens = get_processed_line(i).tokens + def get_line(i): + " Return the tokens for a given line number. " + tokens = get_processed_line(i).tokens - # Add a space at the end, because that is a possible cursor - # position. (When inserting after the input.) We should do this on - # all the lines, not just the line containing the cursor. (Because - # otherwise, line wrapping/scrolling could change when moving the - # cursor around.) - tokens = tokens + [(self.default_char.token, ' ')] - return tokens + # Add a space at the end, because that is a possible cursor + # position. (When inserting after the input.) We should do this on + # all the lines, not just the line containing the cursor. (Because + # otherwise, line wrapping/scrolling could change when moving the + # cursor around.) + tokens = tokens + [(self.default_char.token, ' ')] + return tokens - content = UIContent( - get_line=get_line, - line_count=document.line_count, - cursor_position=translate_rowcol(document.cursor_position_row, - document.cursor_position_col), - default_char=self.default_char) + content = UIContent( + get_line=get_line, + line_count=document.line_count, + cursor_position=translate_rowcol(document.cursor_position_row, + document.cursor_position_col), + default_char=self.default_char) # If there is an auto completion going on, use that start point for a # pop-up menu position. (But only when this buffer has the focus -- @@ -648,22 +648,22 @@ class BufferControl(UIControl): menu_position = self.menu_position(cli) if self.menu_position else None if menu_position is not None: assert isinstance(menu_position, int) - menu_row, menu_col = buffer.document.translate_index_to_position(menu_position) - content.menu_position = translate_rowcol(menu_row, menu_col) + menu_row, menu_col = buffer.document.translate_index_to_position(menu_position) + content.menu_position = translate_rowcol(menu_row, menu_col) elif buffer.complete_state: # Position for completion menu. # Note: We use 'min', because the original cursor position could be # behind the input string when the actual completion is for # some reason shorter than the text we had before. (A completion # can change and shorten the input.) - menu_row, menu_col = buffer.document.translate_index_to_position( + menu_row, menu_col = buffer.document.translate_index_to_position( min(buffer.cursor_position, buffer.complete_state.original_document.cursor_position)) - content.menu_position = translate_rowcol(menu_row, menu_col) + content.menu_position = translate_rowcol(menu_row, menu_col) else: - content.menu_position = None + content.menu_position = None - return content + return content def mouse_handler(self, cli, mouse_event): """ @@ -674,46 +674,46 @@ class BufferControl(UIControl): # Focus buffer when clicked. if self.has_focus(cli): - if self._last_get_processed_line: - processed_line = self._last_get_processed_line(position.y) - + if self._last_get_processed_line: + processed_line = self._last_get_processed_line(position.y) + # Translate coordinates back to the cursor position of the # original input. - xpos = processed_line.display_to_source(position.x) - index = buffer.document.translate_row_col_to_index(position.y, xpos) + xpos = processed_line.display_to_source(position.x) + index = buffer.document.translate_row_col_to_index(position.y, xpos) # Set the cursor position. - if mouse_event.event_type == MouseEventType.MOUSE_DOWN: - buffer.exit_selection() - buffer.cursor_position = index - - elif mouse_event.event_type == MouseEventType.MOUSE_UP: - # When the cursor was moved to another place, select the text. - # (The >1 is actually a small but acceptable workaround for - # selecting text in Vi navigation mode. In navigation mode, - # the cursor can never be after the text, so the cursor - # will be repositioned automatically.) - if abs(buffer.cursor_position - index) > 1: - buffer.start_selection(selection_type=SelectionType.CHARACTERS) - buffer.cursor_position = index - - # Select word around cursor on double click. - # Two MOUSE_UP events in a short timespan are considered a double click. - double_click = self._last_click_timestamp and time.time() - self._last_click_timestamp < .3 - self._last_click_timestamp = time.time() - - if double_click: - start, end = buffer.document.find_boundaries_of_current_word() - buffer.cursor_position += start - buffer.start_selection(selection_type=SelectionType.CHARACTERS) - buffer.cursor_position += end - start - else: - # Don't handle scroll events here. - return NotImplemented + if mouse_event.event_type == MouseEventType.MOUSE_DOWN: + buffer.exit_selection() + buffer.cursor_position = index + + elif mouse_event.event_type == MouseEventType.MOUSE_UP: + # When the cursor was moved to another place, select the text. + # (The >1 is actually a small but acceptable workaround for + # selecting text in Vi navigation mode. In navigation mode, + # the cursor can never be after the text, so the cursor + # will be repositioned automatically.) + if abs(buffer.cursor_position - index) > 1: + buffer.start_selection(selection_type=SelectionType.CHARACTERS) + buffer.cursor_position = index + + # Select word around cursor on double click. + # Two MOUSE_UP events in a short timespan are considered a double click. + double_click = self._last_click_timestamp and time.time() - self._last_click_timestamp < .3 + self._last_click_timestamp = time.time() + + if double_click: + start, end = buffer.document.find_boundaries_of_current_word() + buffer.cursor_position += start + buffer.start_selection(selection_type=SelectionType.CHARACTERS) + buffer.cursor_position += end - start + else: + # Don't handle scroll events here. + return NotImplemented # Not focussed, but focussing on click events. else: - if self.focus_on_click(cli) and mouse_event.event_type == MouseEventType.MOUSE_UP: + if self.focus_on_click(cli) and mouse_event.event_type == MouseEventType.MOUSE_UP: # Focus happens on mouseup. (If we did this on mousedown, the # up event will be received at the point where this widget is # focussed and be handled anyway.) diff --git a/contrib/python/prompt-toolkit/py2/prompt_toolkit/layout/lexers.py b/contrib/python/prompt-toolkit/py2/prompt_toolkit/layout/lexers.py index a928fd8226..9808f2edb5 100644 --- a/contrib/python/prompt-toolkit/py2/prompt_toolkit/layout/lexers.py +++ b/contrib/python/prompt-toolkit/py2/prompt_toolkit/layout/lexers.py @@ -5,22 +5,22 @@ Used for syntax highlighting. from __future__ import unicode_literals from abc import ABCMeta, abstractmethod from six import with_metaclass -from six.moves import range - -from prompt_toolkit.token import Token -from prompt_toolkit.filters import to_cli_filter -from .utils import split_lines - -import re -import six - +from six.moves import range + +from prompt_toolkit.token import Token +from prompt_toolkit.filters import to_cli_filter +from .utils import split_lines + +import re +import six + __all__ = ( 'Lexer', 'SimpleLexer', 'PygmentsLexer', - 'SyntaxSync', - 'SyncFromStart', - 'RegexSync', + 'SyntaxSync', + 'SyncFromStart', + 'RegexSync', ) @@ -29,127 +29,127 @@ class Lexer(with_metaclass(ABCMeta, object)): Base class for all lexers. """ @abstractmethod - def lex_document(self, cli, document): + def lex_document(self, cli, document): """ - Takes a :class:`~prompt_toolkit.document.Document` and returns a - callable that takes a line number and returns the tokens for that line. + Takes a :class:`~prompt_toolkit.document.Document` and returns a + callable that takes a line number and returns the tokens for that line. """ class SimpleLexer(Lexer): """ - Lexer that doesn't do any tokenizing and returns the whole input as one token. - - :param token: The `Token` for this lexer. - """ - # `default_token` parameter is deprecated! - def __init__(self, token=Token, default_token=None): - self.token = token - - if default_token is not None: - self.token = default_token - - def lex_document(self, cli, document): - lines = document.lines - - def get_line(lineno): - " Return the tokens for the given line. " - try: - return [(self.token, lines[lineno])] - except IndexError: - return [] - return get_line - - -class SyntaxSync(with_metaclass(ABCMeta, object)): - """ - Syntax synchroniser. This is a tool that finds a start position for the - lexer. This is especially important when editing big documents; we don't - want to start the highlighting by running the lexer from the beginning of - the file. That is very slow when editing. - """ - @abstractmethod - def get_sync_start_position(self, document, lineno): - """ - Return the position from where we can start lexing as a (row, column) - tuple. - - :param document: `Document` instance that contains all the lines. - :param lineno: The line that we want to highlight. (We need to return - this line, or an earlier position.) - """ - -class SyncFromStart(SyntaxSync): - """ - Always start the syntax highlighting from the beginning. - """ - def get_sync_start_position(self, document, lineno): - return 0, 0 - - -class RegexSync(SyntaxSync): - """ - Synchronize by starting at a line that matches the given regex pattern. + Lexer that doesn't do any tokenizing and returns the whole input as one token. + + :param token: The `Token` for this lexer. """ - # Never go more than this amount of lines backwards for synchronisation. - # That would be too CPU intensive. - MAX_BACKWARDS = 500 - - # Start lexing at the start, if we are in the first 'n' lines and no - # synchronisation position was found. - FROM_START_IF_NO_SYNC_POS_FOUND = 100 - - def __init__(self, pattern): - assert isinstance(pattern, six.text_type) - self._compiled_pattern = re.compile(pattern) - - def get_sync_start_position(self, document, lineno): - " Scan backwards, and find a possible position to start. " - pattern = self._compiled_pattern - lines = document.lines - - # Scan upwards, until we find a point where we can start the syntax - # synchronisation. - for i in range(lineno, max(-1, lineno - self.MAX_BACKWARDS), -1): - match = pattern.match(lines[i]) - if match: - return i, match.start() - - # No synchronisation point found. If we aren't that far from the - # beginning, start at the very beginning, otherwise, just try to start - # at the current line. - if lineno < self.FROM_START_IF_NO_SYNC_POS_FOUND: - return 0, 0 - else: - return lineno, 0 - - @classmethod - def from_pygments_lexer_cls(cls, lexer_cls): - """ - Create a :class:`.RegexSync` instance for this Pygments lexer class. - """ - patterns = { - # For Python, start highlighting at any class/def block. - 'Python': r'^\s*(class|def)\s+', - 'Python 3': r'^\s*(class|def)\s+', - - # For HTML, start at any open/close tag definition. - 'HTML': r'<[/a-zA-Z]', - - # For javascript, start at a function. - 'JavaScript': r'\bfunction\b' - - # TODO: Add definitions for other languages. - # By default, we start at every possible line. - } - p = patterns.get(lexer_cls.name, '^') - return cls(p) - - + # `default_token` parameter is deprecated! + def __init__(self, token=Token, default_token=None): + self.token = token + + if default_token is not None: + self.token = default_token + + def lex_document(self, cli, document): + lines = document.lines + + def get_line(lineno): + " Return the tokens for the given line. " + try: + return [(self.token, lines[lineno])] + except IndexError: + return [] + return get_line + + +class SyntaxSync(with_metaclass(ABCMeta, object)): + """ + Syntax synchroniser. This is a tool that finds a start position for the + lexer. This is especially important when editing big documents; we don't + want to start the highlighting by running the lexer from the beginning of + the file. That is very slow when editing. + """ + @abstractmethod + def get_sync_start_position(self, document, lineno): + """ + Return the position from where we can start lexing as a (row, column) + tuple. + + :param document: `Document` instance that contains all the lines. + :param lineno: The line that we want to highlight. (We need to return + this line, or an earlier position.) + """ + +class SyncFromStart(SyntaxSync): + """ + Always start the syntax highlighting from the beginning. + """ + def get_sync_start_position(self, document, lineno): + return 0, 0 + + +class RegexSync(SyntaxSync): + """ + Synchronize by starting at a line that matches the given regex pattern. + """ + # Never go more than this amount of lines backwards for synchronisation. + # That would be too CPU intensive. + MAX_BACKWARDS = 500 + + # Start lexing at the start, if we are in the first 'n' lines and no + # synchronisation position was found. + FROM_START_IF_NO_SYNC_POS_FOUND = 100 + + def __init__(self, pattern): + assert isinstance(pattern, six.text_type) + self._compiled_pattern = re.compile(pattern) + + def get_sync_start_position(self, document, lineno): + " Scan backwards, and find a possible position to start. " + pattern = self._compiled_pattern + lines = document.lines + + # Scan upwards, until we find a point where we can start the syntax + # synchronisation. + for i in range(lineno, max(-1, lineno - self.MAX_BACKWARDS), -1): + match = pattern.match(lines[i]) + if match: + return i, match.start() + + # No synchronisation point found. If we aren't that far from the + # beginning, start at the very beginning, otherwise, just try to start + # at the current line. + if lineno < self.FROM_START_IF_NO_SYNC_POS_FOUND: + return 0, 0 + else: + return lineno, 0 + + @classmethod + def from_pygments_lexer_cls(cls, lexer_cls): + """ + Create a :class:`.RegexSync` instance for this Pygments lexer class. + """ + patterns = { + # For Python, start highlighting at any class/def block. + 'Python': r'^\s*(class|def)\s+', + 'Python 3': r'^\s*(class|def)\s+', + + # For HTML, start at any open/close tag definition. + 'HTML': r'<[/a-zA-Z]', + + # For javascript, start at a function. + 'JavaScript': r'\bfunction\b' + + # TODO: Add definitions for other languages. + # By default, we start at every possible line. + } + p = patterns.get(lexer_cls.name, '^') + return cls(p) + + class PygmentsLexer(Lexer): """ Lexer that calls a pygments lexer. - + Example:: from pygments.lexers import HtmlLexer @@ -161,32 +161,32 @@ class PygmentsLexer(Lexer): from pygments.styles import get_style_by_name style = style_from_pygments(get_style_by_name('monokai')) - :param pygments_lexer_cls: A `Lexer` from Pygments. - :param sync_from_start: Start lexing at the start of the document. This - will always give the best results, but it will be slow for bigger - documents. (When the last part of the document is display, then the - whole document will be lexed by Pygments on every key stroke.) It is - recommended to disable this for inputs that are expected to be more - than 1,000 lines. - :param syntax_sync: `SyntaxSync` object. + :param pygments_lexer_cls: A `Lexer` from Pygments. + :param sync_from_start: Start lexing at the start of the document. This + will always give the best results, but it will be slow for bigger + documents. (When the last part of the document is display, then the + whole document will be lexed by Pygments on every key stroke.) It is + recommended to disable this for inputs that are expected to be more + than 1,000 lines. + :param syntax_sync: `SyntaxSync` object. """ - # Minimum amount of lines to go backwards when starting the parser. - # This is important when the lines are retrieved in reverse order, or when - # scrolling upwards. (Due to the complexity of calculating the vertical - # scroll offset in the `Window` class, lines are not always retrieved in - # order.) - MIN_LINES_BACKWARDS = 50 - - # When a parser was started this amount of lines back, read the parser - # until we get the current line. Otherwise, start a new parser. - # (This should probably be bigger than MIN_LINES_BACKWARDS.) - REUSE_GENERATOR_MAX_DISTANCE = 100 - - def __init__(self, pygments_lexer_cls, sync_from_start=True, syntax_sync=None): - assert syntax_sync is None or isinstance(syntax_sync, SyntaxSync) - + # Minimum amount of lines to go backwards when starting the parser. + # This is important when the lines are retrieved in reverse order, or when + # scrolling upwards. (Due to the complexity of calculating the vertical + # scroll offset in the `Window` class, lines are not always retrieved in + # order.) + MIN_LINES_BACKWARDS = 50 + + # When a parser was started this amount of lines back, read the parser + # until we get the current line. Otherwise, start a new parser. + # (This should probably be bigger than MIN_LINES_BACKWARDS.) + REUSE_GENERATOR_MAX_DISTANCE = 100 + + def __init__(self, pygments_lexer_cls, sync_from_start=True, syntax_sync=None): + assert syntax_sync is None or isinstance(syntax_sync, SyntaxSync) + self.pygments_lexer_cls = pygments_lexer_cls - self.sync_from_start = to_cli_filter(sync_from_start) + self.sync_from_start = to_cli_filter(sync_from_start) # Instantiate the Pygments lexer. self.pygments_lexer = pygments_lexer_cls( @@ -194,127 +194,127 @@ class PygmentsLexer(Lexer): stripall=False, ensurenl=False) - # Create syntax sync instance. - self.syntax_sync = syntax_sync or RegexSync.from_pygments_lexer_cls(pygments_lexer_cls) - - @classmethod - def from_filename(cls, filename, sync_from_start=True): - """ - Create a `Lexer` from a filename. - """ - # Inline imports: the Pygments dependency is optional! - from pygments.util import ClassNotFound - from pygments.lexers import get_lexer_for_filename - - try: - pygments_lexer = get_lexer_for_filename(filename) - except ClassNotFound: - return SimpleLexer() - else: - return cls(pygments_lexer.__class__, sync_from_start=sync_from_start) - - def lex_document(self, cli, document): - """ - Create a lexer function that takes a line number and returns the list - of (Token, text) tuples as the Pygments lexer returns for that line. - """ - # Cache of already lexed lines. - cache = {} - - # Pygments generators that are currently lexing. - line_generators = {} # Map lexer generator to the line number. - - def get_syntax_sync(): - " The Syntax synchronisation objcet that we currently use. " - if self.sync_from_start(cli): - return SyncFromStart() - else: - return self.syntax_sync - - def find_closest_generator(i): - " Return a generator close to line 'i', or None if none was fonud. " - for generator, lineno in line_generators.items(): - if lineno < i and i - lineno < self.REUSE_GENERATOR_MAX_DISTANCE: - return generator - - def create_line_generator(start_lineno, column=0): - """ - Create a generator that yields the lexed lines. - Each iteration it yields a (line_number, [(token, text), ...]) tuple. - """ - def get_tokens(): - text = '\n'.join(document.lines[start_lineno:])[column:] - - # We call `get_tokens_unprocessed`, because `get_tokens` will - # still replace \r\n and \r by \n. (We don't want that, - # Pygments should return exactly the same amount of text, as we - # have given as input.) - for _, t, v in self.pygments_lexer.get_tokens_unprocessed(text): - yield t, v - - return enumerate(split_lines(get_tokens()), start_lineno) - - def get_generator(i): - """ - Find an already started generator that is close, or create a new one. - """ - # Find closest line generator. - generator = find_closest_generator(i) - if generator: - return generator - - # No generator found. Determine starting point for the syntax - # synchronisation first. - - # Go at least x lines back. (Make scrolling upwards more - # efficient.) - i = max(0, i - self.MIN_LINES_BACKWARDS) - - if i == 0: - row = 0 - column = 0 - else: - row, column = get_syntax_sync().get_sync_start_position(document, i) - - # Find generator close to this point, or otherwise create a new one. - generator = find_closest_generator(i) - if generator: - return generator - else: - generator = create_line_generator(row, column) - - # If the column is not 0, ignore the first line. (Which is - # incomplete. This happens when the synchronisation algorithm tells - # us to start parsing in the middle of a line.) - if column: - next(generator) - row += 1 - - line_generators[generator] = row - return generator - - def get_line(i): - " Return the tokens for a given line number. " - try: - return cache[i] - except KeyError: - generator = get_generator(i) - - # Exhaust the generator, until we find the requested line. - for num, line in generator: - cache[num] = line - if num == i: - line_generators[generator] = i - - # Remove the next item from the cache. - # (It could happen that it's already there, because of - # another generator that started filling these lines, - # but we want to synchronise these lines with the - # current lexer's state.) - if num + 1 in cache: - del cache[num + 1] - - return cache[num] - return [] - - return get_line + # Create syntax sync instance. + self.syntax_sync = syntax_sync or RegexSync.from_pygments_lexer_cls(pygments_lexer_cls) + + @classmethod + def from_filename(cls, filename, sync_from_start=True): + """ + Create a `Lexer` from a filename. + """ + # Inline imports: the Pygments dependency is optional! + from pygments.util import ClassNotFound + from pygments.lexers import get_lexer_for_filename + + try: + pygments_lexer = get_lexer_for_filename(filename) + except ClassNotFound: + return SimpleLexer() + else: + return cls(pygments_lexer.__class__, sync_from_start=sync_from_start) + + def lex_document(self, cli, document): + """ + Create a lexer function that takes a line number and returns the list + of (Token, text) tuples as the Pygments lexer returns for that line. + """ + # Cache of already lexed lines. + cache = {} + + # Pygments generators that are currently lexing. + line_generators = {} # Map lexer generator to the line number. + + def get_syntax_sync(): + " The Syntax synchronisation objcet that we currently use. " + if self.sync_from_start(cli): + return SyncFromStart() + else: + return self.syntax_sync + + def find_closest_generator(i): + " Return a generator close to line 'i', or None if none was fonud. " + for generator, lineno in line_generators.items(): + if lineno < i and i - lineno < self.REUSE_GENERATOR_MAX_DISTANCE: + return generator + + def create_line_generator(start_lineno, column=0): + """ + Create a generator that yields the lexed lines. + Each iteration it yields a (line_number, [(token, text), ...]) tuple. + """ + def get_tokens(): + text = '\n'.join(document.lines[start_lineno:])[column:] + + # We call `get_tokens_unprocessed`, because `get_tokens` will + # still replace \r\n and \r by \n. (We don't want that, + # Pygments should return exactly the same amount of text, as we + # have given as input.) + for _, t, v in self.pygments_lexer.get_tokens_unprocessed(text): + yield t, v + + return enumerate(split_lines(get_tokens()), start_lineno) + + def get_generator(i): + """ + Find an already started generator that is close, or create a new one. + """ + # Find closest line generator. + generator = find_closest_generator(i) + if generator: + return generator + + # No generator found. Determine starting point for the syntax + # synchronisation first. + + # Go at least x lines back. (Make scrolling upwards more + # efficient.) + i = max(0, i - self.MIN_LINES_BACKWARDS) + + if i == 0: + row = 0 + column = 0 + else: + row, column = get_syntax_sync().get_sync_start_position(document, i) + + # Find generator close to this point, or otherwise create a new one. + generator = find_closest_generator(i) + if generator: + return generator + else: + generator = create_line_generator(row, column) + + # If the column is not 0, ignore the first line. (Which is + # incomplete. This happens when the synchronisation algorithm tells + # us to start parsing in the middle of a line.) + if column: + next(generator) + row += 1 + + line_generators[generator] = row + return generator + + def get_line(i): + " Return the tokens for a given line number. " + try: + return cache[i] + except KeyError: + generator = get_generator(i) + + # Exhaust the generator, until we find the requested line. + for num, line in generator: + cache[num] = line + if num == i: + line_generators[generator] = i + + # Remove the next item from the cache. + # (It could happen that it's already there, because of + # another generator that started filling these lines, + # but we want to synchronise these lines with the + # current lexer's state.) + if num + 1 in cache: + del cache[num + 1] + + return cache[num] + return [] + + return get_line diff --git a/contrib/python/prompt-toolkit/py2/prompt_toolkit/layout/margins.py b/contrib/python/prompt-toolkit/py2/prompt_toolkit/layout/margins.py index 2934dfc9a7..1c596094d6 100644 --- a/contrib/python/prompt-toolkit/py2/prompt_toolkit/layout/margins.py +++ b/contrib/python/prompt-toolkit/py2/prompt_toolkit/layout/margins.py @@ -3,21 +3,21 @@ Margin implementations for a :class:`~prompt_toolkit.layout.containers.Window`. """ from __future__ import unicode_literals -from abc import ABCMeta, abstractmethod +from abc import ABCMeta, abstractmethod from six import with_metaclass -from six.moves import range +from six.moves import range from prompt_toolkit.filters import to_cli_filter -from prompt_toolkit.token import Token -from prompt_toolkit.utils import get_cwidth -from .utils import token_list_to_text +from prompt_toolkit.token import Token +from prompt_toolkit.utils import get_cwidth +from .utils import token_list_to_text __all__ = ( 'Margin', 'NumberredMargin', 'ScrollbarMargin', 'ConditionalMargin', - 'PromptMargin', + 'PromptMargin', ) @@ -26,14 +26,14 @@ class Margin(with_metaclass(ABCMeta, object)): Base interface for a margin. """ @abstractmethod - def get_width(self, cli, get_ui_content): + def get_width(self, cli, get_ui_content): """ Return the width that this margin is going to consume. - - :param cli: :class:`.CommandLineInterface` instance. - :param get_ui_content: Callable that asks the user control to create - a :class:`.UIContent` instance. This can be used for instance to - obtain the number of lines. + + :param cli: :class:`.CommandLineInterface` instance. + :param get_ui_content: Callable that asks the user control to create + a :class:`.UIContent` instance. This can be used for instance to + obtain the number of lines. """ return 0 @@ -43,7 +43,7 @@ class Margin(with_metaclass(ABCMeta, object)): Creates a margin. This should return a list of (Token, text) tuples. - :param cli: :class:`.CommandLineInterface` instance. + :param cli: :class:`.CommandLineInterface` instance. :param window_render_info: :class:`~prompt_toolkit.layout.containers.WindowRenderInfo` instance, generated after rendering and copying the visible part of @@ -63,16 +63,16 @@ class NumberredMargin(Margin): :param relative: Number relative to the cursor position. Similar to the Vi 'relativenumber' option. - :param display_tildes: Display tildes after the end of the document, just - like Vi does. + :param display_tildes: Display tildes after the end of the document, just + like Vi does. """ - def __init__(self, relative=False, display_tildes=False): + def __init__(self, relative=False, display_tildes=False): self.relative = to_cli_filter(relative) - self.display_tildes = to_cli_filter(display_tildes) + self.display_tildes = to_cli_filter(display_tildes) - def get_width(self, cli, get_ui_content): - line_count = get_ui_content().line_count - return max(3, len('%s' % line_count) + 1) + def get_width(self, cli, get_ui_content): + line_count = get_ui_content().line_count + return max(3, len('%s' % line_count) + 1) def create_margin(self, cli, window_render_info, width, height): relative = self.relative(cli) @@ -81,40 +81,40 @@ class NumberredMargin(Margin): token_current = Token.LineNumber.Current # Get current line number. - current_lineno = window_render_info.ui_content.cursor_position.y + current_lineno = window_render_info.ui_content.cursor_position.y # Construct margin. result = [] - last_lineno = None - - for y, lineno in enumerate(window_render_info.displayed_lines): - # Only display line number if this line is not a continuation of the previous line. - if lineno != last_lineno: - if lineno is None: - pass - elif lineno == current_lineno: + last_lineno = None + + for y, lineno in enumerate(window_render_info.displayed_lines): + # Only display line number if this line is not a continuation of the previous line. + if lineno != last_lineno: + if lineno is None: + pass + elif lineno == current_lineno: # Current line. if relative: # Left align current number in relative mode. - result.append((token_current, '%i' % (lineno + 1))) + result.append((token_current, '%i' % (lineno + 1))) else: - result.append((token_current, ('%i ' % (lineno + 1)).rjust(width))) + result.append((token_current, ('%i ' % (lineno + 1)).rjust(width))) else: # Other lines. if relative: - lineno = abs(lineno - current_lineno) - 1 + lineno = abs(lineno - current_lineno) - 1 - result.append((token, ('%i ' % (lineno + 1)).rjust(width))) + result.append((token, ('%i ' % (lineno + 1)).rjust(width))) - last_lineno = lineno + last_lineno = lineno result.append((Token, '\n')) - # Fill with tildes. - if self.display_tildes(cli): - while y < window_render_info.window_height: - result.append((Token.Tilde, '~\n')) - y += 1 - + # Fill with tildes. + if self.display_tildes(cli): + while y < window_render_info.window_height: + result.append((Token.Tilde, '~\n')) + y += 1 + return result @@ -128,9 +128,9 @@ class ConditionalMargin(Margin): self.margin = margin self.filter = to_cli_filter(filter) - def get_width(self, cli, ui_content): + def get_width(self, cli, ui_content): if self.filter(cli): - return self.margin.get_width(cli, ui_content) + return self.margin.get_width(cli, ui_content) else: return 0 @@ -144,110 +144,110 @@ class ConditionalMargin(Margin): class ScrollbarMargin(Margin): """ Margin displaying a scrollbar. - - :param display_arrows: Display scroll up/down arrows. + + :param display_arrows: Display scroll up/down arrows. """ - def __init__(self, display_arrows=False): - self.display_arrows = to_cli_filter(display_arrows) - - def get_width(self, cli, ui_content): + def __init__(self, display_arrows=False): + self.display_arrows = to_cli_filter(display_arrows) + + def get_width(self, cli, ui_content): return 1 def create_margin(self, cli, window_render_info, width, height): total_height = window_render_info.content_height - display_arrows = self.display_arrows(cli) - - window_height = window_render_info.window_height - if display_arrows: - window_height -= 2 - - try: - items_per_row = float(total_height) / min(total_height, window_height) - except ZeroDivisionError: - return [] - else: - def is_scroll_button(row): - " True if we should display a button on this row. " - current_row_middle = int((row + .5) * items_per_row) - return current_row_middle in window_render_info.displayed_lines - - # Up arrow. - result = [] - if display_arrows: - result.extend([ - (Token.Scrollbar.Arrow, '^'), - (Token.Scrollbar, '\n') - ]) - - # Scrollbar body. - for i in range(window_height): - if is_scroll_button(i): - result.append((Token.Scrollbar.Button, ' ')) - else: - result.append((Token.Scrollbar, ' ')) - result.append((Token, '\n')) - - # Down arrow - if display_arrows: - result.append((Token.Scrollbar.Arrow, 'v')) - - return result - - -class PromptMargin(Margin): - """ - Create margin that displays a prompt. - This can display one prompt at the first line, and a continuation prompt - (e.g, just dots) on all the following lines. - - :param get_prompt_tokens: Callable that takes a CommandLineInterface as - input and returns a list of (Token, type) tuples to be shown as the - prompt at the first line. - :param get_continuation_tokens: Callable that takes a CommandLineInterface - and a width as input and returns a list of (Token, type) tuples for the - next lines of the input. - :param show_numbers: (bool or :class:`~prompt_toolkit.filters.CLIFilter`) - Display line numbers instead of the continuation prompt. - """ - def __init__(self, get_prompt_tokens, get_continuation_tokens=None, - show_numbers=False): - assert callable(get_prompt_tokens) - assert get_continuation_tokens is None or callable(get_continuation_tokens) - show_numbers = to_cli_filter(show_numbers) - - self.get_prompt_tokens = get_prompt_tokens - self.get_continuation_tokens = get_continuation_tokens - self.show_numbers = show_numbers - - def get_width(self, cli, ui_content): - " Width to report to the `Window`. " - # Take the width from the first line. - text = token_list_to_text(self.get_prompt_tokens(cli)) - return get_cwidth(text) - - def create_margin(self, cli, window_render_info, width, height): - # First line. - tokens = self.get_prompt_tokens(cli)[:] - - # Next lines. (Show line numbering when numbering is enabled.) - if self.get_continuation_tokens: + display_arrows = self.display_arrows(cli) + + window_height = window_render_info.window_height + if display_arrows: + window_height -= 2 + + try: + items_per_row = float(total_height) / min(total_height, window_height) + except ZeroDivisionError: + return [] + else: + def is_scroll_button(row): + " True if we should display a button on this row. " + current_row_middle = int((row + .5) * items_per_row) + return current_row_middle in window_render_info.displayed_lines + + # Up arrow. + result = [] + if display_arrows: + result.extend([ + (Token.Scrollbar.Arrow, '^'), + (Token.Scrollbar, '\n') + ]) + + # Scrollbar body. + for i in range(window_height): + if is_scroll_button(i): + result.append((Token.Scrollbar.Button, ' ')) + else: + result.append((Token.Scrollbar, ' ')) + result.append((Token, '\n')) + + # Down arrow + if display_arrows: + result.append((Token.Scrollbar.Arrow, 'v')) + + return result + + +class PromptMargin(Margin): + """ + Create margin that displays a prompt. + This can display one prompt at the first line, and a continuation prompt + (e.g, just dots) on all the following lines. + + :param get_prompt_tokens: Callable that takes a CommandLineInterface as + input and returns a list of (Token, type) tuples to be shown as the + prompt at the first line. + :param get_continuation_tokens: Callable that takes a CommandLineInterface + and a width as input and returns a list of (Token, type) tuples for the + next lines of the input. + :param show_numbers: (bool or :class:`~prompt_toolkit.filters.CLIFilter`) + Display line numbers instead of the continuation prompt. + """ + def __init__(self, get_prompt_tokens, get_continuation_tokens=None, + show_numbers=False): + assert callable(get_prompt_tokens) + assert get_continuation_tokens is None or callable(get_continuation_tokens) + show_numbers = to_cli_filter(show_numbers) + + self.get_prompt_tokens = get_prompt_tokens + self.get_continuation_tokens = get_continuation_tokens + self.show_numbers = show_numbers + + def get_width(self, cli, ui_content): + " Width to report to the `Window`. " + # Take the width from the first line. + text = token_list_to_text(self.get_prompt_tokens(cli)) + return get_cwidth(text) + + def create_margin(self, cli, window_render_info, width, height): + # First line. + tokens = self.get_prompt_tokens(cli)[:] + + # Next lines. (Show line numbering when numbering is enabled.) + if self.get_continuation_tokens: # Note: we turn this into a list, to make sure that we fail early # in case `get_continuation_tokens` returns something else, # like `None`. tokens2 = list(self.get_continuation_tokens(cli, width)) - else: - tokens2 = [] - - show_numbers = self.show_numbers(cli) - last_y = None - - for y in window_render_info.displayed_lines[1:]: - tokens.append((Token, '\n')) - if show_numbers: - if y != last_y: - tokens.append((Token.LineNumber, ('%i ' % (y + 1)).rjust(width))) + else: + tokens2 = [] + + show_numbers = self.show_numbers(cli) + last_y = None + + for y in window_render_info.displayed_lines[1:]: + tokens.append((Token, '\n')) + if show_numbers: + if y != last_y: + tokens.append((Token.LineNumber, ('%i ' % (y + 1)).rjust(width))) else: - tokens.extend(tokens2) - last_y = y + tokens.extend(tokens2) + last_y = y - return tokens + return tokens diff --git a/contrib/python/prompt-toolkit/py2/prompt_toolkit/layout/menus.py b/contrib/python/prompt-toolkit/py2/prompt_toolkit/layout/menus.py index a916846e45..8883d0594e 100644 --- a/contrib/python/prompt-toolkit/py2/prompt_toolkit/layout/menus.py +++ b/contrib/python/prompt-toolkit/py2/prompt_toolkit/layout/menus.py @@ -1,16 +1,16 @@ from __future__ import unicode_literals -from six.moves import zip_longest, range -from prompt_toolkit.filters import HasCompletions, IsDone, Condition, to_cli_filter -from prompt_toolkit.mouse_events import MouseEventType -from prompt_toolkit.token import Token +from six.moves import zip_longest, range +from prompt_toolkit.filters import HasCompletions, IsDone, Condition, to_cli_filter +from prompt_toolkit.mouse_events import MouseEventType +from prompt_toolkit.token import Token from prompt_toolkit.utils import get_cwidth -from .containers import Window, HSplit, ConditionalContainer, ScrollOffsets -from .controls import UIControl, UIContent +from .containers import Window, HSplit, ConditionalContainer, ScrollOffsets +from .controls import UIControl, UIContent from .dimension import LayoutDimension -from .margins import ScrollbarMargin -from .screen import Point, Char +from .margins import ScrollbarMargin +from .screen import Point, Char import math @@ -29,12 +29,12 @@ class CompletionsMenuControl(UIControl): is a very high number, the current completion will be shown in the middle most of the time. """ - # Preferred minimum size of the menu control. - # The CompletionsMenu class defines a width of 8, and there is a scrollbar - # of 1.) - MIN_WIDTH = 7 + # Preferred minimum size of the menu control. + # The CompletionsMenu class defines a width of 8, and there is a scrollbar + # of 1.) + MIN_WIDTH = 7 - def __init__(self): + def __init__(self): self.token = Token.Menu.Completions def has_focus(self, cli): @@ -46,20 +46,20 @@ class CompletionsMenuControl(UIControl): menu_width = self._get_menu_width(500, complete_state) menu_meta_width = self._get_menu_meta_width(500, complete_state) - return menu_width + menu_meta_width + return menu_width + menu_meta_width else: return 0 - def preferred_height(self, cli, width, max_available_height, wrap_lines): + def preferred_height(self, cli, width, max_available_height, wrap_lines): complete_state = cli.current_buffer.complete_state if complete_state: return len(complete_state.current_completions) else: return 0 - def create_content(self, cli, width, height): + def create_content(self, cli, width, height): """ - Create a UIContent object for this control. + Create a UIContent object for this control. """ complete_state = cli.current_buffer.complete_state if complete_state: @@ -67,25 +67,25 @@ class CompletionsMenuControl(UIControl): index = complete_state.complete_index # Can be None! # Calculate width of completions menu. - menu_width = self._get_menu_width(width, complete_state) - menu_meta_width = self._get_menu_meta_width(width - menu_width, complete_state) + menu_width = self._get_menu_width(width, complete_state) + menu_meta_width = self._get_menu_meta_width(width - menu_width, complete_state) show_meta = self._show_meta(complete_state) - def get_line(i): - c = completions[i] - is_current_completion = (i == index) - result = self._get_menu_item_tokens(c, is_current_completion, menu_width) + def get_line(i): + c = completions[i] + is_current_completion = (i == index) + result = self._get_menu_item_tokens(c, is_current_completion, menu_width) - if show_meta: - result += self._get_menu_item_meta_tokens(c, is_current_completion, menu_meta_width) - return result + if show_meta: + result += self._get_menu_item_meta_tokens(c, is_current_completion, menu_meta_width) + return result - return UIContent(get_line=get_line, - cursor_position=Point(x=0, y=index or 0), - line_count=len(completions), - default_char=Char(' ', self.token)) + return UIContent(get_line=get_line, + cursor_position=Point(x=0, y=index or 0), + line_count=len(completions), + default_char=Char(' ', self.token)) - return UIContent() + return UIContent() def _show_meta(self, complete_state): """ @@ -97,8 +97,8 @@ class CompletionsMenuControl(UIControl): """ Return the width of the main column. """ - return min(max_width, max(self.MIN_WIDTH, max(get_cwidth(c.display) - for c in complete_state.current_completions) + 2)) + return min(max_width, max(self.MIN_WIDTH, max(get_cwidth(c.display) + for c in complete_state.current_completions) + 2)) def _get_menu_meta_width(self, max_width, complete_state): """ @@ -136,16 +136,16 @@ class CompletionsMenuControl(UIControl): """ b = cli.current_buffer - if mouse_event.event_type == MouseEventType.MOUSE_UP: + if mouse_event.event_type == MouseEventType.MOUSE_UP: # Select completion. - b.go_to_completion(mouse_event.position.y) + b.go_to_completion(mouse_event.position.y) b.complete_state = None - elif mouse_event.event_type == MouseEventType.SCROLL_DOWN: + elif mouse_event.event_type == MouseEventType.SCROLL_DOWN: # Scroll up. b.complete_next(count=3, disable_wrap_around=True) - elif mouse_event.event_type == MouseEventType.SCROLL_UP: + elif mouse_event.event_type == MouseEventType.SCROLL_UP: # Scroll down. b.complete_previous(count=3, disable_wrap_around=True) @@ -179,19 +179,19 @@ def _trim_text(text, max_width): class CompletionsMenu(ConditionalContainer): - def __init__(self, max_height=None, scroll_offset=0, extra_filter=True, display_arrows=False): - extra_filter = to_cli_filter(extra_filter) - display_arrows = to_cli_filter(display_arrows) - + def __init__(self, max_height=None, scroll_offset=0, extra_filter=True, display_arrows=False): + extra_filter = to_cli_filter(extra_filter) + display_arrows = to_cli_filter(display_arrows) + super(CompletionsMenu, self).__init__( content=Window( - content=CompletionsMenuControl(), + content=CompletionsMenuControl(), width=LayoutDimension(min=8), - height=LayoutDimension(min=1, max=max_height), - scroll_offsets=ScrollOffsets(top=scroll_offset, bottom=scroll_offset), - right_margins=[ScrollbarMargin(display_arrows=display_arrows)], - dont_extend_width=True, - ), + height=LayoutDimension(min=1, max=max_height), + scroll_offsets=ScrollOffsets(top=scroll_offset, bottom=scroll_offset), + right_margins=[ScrollbarMargin(display_arrows=display_arrows)], + dont_extend_width=True, + ), # Show when there are completions but not at the point we are # returning the input. filter=HasCompletions() & ~IsDone() & extra_filter) @@ -260,7 +260,7 @@ class MultiColumnCompletionMenuControl(UIControl): result -= column_width return result + self._required_margin - def preferred_height(self, cli, width, max_available_height, wrap_lines): + def preferred_height(self, cli, width, max_available_height, wrap_lines): """ Preferred height: as much as needed in order to display all the completions. """ @@ -270,9 +270,9 @@ class MultiColumnCompletionMenuControl(UIControl): return int(math.ceil(len(complete_state.current_completions) / float(column_count))) - def create_content(self, cli, width, height): + def create_content(self, cli, width, height): """ - Create a UIContent object for this menu. + Create a UIContent object for this menu. """ complete_state = cli.current_buffer.complete_state column_width = self._get_column_width(complete_state) @@ -316,15 +316,15 @@ class MultiColumnCompletionMenuControl(UIControl): render_right_arrow = self.scroll < len(rows_[0]) - visible_columns # Write completions to screen. - tokens_for_line = [] + tokens_for_line = [] for row_index, row in enumerate(rows_): - tokens = [] + tokens = [] middle_row = row_index == len(rows_) // 2 # Draw left arrow if we have hidden completions on the left. if render_left_arrow: - tokens += [(Token.Scrollbar, '<' if middle_row else ' ')] + tokens += [(Token.Scrollbar, '<' if middle_row else ' ')] # Draw row content. for column_index, c in enumerate(row[self.scroll:][:visible_columns]): @@ -342,13 +342,13 @@ class MultiColumnCompletionMenuControl(UIControl): # Draw right arrow if we have hidden completions on the right. if render_right_arrow: - tokens += [(Token.Scrollbar, '>' if middle_row else ' ')] + tokens += [(Token.Scrollbar, '>' if middle_row else ' ')] # Newline. - tokens_for_line.append(tokens) + tokens_for_line.append(tokens) - else: - tokens = [] + else: + tokens = [] self._rendered_rows = height self._rendered_columns = visible_columns @@ -357,11 +357,11 @@ class MultiColumnCompletionMenuControl(UIControl): self._render_right_arrow = render_right_arrow self._render_width = column_width * visible_columns + render_left_arrow + render_right_arrow + 1 - def get_line(i): - return tokens_for_line[i] - - return UIContent(get_line=get_line, line_count=len(rows_)) + def get_line(i): + return tokens_for_line[i] + return UIContent(get_line=get_line, line_count=len(rows_)) + def _get_column_width(self, complete_state): """ Return the width of each column. @@ -393,13 +393,13 @@ class MultiColumnCompletionMenuControl(UIControl): b.complete_next(count=self._rendered_rows, disable_wrap_around=True) self.scroll = min(self._total_columns - self._rendered_columns, self.scroll + 1) - if mouse_event.event_type == MouseEventType.SCROLL_DOWN: + if mouse_event.event_type == MouseEventType.SCROLL_DOWN: scroll_right() - elif mouse_event.event_type == MouseEventType.SCROLL_UP: + elif mouse_event.event_type == MouseEventType.SCROLL_UP: scroll_left() - elif mouse_event.event_type == MouseEventType.MOUSE_UP: + elif mouse_event.event_type == MouseEventType.MOUSE_UP: x = mouse_event.position.x y = mouse_event.position.y @@ -475,17 +475,17 @@ class _SelectedCompletionMetaControl(UIControl): else: return 0 - def preferred_height(self, cli, width, max_available_height, wrap_lines): + def preferred_height(self, cli, width, max_available_height, wrap_lines): return 1 - def create_content(self, cli, width, height): - tokens = self._get_tokens(cli) - - def get_line(i): - return tokens - - return UIContent(get_line=get_line, line_count=1 if tokens else 0) + def create_content(self, cli, width, height): + tokens = self._get_tokens(cli) + def get_line(i): + return tokens + + return UIContent(get_line=get_line, line_count=1 if tokens else 0) + def _get_tokens(self, cli): token = Token.Menu.Completions.MultiColumnMeta state = cli.current_buffer.complete_state diff --git a/contrib/python/prompt-toolkit/py2/prompt_toolkit/layout/processors.py b/contrib/python/prompt-toolkit/py2/prompt_toolkit/layout/processors.py index 0b8bc9c223..fc3e29a089 100644 --- a/contrib/python/prompt-toolkit/py2/prompt_toolkit/layout/processors.py +++ b/contrib/python/prompt-toolkit/py2/prompt_toolkit/layout/processors.py @@ -8,20 +8,20 @@ token types. from __future__ import unicode_literals from abc import ABCMeta, abstractmethod from six import with_metaclass -from six.moves import range +from six.moves import range -from prompt_toolkit.cache import SimpleCache +from prompt_toolkit.cache import SimpleCache from prompt_toolkit.document import Document from prompt_toolkit.enums import SEARCH_BUFFER -from prompt_toolkit.filters import to_cli_filter, ViInsertMultipleMode +from prompt_toolkit.filters import to_cli_filter, ViInsertMultipleMode from prompt_toolkit.layout.utils import token_list_to_text -from prompt_toolkit.reactive import Integer -from prompt_toolkit.token import Token +from prompt_toolkit.reactive import Integer +from prompt_toolkit.token import Token -from .utils import token_list_len, explode_tokens - -import re +from .utils import token_list_len, explode_tokens +import re + __all__ = ( 'Processor', 'Transformation', @@ -29,37 +29,37 @@ __all__ = ( 'HighlightSearchProcessor', 'HighlightSelectionProcessor', 'PasswordProcessor', - 'HighlightMatchingBracketProcessor', - 'DisplayMultipleCursors', + 'HighlightMatchingBracketProcessor', + 'DisplayMultipleCursors', 'BeforeInput', 'AfterInput', 'AppendAutoSuggestion', 'ConditionalProcessor', 'ShowLeadingWhiteSpaceProcessor', 'ShowTrailingWhiteSpaceProcessor', - 'TabsProcessor', + 'TabsProcessor', ) class Processor(with_metaclass(ABCMeta, object)): """ - Manipulate the tokens for a given line in a + Manipulate the tokens for a given line in a :class:`~prompt_toolkit.layout.controls.BufferControl`. """ @abstractmethod - def apply_transformation(self, cli, document, lineno, source_to_display, tokens): + def apply_transformation(self, cli, document, lineno, source_to_display, tokens): """ Apply transformation. Returns a :class:`.Transformation` instance. - - :param cli: :class:`.CommandLineInterface` instance. - :param lineno: The number of the line to which we apply the processor. - :param source_to_display: A function that returns the position in the - `tokens` for any position in the source string. (This takes - previous processors into account.) - :param tokens: List of tokens that we can transform. (Received from the - previous processor.) + + :param cli: :class:`.CommandLineInterface` instance. + :param lineno: The number of the line to which we apply the processor. + :param source_to_display: A function that returns the position in the + `tokens` for any position in the source string. (This takes + previous processors into account.) + :param tokens: List of tokens that we can transform. (Received from the + previous processor.) """ - return Transformation(tokens) + return Transformation(tokens) def has_focus(self, cli): """ @@ -83,26 +83,26 @@ class Transformation(object): :param display_to_source: Cursor position transformed from source string to original string. """ - def __init__(self, tokens, source_to_display=None, display_to_source=None): + def __init__(self, tokens, source_to_display=None, display_to_source=None): self.tokens = tokens self.source_to_display = source_to_display or (lambda i: i) self.display_to_source = display_to_source or (lambda i: i) -class HighlightSearchProcessor(Processor): +class HighlightSearchProcessor(Processor): """ Processor that highlights search matches in the document. - Note that this doesn't support multiline search matches yet. + Note that this doesn't support multiline search matches yet. :param preview_search: A Filter; when active it indicates that we take the search text in real time while the user is typing, instead of the last active search state. """ - def __init__(self, preview_search=False, search_buffer_name=SEARCH_BUFFER, - get_search_state=None): + def __init__(self, preview_search=False, search_buffer_name=SEARCH_BUFFER, + get_search_state=None): self.preview_search = to_cli_filter(preview_search) self.search_buffer_name = search_buffer_name - self.get_search_state = get_search_state or (lambda cli: cli.search_state) + self.get_search_state = get_search_state or (lambda cli: cli.search_state) def _get_search_text(self, cli): """ @@ -113,70 +113,70 @@ class HighlightSearchProcessor(Processor): return cli.buffers[self.search_buffer_name].text # Otherwise, take the text of the last active search. else: - return self.get_search_state(cli).text + return self.get_search_state(cli).text - def apply_transformation(self, cli, document, lineno, source_to_display, tokens): + def apply_transformation(self, cli, document, lineno, source_to_display, tokens): search_text = self._get_search_text(cli) - searchmatch_current_token = (':', ) + Token.SearchMatch.Current - searchmatch_token = (':', ) + Token.SearchMatch + searchmatch_current_token = (':', ) + Token.SearchMatch.Current + searchmatch_token = (':', ) + Token.SearchMatch if search_text and not cli.is_returning: # For each search match, replace the Token. - line_text = token_list_to_text(tokens) - tokens = explode_tokens(tokens) + line_text = token_list_to_text(tokens) + tokens = explode_tokens(tokens) - flags = re.IGNORECASE if cli.is_ignoring_case else 0 + flags = re.IGNORECASE if cli.is_ignoring_case else 0 - # Get cursor column. - if document.cursor_position_row == lineno: - cursor_column = source_to_display(document.cursor_position_col) - else: - cursor_column = None + # Get cursor column. + if document.cursor_position_row == lineno: + cursor_column = source_to_display(document.cursor_position_col) + else: + cursor_column = None - for match in re.finditer(re.escape(search_text), line_text, flags=flags): - if cursor_column is not None: - on_cursor = match.start() <= cursor_column < match.end() - else: - on_cursor = False + for match in re.finditer(re.escape(search_text), line_text, flags=flags): + if cursor_column is not None: + on_cursor = match.start() <= cursor_column < match.end() + else: + on_cursor = False - for i in range(match.start(), match.end()): - old_token, text = tokens[i] - if on_cursor: - tokens[i] = (old_token + searchmatch_current_token, tokens[i][1]) - else: - tokens[i] = (old_token + searchmatch_token, tokens[i][1]) + for i in range(match.start(), match.end()): + old_token, text = tokens[i] + if on_cursor: + tokens[i] = (old_token + searchmatch_current_token, tokens[i][1]) + else: + tokens[i] = (old_token + searchmatch_token, tokens[i][1]) - return Transformation(tokens) + return Transformation(tokens) -class HighlightSelectionProcessor(Processor): +class HighlightSelectionProcessor(Processor): """ Processor that highlights the selection in the document. """ - def apply_transformation(self, cli, document, lineno, source_to_display, tokens): - selected_token = (':', ) + Token.SelectedText - + def apply_transformation(self, cli, document, lineno, source_to_display, tokens): + selected_token = (':', ) + Token.SelectedText + # In case of selection, highlight all matches. - selection_at_line = document.selection_range_at_line(lineno) + selection_at_line = document.selection_range_at_line(lineno) - if selection_at_line: - from_, to = selection_at_line - from_ = source_to_display(from_) - to = source_to_display(to) + if selection_at_line: + from_, to = selection_at_line + from_ = source_to_display(from_) + to = source_to_display(to) - tokens = explode_tokens(tokens) + tokens = explode_tokens(tokens) - if from_ == 0 and to == 0 and len(tokens) == 0: - # When this is an empty line, insert a space in order to - # visualiase the selection. - return Transformation([(Token.SelectedText, ' ')]) - else: - for i in range(from_, to + 1): - if i < len(tokens): - old_token, old_text = tokens[i] - tokens[i] = (old_token + selected_token, old_text) + if from_ == 0 and to == 0 and len(tokens) == 0: + # When this is an empty line, insert a space in order to + # visualiase the selection. + return Transformation([(Token.SelectedText, ' ')]) + else: + for i in range(from_, to + 1): + if i < len(tokens): + old_token, old_text = tokens[i] + tokens[i] = (old_token + selected_token, old_text) - return Transformation(tokens) + return Transformation(tokens) class PasswordProcessor(Processor): @@ -188,121 +188,121 @@ class PasswordProcessor(Processor): def __init__(self, char='*'): self.char = char - def apply_transformation(self, cli, document, lineno, source_to_display, tokens): - tokens = [(token, self.char * len(text)) for token, text in tokens] - return Transformation(tokens) + def apply_transformation(self, cli, document, lineno, source_to_display, tokens): + tokens = [(token, self.char * len(text)) for token, text in tokens] + return Transformation(tokens) -class HighlightMatchingBracketProcessor(Processor): +class HighlightMatchingBracketProcessor(Processor): """ When the cursor is on or right after a bracket, it highlights the matching bracket. - - :param max_cursor_distance: Only highlight matching brackets when the - cursor is within this distance. (From inside a `Processor`, we can't - know which lines will be visible on the screen. But we also don't want - to scan the whole document for matching brackets on each key press, so - we limit to this value.) + + :param max_cursor_distance: Only highlight matching brackets when the + cursor is within this distance. (From inside a `Processor`, we can't + know which lines will be visible on the screen. But we also don't want + to scan the whole document for matching brackets on each key press, so + we limit to this value.) """ _closing_braces = '])}>' - def __init__(self, chars='[](){}<>', max_cursor_distance=1000): + def __init__(self, chars='[](){}<>', max_cursor_distance=1000): self.chars = chars - self.max_cursor_distance = max_cursor_distance - - self._positions_cache = SimpleCache(maxsize=8) - - def _get_positions_to_highlight(self, document): - """ - Return a list of (row, col) tuples that need to be highlighted. - """ - # Try for the character under the cursor. - if document.current_char and document.current_char in self.chars: - pos = document.find_matching_bracket_position( - start_pos=document.cursor_position - self.max_cursor_distance, - end_pos=document.cursor_position + self.max_cursor_distance) - - # Try for the character before the cursor. - elif (document.char_before_cursor and document.char_before_cursor in - self._closing_braces and document.char_before_cursor in self.chars): - document = Document(document.text, document.cursor_position - 1) - - pos = document.find_matching_bracket_position( - start_pos=document.cursor_position - self.max_cursor_distance, - end_pos=document.cursor_position + self.max_cursor_distance) - else: - pos = None - - # Return a list of (row, col) tuples that need to be highlighted. - if pos: - pos += document.cursor_position # pos is relative. - row, col = document.translate_index_to_position(pos) - return [(row, col), (document.cursor_position_row, document.cursor_position_col)] - else: - return [] - - def apply_transformation(self, cli, document, lineno, source_to_display, tokens): - # Get the highlight positions. - key = (cli.render_counter, document.text, document.cursor_position) - positions = self._positions_cache.get( - key, lambda: self._get_positions_to_highlight(document)) - - # Apply if positions were found at this line. - if positions: - for row, col in positions: - if row == lineno: - col = source_to_display(col) - tokens = explode_tokens(tokens) - token, text = tokens[col] - - if col == document.cursor_position_col: - token += (':', ) + Token.MatchingBracket.Cursor - else: - token += (':', ) + Token.MatchingBracket.Other - - tokens[col] = (token, text) - - return Transformation(tokens) - - -class DisplayMultipleCursors(Processor): + self.max_cursor_distance = max_cursor_distance + + self._positions_cache = SimpleCache(maxsize=8) + + def _get_positions_to_highlight(self, document): + """ + Return a list of (row, col) tuples that need to be highlighted. + """ + # Try for the character under the cursor. + if document.current_char and document.current_char in self.chars: + pos = document.find_matching_bracket_position( + start_pos=document.cursor_position - self.max_cursor_distance, + end_pos=document.cursor_position + self.max_cursor_distance) + + # Try for the character before the cursor. + elif (document.char_before_cursor and document.char_before_cursor in + self._closing_braces and document.char_before_cursor in self.chars): + document = Document(document.text, document.cursor_position - 1) + + pos = document.find_matching_bracket_position( + start_pos=document.cursor_position - self.max_cursor_distance, + end_pos=document.cursor_position + self.max_cursor_distance) + else: + pos = None + + # Return a list of (row, col) tuples that need to be highlighted. + if pos: + pos += document.cursor_position # pos is relative. + row, col = document.translate_index_to_position(pos) + return [(row, col), (document.cursor_position_row, document.cursor_position_col)] + else: + return [] + + def apply_transformation(self, cli, document, lineno, source_to_display, tokens): + # Get the highlight positions. + key = (cli.render_counter, document.text, document.cursor_position) + positions = self._positions_cache.get( + key, lambda: self._get_positions_to_highlight(document)) + + # Apply if positions were found at this line. + if positions: + for row, col in positions: + if row == lineno: + col = source_to_display(col) + tokens = explode_tokens(tokens) + token, text = tokens[col] + + if col == document.cursor_position_col: + token += (':', ) + Token.MatchingBracket.Cursor + else: + token += (':', ) + Token.MatchingBracket.Other + + tokens[col] = (token, text) + + return Transformation(tokens) + + +class DisplayMultipleCursors(Processor): """ - When we're in Vi block insert mode, display all the cursors. + When we're in Vi block insert mode, display all the cursors. """ - _insert_multiple = ViInsertMultipleMode() + _insert_multiple = ViInsertMultipleMode() - def __init__(self, buffer_name): - self.buffer_name = buffer_name - - def apply_transformation(self, cli, document, lineno, source_to_display, tokens): - buff = cli.buffers[self.buffer_name] + def __init__(self, buffer_name): + self.buffer_name = buffer_name - if self._insert_multiple(cli): - positions = buff.multiple_cursor_positions - tokens = explode_tokens(tokens) + def apply_transformation(self, cli, document, lineno, source_to_display, tokens): + buff = cli.buffers[self.buffer_name] - # If any cursor appears on the current line, highlight that. - start_pos = document.translate_row_col_to_index(lineno, 0) - end_pos = start_pos + len(document.lines[lineno]) + if self._insert_multiple(cli): + positions = buff.multiple_cursor_positions + tokens = explode_tokens(tokens) - token_suffix = (':', ) + Token.MultipleCursors.Cursor + # If any cursor appears on the current line, highlight that. + start_pos = document.translate_row_col_to_index(lineno, 0) + end_pos = start_pos + len(document.lines[lineno]) - for p in positions: - if start_pos <= p < end_pos: - column = source_to_display(p - start_pos) + token_suffix = (':', ) + Token.MultipleCursors.Cursor - # Replace token. - token, text = tokens[column] - token += token_suffix - tokens[column] = (token, text) - elif p == end_pos: - tokens.append((token_suffix, ' ')) - - return Transformation(tokens) - else: - return Transformation(tokens) + for p in positions: + if start_pos <= p < end_pos: + column = source_to_display(p - start_pos) + # Replace token. + token, text = tokens[column] + token += token_suffix + tokens[column] = (token, text) + elif p == end_pos: + tokens.append((token_suffix, ' ')) + return Transformation(tokens) + else: + return Transformation(tokens) + + class BeforeInput(Processor): """ Insert tokens before the input. @@ -315,21 +315,21 @@ class BeforeInput(Processor): assert callable(get_tokens) self.get_tokens = get_tokens - def apply_transformation(self, cli, document, lineno, source_to_display, tokens): - if lineno == 0: - tokens_before = self.get_tokens(cli) - tokens = tokens_before + tokens - - shift_position = token_list_len(tokens_before) - source_to_display = lambda i: i + shift_position - display_to_source = lambda i: i - shift_position - else: - source_to_display = None - display_to_source = None - - return Transformation(tokens, source_to_display=source_to_display, - display_to_source=display_to_source) - + def apply_transformation(self, cli, document, lineno, source_to_display, tokens): + if lineno == 0: + tokens_before = self.get_tokens(cli) + tokens = tokens_before + tokens + + shift_position = token_list_len(tokens_before) + source_to_display = lambda i: i + shift_position + display_to_source = lambda i: i - shift_position + else: + source_to_display = None + display_to_source = None + + return Transformation(tokens, source_to_display=source_to_display, + display_to_source=display_to_source) + @classmethod def static(cls, text, token=Token): """ @@ -357,12 +357,12 @@ class AfterInput(Processor): assert callable(get_tokens) self.get_tokens = get_tokens - def apply_transformation(self, cli, document, lineno, source_to_display, tokens): - # Insert tokens after the last line. - if lineno == document.line_count - 1: - return Transformation(tokens=tokens + self.get_tokens(cli)) - else: - return Transformation(tokens=tokens) + def apply_transformation(self, cli, document, lineno, source_to_display, tokens): + # Insert tokens after the last line. + if lineno == document.line_count - 1: + return Transformation(tokens=tokens + self.get_tokens(cli)) + else: + return Transformation(tokens=tokens) @classmethod def static(cls, text, token=Token): @@ -397,171 +397,171 @@ class AppendAutoSuggestion(Processor): else: return cli.current_buffer - def apply_transformation(self, cli, document, lineno, source_to_display, tokens): - # Insert tokens after the last line. - if lineno == document.line_count - 1: - buffer = self._get_buffer(cli) - - if buffer.suggestion and buffer.document.is_cursor_at_the_end: - suggestion = buffer.suggestion.text - else: - suggestion = '' - - return Transformation(tokens=tokens + [(self.token, suggestion)]) + def apply_transformation(self, cli, document, lineno, source_to_display, tokens): + # Insert tokens after the last line. + if lineno == document.line_count - 1: + buffer = self._get_buffer(cli) + + if buffer.suggestion and buffer.document.is_cursor_at_the_end: + suggestion = buffer.suggestion.text + else: + suggestion = '' + + return Transformation(tokens=tokens + [(self.token, suggestion)]) else: - return Transformation(tokens=tokens) + return Transformation(tokens=tokens) class ShowLeadingWhiteSpaceProcessor(Processor): """ Make leading whitespace visible. - - :param get_char: Callable that takes a :class:`CommandLineInterface` - instance and returns one character. - :param token: Token to be used. + + :param get_char: Callable that takes a :class:`CommandLineInterface` + instance and returns one character. + :param token: Token to be used. """ - def __init__(self, get_char=None, token=Token.LeadingWhiteSpace): - assert get_char is None or callable(get_char) - - if get_char is None: - def get_char(cli): - if '\xb7'.encode(cli.output.encoding(), 'replace') == b'?': - return '.' - else: - return '\xb7' - + def __init__(self, get_char=None, token=Token.LeadingWhiteSpace): + assert get_char is None or callable(get_char) + + if get_char is None: + def get_char(cli): + if '\xb7'.encode(cli.output.encoding(), 'replace') == b'?': + return '.' + else: + return '\xb7' + self.token = token - self.get_char = get_char + self.get_char = get_char - def apply_transformation(self, cli, document, lineno, source_to_display, tokens): + def apply_transformation(self, cli, document, lineno, source_to_display, tokens): # Walk through all te tokens. - if tokens and token_list_to_text(tokens).startswith(' '): - t = (self.token, self.get_char(cli)) - tokens = explode_tokens(tokens) + if tokens and token_list_to_text(tokens).startswith(' '): + t = (self.token, self.get_char(cli)) + tokens = explode_tokens(tokens) - for i in range(len(tokens)): - if tokens[i][1] == ' ': - tokens[i] = t - else: - break + for i in range(len(tokens)): + if tokens[i][1] == ' ': + tokens[i] = t + else: + break - return Transformation(tokens) + return Transformation(tokens) class ShowTrailingWhiteSpaceProcessor(Processor): """ Make trailing whitespace visible. - - :param get_char: Callable that takes a :class:`CommandLineInterface` - instance and returns one character. - :param token: Token to be used. - """ - def __init__(self, get_char=None, token=Token.TrailingWhiteSpace): - assert get_char is None or callable(get_char) - - if get_char is None: - def get_char(cli): - if '\xb7'.encode(cli.output.encoding(), 'replace') == b'?': - return '.' - else: - return '\xb7' - - self.token = token - self.get_char = get_char - - - def apply_transformation(self, cli, document, lineno, source_to_display, tokens): - if tokens and tokens[-1][1].endswith(' '): - t = (self.token, self.get_char(cli)) - tokens = explode_tokens(tokens) - - # Walk backwards through all te tokens and replace whitespace. - for i in range(len(tokens) - 1, -1, -1): - char = tokens[i][1] - if char == ' ': - tokens[i] = t - else: - break - - return Transformation(tokens) - - -class TabsProcessor(Processor): + + :param get_char: Callable that takes a :class:`CommandLineInterface` + instance and returns one character. + :param token: Token to be used. """ - Render tabs as spaces (instead of ^I) or make them visible (for instance, - by replacing them with dots.) - - :param tabstop: (Integer) Horizontal space taken by a tab. - :param get_char1: Callable that takes a `CommandLineInterface` and return a - character (text of length one). This one is used for the first space - taken by the tab. - :param get_char2: Like `get_char1`, but for the rest of the space. - """ - def __init__(self, tabstop=4, get_char1=None, get_char2=None, token=Token.Tab): - assert isinstance(tabstop, Integer) - assert get_char1 is None or callable(get_char1) - assert get_char2 is None or callable(get_char2) - - self.get_char1 = get_char1 or get_char2 or (lambda cli: '|') - self.get_char2 = get_char2 or get_char1 or (lambda cli: '\u2508') - self.tabstop = tabstop + def __init__(self, get_char=None, token=Token.TrailingWhiteSpace): + assert get_char is None or callable(get_char) + + if get_char is None: + def get_char(cli): + if '\xb7'.encode(cli.output.encoding(), 'replace') == b'?': + return '.' + else: + return '\xb7' + self.token = token - - def apply_transformation(self, cli, document, lineno, source_to_display, tokens): - tabstop = int(self.tabstop) - token = self.token - - # Create separator for tabs. - separator1 = self.get_char1(cli) - separator2 = self.get_char2(cli) - - # Transform tokens. - tokens = explode_tokens(tokens) - - position_mappings = {} - result_tokens = [] - pos = 0 - - for i, token_and_text in enumerate(tokens): - position_mappings[i] = pos - - if token_and_text[1] == '\t': - # Calculate how many characters we have to insert. - count = tabstop - (pos % tabstop) - if count == 0: - count = tabstop - - # Insert tab. - result_tokens.append((token, separator1)) - result_tokens.append((token, separator2 * (count - 1))) - pos += count + self.get_char = get_char + + + def apply_transformation(self, cli, document, lineno, source_to_display, tokens): + if tokens and tokens[-1][1].endswith(' '): + t = (self.token, self.get_char(cli)) + tokens = explode_tokens(tokens) + + # Walk backwards through all te tokens and replace whitespace. + for i in range(len(tokens) - 1, -1, -1): + char = tokens[i][1] + if char == ' ': + tokens[i] = t + else: + break + + return Transformation(tokens) + + +class TabsProcessor(Processor): + """ + Render tabs as spaces (instead of ^I) or make them visible (for instance, + by replacing them with dots.) + + :param tabstop: (Integer) Horizontal space taken by a tab. + :param get_char1: Callable that takes a `CommandLineInterface` and return a + character (text of length one). This one is used for the first space + taken by the tab. + :param get_char2: Like `get_char1`, but for the rest of the space. + """ + def __init__(self, tabstop=4, get_char1=None, get_char2=None, token=Token.Tab): + assert isinstance(tabstop, Integer) + assert get_char1 is None or callable(get_char1) + assert get_char2 is None or callable(get_char2) + + self.get_char1 = get_char1 or get_char2 or (lambda cli: '|') + self.get_char2 = get_char2 or get_char1 or (lambda cli: '\u2508') + self.tabstop = tabstop + self.token = token + + def apply_transformation(self, cli, document, lineno, source_to_display, tokens): + tabstop = int(self.tabstop) + token = self.token + + # Create separator for tabs. + separator1 = self.get_char1(cli) + separator2 = self.get_char2(cli) + + # Transform tokens. + tokens = explode_tokens(tokens) + + position_mappings = {} + result_tokens = [] + pos = 0 + + for i, token_and_text in enumerate(tokens): + position_mappings[i] = pos + + if token_and_text[1] == '\t': + # Calculate how many characters we have to insert. + count = tabstop - (pos % tabstop) + if count == 0: + count = tabstop + + # Insert tab. + result_tokens.append((token, separator1)) + result_tokens.append((token, separator2 * (count - 1))) + pos += count else: - result_tokens.append(token_and_text) - pos += 1 - - position_mappings[len(tokens)] = pos - - def source_to_display(from_position): - " Maps original cursor position to the new one. " - return position_mappings[from_position] - - def display_to_source(display_pos): - " Maps display cursor position to the original one. " - position_mappings_reversed = dict((v, k) for k, v in position_mappings.items()) - - while display_pos >= 0: - try: - return position_mappings_reversed[display_pos] - except KeyError: - display_pos -= 1 - return 0 - - return Transformation( - result_tokens, - source_to_display=source_to_display, - display_to_source=display_to_source) - - + result_tokens.append(token_and_text) + pos += 1 + + position_mappings[len(tokens)] = pos + + def source_to_display(from_position): + " Maps original cursor position to the new one. " + return position_mappings[from_position] + + def display_to_source(display_pos): + " Maps display cursor position to the original one. " + position_mappings_reversed = dict((v, k) for k, v in position_mappings.items()) + + while display_pos >= 0: + try: + return position_mappings_reversed[display_pos] + except KeyError: + display_pos -= 1 + return 0 + + return Transformation( + result_tokens, + source_to_display=source_to_display, + display_to_source=display_to_source) + + class ConditionalProcessor(Processor): """ Processor that applies another processor, according to a certain condition. @@ -586,13 +586,13 @@ class ConditionalProcessor(Processor): self.processor = processor self.filter = to_cli_filter(filter) - def apply_transformation(self, cli, document, lineno, source_to_display, tokens): + def apply_transformation(self, cli, document, lineno, source_to_display, tokens): # Run processor when enabled. if self.filter(cli): - return self.processor.apply_transformation( - cli, document, lineno, source_to_display, tokens) + return self.processor.apply_transformation( + cli, document, lineno, source_to_display, tokens) else: - return Transformation(tokens) + return Transformation(tokens) def has_focus(self, cli): if self.filter(cli): diff --git a/contrib/python/prompt-toolkit/py2/prompt_toolkit/layout/prompt.py b/contrib/python/prompt-toolkit/py2/prompt_toolkit/layout/prompt.py index 7d00ec513e..2a1373efbb 100644 --- a/contrib/python/prompt-toolkit/py2/prompt_toolkit/layout/prompt.py +++ b/contrib/python/prompt-toolkit/py2/prompt_toolkit/layout/prompt.py @@ -3,7 +3,7 @@ from __future__ import unicode_literals from six import text_type from prompt_toolkit.enums import IncrementalSearchDirection, SEARCH_BUFFER -from prompt_toolkit.token import Token +from prompt_toolkit.token import Token from .utils import token_list_len from .processors import Processor, Transformation @@ -45,7 +45,7 @@ class DefaultPrompt(Processor): return [(Token.Prompt, message)] return cls(get_message_tokens) - def apply_transformation(self, cli, document, lineno, source_to_display, tokens): + def apply_transformation(self, cli, document, lineno, source_to_display, tokens): # Get text before cursor. if cli.is_searching: before = _get_isearch_tokens(cli) @@ -59,11 +59,11 @@ class DefaultPrompt(Processor): # Insert before buffer text. shift_position = token_list_len(before) - # Only show the prompt before the first line. For the following lines, - # only indent using spaces. - if lineno != 0: - before = [(Token.Prompt, ' ' * shift_position)] - + # Only show the prompt before the first line. For the following lines, + # only indent using spaces. + if lineno != 0: + before = [(Token.Prompt, ' ' * shift_position)] + return Transformation( tokens=before + tokens, source_to_display=lambda i: i + shift_position, diff --git a/contrib/python/prompt-toolkit/py2/prompt_toolkit/layout/screen.py b/contrib/python/prompt-toolkit/py2/prompt_toolkit/layout/screen.py index 95561f5de7..3e66f26500 100644 --- a/contrib/python/prompt-toolkit/py2/prompt_toolkit/layout/screen.py +++ b/contrib/python/prompt-toolkit/py2/prompt_toolkit/layout/screen.py @@ -1,9 +1,9 @@ from __future__ import unicode_literals -from prompt_toolkit.cache import FastDictCache -from prompt_toolkit.token import Token +from prompt_toolkit.cache import FastDictCache +from prompt_toolkit.token import Token from prompt_toolkit.utils import get_cwidth - + from collections import defaultdict, namedtuple __all__ = ( @@ -61,7 +61,7 @@ class Char(object): '\x1c': '^\\', '\x1d': '^]', '\x1f': '^_', - '\x7f': '^?', # Backspace + '\x7f': '^?', # Backspace } def __init__(self, char=' ', token=Token): @@ -87,7 +87,7 @@ class Char(object): return '%s(%r, %r)' % (self.__class__.__name__, self.char, self.token) -_CHAR_CACHE = FastDictCache(Char, size=1000 * 1000) +_CHAR_CACHE = FastDictCache(Char, size=1000 * 1000) Transparent = Token.Transparent @@ -97,13 +97,13 @@ class Screen(object): """ def __init__(self, default_char=None, initial_width=0, initial_height=0): if default_char is None: - default_char = _CHAR_CACHE[' ', Transparent] + default_char = _CHAR_CACHE[' ', Transparent] self.data_buffer = defaultdict(lambda: defaultdict(lambda: default_char)) - #: Escape sequences to be injected. - self.zero_width_escapes = defaultdict(lambda: defaultdict(lambda: '')) - + #: Escape sequences to be injected. + self.zero_width_escapes = defaultdict(lambda: defaultdict(lambda: '')) + #: Position of the cursor. self.cursor_position = Point(y=0, x=0) diff --git a/contrib/python/prompt-toolkit/py2/prompt_toolkit/layout/toolbars.py b/contrib/python/prompt-toolkit/py2/prompt_toolkit/layout/toolbars.py index 2e77c2fa16..573e7db666 100644 --- a/contrib/python/prompt-toolkit/py2/prompt_toolkit/layout/toolbars.py +++ b/contrib/python/prompt-toolkit/py2/prompt_toolkit/layout/toolbars.py @@ -4,15 +4,15 @@ from ..enums import IncrementalSearchDirection from .processors import BeforeInput -from .lexers import SimpleLexer +from .lexers import SimpleLexer from .dimension import LayoutDimension -from .controls import BufferControl, TokenListControl, UIControl, UIContent +from .controls import BufferControl, TokenListControl, UIControl, UIContent from .containers import Window, ConditionalContainer -from .screen import Char +from .screen import Char from .utils import token_list_len -from prompt_toolkit.enums import SEARCH_BUFFER, SYSTEM_BUFFER +from prompt_toolkit.enums import SEARCH_BUFFER, SYSTEM_BUFFER from prompt_toolkit.filters import HasFocus, HasArg, HasCompletions, HasValidationError, HasSearch, Always, IsDone -from prompt_toolkit.token import Token +from prompt_toolkit.token import Token __all__ = ( 'TokenListToolbar', @@ -35,13 +35,13 @@ class TokenListToolbar(ConditionalContainer): class SystemToolbarControl(BufferControl): def __init__(self): - token = Token.Toolbar.System - + token = Token.Toolbar.System + super(SystemToolbarControl, self).__init__( buffer_name=SYSTEM_BUFFER, - default_char=Char(token=token), - lexer=SimpleLexer(token=token.Text), - input_processors=[BeforeInput.static('Shell command: ', token)],) + default_char=Char(token=token), + lexer=SimpleLexer(token=token.Text), + input_processors=[BeforeInput.static('Shell command: ', token)],) class SystemToolbar(ConditionalContainer): @@ -56,13 +56,13 @@ class SystemToolbar(ConditionalContainer): class ArgToolbarControl(TokenListControl): def __init__(self): def get_tokens(cli): - arg = cli.input_processor.arg - if arg == '-': - arg = '-1' - + arg = cli.input_processor.arg + if arg == '-': + arg = '-1' + return [ (Token.Toolbar.Arg, 'Repeat: '), - (Token.Toolbar.Arg.Text, arg), + (Token.Toolbar.Arg.Text, arg), ] super(ArgToolbarControl, self).__init__(get_tokens) @@ -97,8 +97,8 @@ class SearchToolbarControl(BufferControl): super(SearchToolbarControl, self).__init__( buffer_name=SEARCH_BUFFER, input_processors=[BeforeInput(get_before_input)], - default_char=Char(token=token), - lexer=SimpleLexer(token=token.Text)) + default_char=Char(token=token), + lexer=SimpleLexer(token=token.Text)) class SearchToolbar(ConditionalContainer): @@ -113,7 +113,7 @@ class SearchToolbar(ConditionalContainer): class CompletionsToolbarControl(UIControl): token = Token.Toolbar.Completions - def create_content(self, cli, width, height): + def create_content(self, cli, width, height): complete_state = cli.current_buffer.complete_state if complete_state: completions = complete_state.current_completions @@ -161,12 +161,12 @@ class CompletionsToolbarControl(UIControl): else: all_tokens = [] - def get_line(i): - return all_tokens - - return UIContent(get_line=get_line, line_count=1) + def get_line(i): + return all_tokens + return UIContent(get_line=get_line, line_count=1) + class CompletionsToolbar(ConditionalContainer): def __init__(self, extra_filter=Always()): super(CompletionsToolbar, self).__init__( diff --git a/contrib/python/prompt-toolkit/py2/prompt_toolkit/layout/utils.py b/contrib/python/prompt-toolkit/py2/prompt_toolkit/layout/utils.py index a4fb7ed0f5..3fa16de535 100644 --- a/contrib/python/prompt-toolkit/py2/prompt_toolkit/layout/utils.py +++ b/contrib/python/prompt-toolkit/py2/prompt_toolkit/layout/utils.py @@ -1,14 +1,14 @@ from __future__ import unicode_literals from prompt_toolkit.utils import get_cwidth -from prompt_toolkit.token import Token +from prompt_toolkit.token import Token __all__ = ( 'token_list_len', 'token_list_width', 'token_list_to_text', 'explode_tokens', - 'split_lines', + 'split_lines', 'find_window_for_buffer_name', ) @@ -20,8 +20,8 @@ def token_list_len(tokenlist): :param tokenlist: List of (token, text) or (token, text, mouse_handler) tuples. """ - ZeroWidthEscape = Token.ZeroWidthEscape - return sum(len(item[1]) for item in tokenlist if item[0] != ZeroWidthEscape) + ZeroWidthEscape = Token.ZeroWidthEscape + return sum(len(item[1]) for item in tokenlist if item[0] != ZeroWidthEscape) def token_list_width(tokenlist): @@ -32,16 +32,16 @@ def token_list_width(tokenlist): :param tokenlist: List of (token, text) or (token, text, mouse_handler) tuples. """ - ZeroWidthEscape = Token.ZeroWidthEscape - return sum(get_cwidth(c) for item in tokenlist for c in item[1] if item[0] != ZeroWidthEscape) + ZeroWidthEscape = Token.ZeroWidthEscape + return sum(get_cwidth(c) for item in tokenlist for c in item[1] if item[0] != ZeroWidthEscape) def token_list_to_text(tokenlist): """ Concatenate all the text parts again. """ - ZeroWidthEscape = Token.ZeroWidthEscape - return ''.join(item[1] for item in tokenlist if item[0] != ZeroWidthEscape) + ZeroWidthEscape = Token.ZeroWidthEscape + return ''.join(item[1] for item in tokenlist if item[0] != ZeroWidthEscape) def iter_token_lines(tokenlist): @@ -62,7 +62,7 @@ def iter_token_lines(tokenlist): def split_lines(tokenlist): """ Take a single list of (Token, text) tuples and yield one such list for each - line. Just like str.split, this will yield at least one item. + line. Just like str.split, this will yield at least one item. :param tokenlist: List of (token, text) or (token, text, mouse_handler) tuples. @@ -82,8 +82,8 @@ def split_lines(tokenlist): line = [] line.append((token, parts[-1])) - # Note that parts[-1] can be empty, and that's fine. It happens - # in the case of [(Token.SetCursorPosition, '')]. + # Note that parts[-1] can be empty, and that's fine. It happens + # in the case of [(Token.SetCursorPosition, '')]. # For (token, text, mouse_handler) tuples. # I know, partly copy/paste, but understandable and more efficient @@ -100,67 +100,67 @@ def split_lines(tokenlist): line.append((token, parts[-1], mouse_handler)) - # Always yield the last line, even when this is an empty line. This ensures - # that when `tokenlist` ends with a newline character, an additional empty - # line is yielded. (Otherwise, there's no way to differentiate between the - # cases where `tokenlist` does and doesn't end with a newline.) - yield line - - -class _ExplodedList(list): - """ - Wrapper around a list, that marks it as 'exploded'. - - As soon as items are added or the list is extended, the new items are - automatically exploded as well. - """ - def __init__(self, *a, **kw): - super(_ExplodedList, self).__init__(*a, **kw) - self.exploded = True - - def append(self, item): - self.extend([item]) - - def extend(self, lst): - super(_ExplodedList, self).extend(explode_tokens(lst)) - - def insert(self, index, item): - raise NotImplementedError # TODO - - # TODO: When creating a copy() or [:], return also an _ExplodedList. - - def __setitem__(self, index, value): - """ - Ensure that when `(Token, 'long string')` is set, the string will be - exploded. - """ - if not isinstance(index, slice): - index = slice(index, index + 1) - value = explode_tokens([value]) - super(_ExplodedList, self).__setitem__(index, value) - - + # Always yield the last line, even when this is an empty line. This ensures + # that when `tokenlist` ends with a newline character, an additional empty + # line is yielded. (Otherwise, there's no way to differentiate between the + # cases where `tokenlist` does and doesn't end with a newline.) + yield line + + +class _ExplodedList(list): + """ + Wrapper around a list, that marks it as 'exploded'. + + As soon as items are added or the list is extended, the new items are + automatically exploded as well. + """ + def __init__(self, *a, **kw): + super(_ExplodedList, self).__init__(*a, **kw) + self.exploded = True + + def append(self, item): + self.extend([item]) + + def extend(self, lst): + super(_ExplodedList, self).extend(explode_tokens(lst)) + + def insert(self, index, item): + raise NotImplementedError # TODO + + # TODO: When creating a copy() or [:], return also an _ExplodedList. + + def __setitem__(self, index, value): + """ + Ensure that when `(Token, 'long string')` is set, the string will be + exploded. + """ + if not isinstance(index, slice): + index = slice(index, index + 1) + value = explode_tokens([value]) + super(_ExplodedList, self).__setitem__(index, value) + + def explode_tokens(tokenlist): """ Turn a list of (token, text) tuples into another list where each string is exactly one character. - It should be fine to call this function several times. Calling this on a - list that is already exploded, is a null operation. - + It should be fine to call this function several times. Calling this on a + list that is already exploded, is a null operation. + :param tokenlist: List of (token, text) tuples. """ - # When the tokenlist is already exploded, don't explode again. - if getattr(tokenlist, 'exploded', False): - return tokenlist - + # When the tokenlist is already exploded, don't explode again. + if getattr(tokenlist, 'exploded', False): + return tokenlist + result = [] for token, string in tokenlist: for c in string: result.append((token, c)) - return _ExplodedList(result) + return _ExplodedList(result) def find_window_for_buffer_name(cli, buffer_name): diff --git a/contrib/python/prompt-toolkit/py2/prompt_toolkit/mouse_events.py b/contrib/python/prompt-toolkit/py2/prompt_toolkit/mouse_events.py index f42276ce9f..4537ba8035 100644 --- a/contrib/python/prompt-toolkit/py2/prompt_toolkit/mouse_events.py +++ b/contrib/python/prompt-toolkit/py2/prompt_toolkit/mouse_events.py @@ -18,21 +18,21 @@ coordinates to coordinates relative to the user control, and there from __future__ import unicode_literals __all__ = ( - 'MouseEventType', + 'MouseEventType', 'MouseEvent' ) -class MouseEventType: +class MouseEventType: MOUSE_UP = 'MOUSE_UP' MOUSE_DOWN = 'MOUSE_DOWN' SCROLL_UP = 'SCROLL_UP' SCROLL_DOWN = 'SCROLL_DOWN' -MouseEventTypes = MouseEventType # Deprecated: plural for backwards compatibility. - - +MouseEventTypes = MouseEventType # Deprecated: plural for backwards compatibility. + + class MouseEvent(object): """ Mouse event, sent to `UIControl.mouse_handler`. diff --git a/contrib/python/prompt-toolkit/py2/prompt_toolkit/output.py b/contrib/python/prompt-toolkit/py2/prompt_toolkit/output.py index 072fb0677f..b863abc908 100644 --- a/contrib/python/prompt-toolkit/py2/prompt_toolkit/output.py +++ b/contrib/python/prompt-toolkit/py2/prompt_toolkit/output.py @@ -4,7 +4,7 @@ Interface for an output. from __future__ import unicode_literals from abc import ABCMeta, abstractmethod from six import with_metaclass -from prompt_toolkit.layout.screen import Size +from prompt_toolkit.layout.screen import Size __all__ = ( 'Output', @@ -21,19 +21,19 @@ class Output(with_metaclass(ABCMeta, object)): :class:`~prompt_toolkit.terminal.win32_output.Win32Output`. """ @abstractmethod - def fileno(self): - " Return the file descriptor to which we can write for the output. " - - @abstractmethod - def encoding(self): - """ - Return the encoding for this output, e.g. 'utf-8'. - (This is used mainly to know which characters are supported by the - output the data, so that the UI can provide alternatives, when - required.) - """ - - @abstractmethod + def fileno(self): + " Return the file descriptor to which we can write for the output. " + + @abstractmethod + def encoding(self): + """ + Return the encoding for this output, e.g. 'utf-8'. + (This is used mainly to know which characters are supported by the + output the data, so that the UI can provide alternatives, when + required.) + """ + + @abstractmethod def write(self, data): " Write text (Terminal escape sequences will be removed/escaped.) " @@ -147,46 +147,46 @@ class Output(with_metaclass(ABCMeta, object)): def disable_bracketed_paste(self): " For vt100 only. " - - -class DummyOutput(Output): - """ - For testing. An output class that doesn't render anything. - """ - def fileno(self): - " There is no sensible default for fileno(). " - raise NotImplementedError - - def encoding(self): - return 'utf-8' - - def write(self, data): pass - def write_raw(self, data): pass - def set_title(self, title): pass - def clear_title(self): pass - def flush(self): pass - def erase_screen(self): pass - def enter_alternate_screen(self): pass - def quit_alternate_screen(self): pass - def enable_mouse_support(self): pass - def disable_mouse_support(self): pass - def erase_end_of_line(self): pass - def erase_down(self): pass - def reset_attributes(self): pass - def set_attributes(self, attrs): pass - def disable_autowrap(self): pass - def enable_autowrap(self): pass - def cursor_goto(self, row=0, column=0): pass - def cursor_up(self, amount): pass - def cursor_down(self, amount): pass - def cursor_forward(self, amount): pass - def cursor_backward(self, amount): pass - def hide_cursor(self): pass - def show_cursor(self): pass - def ask_for_cpr(self): pass - def bell(self): pass - def enable_bracketed_paste(self): pass - def disable_bracketed_paste(self): pass - - def get_size(self): - return Size(rows=40, columns=80) + + +class DummyOutput(Output): + """ + For testing. An output class that doesn't render anything. + """ + def fileno(self): + " There is no sensible default for fileno(). " + raise NotImplementedError + + def encoding(self): + return 'utf-8' + + def write(self, data): pass + def write_raw(self, data): pass + def set_title(self, title): pass + def clear_title(self): pass + def flush(self): pass + def erase_screen(self): pass + def enter_alternate_screen(self): pass + def quit_alternate_screen(self): pass + def enable_mouse_support(self): pass + def disable_mouse_support(self): pass + def erase_end_of_line(self): pass + def erase_down(self): pass + def reset_attributes(self): pass + def set_attributes(self, attrs): pass + def disable_autowrap(self): pass + def enable_autowrap(self): pass + def cursor_goto(self, row=0, column=0): pass + def cursor_up(self, amount): pass + def cursor_down(self, amount): pass + def cursor_forward(self, amount): pass + def cursor_backward(self, amount): pass + def hide_cursor(self): pass + def show_cursor(self): pass + def ask_for_cpr(self): pass + def bell(self): pass + def enable_bracketed_paste(self): pass + def disable_bracketed_paste(self): pass + + def get_size(self): + return Size(rows=40, columns=80) diff --git a/contrib/python/prompt-toolkit/py2/prompt_toolkit/renderer.py b/contrib/python/prompt-toolkit/py2/prompt_toolkit/renderer.py index 7a8fde55b3..c0fee22e10 100644 --- a/contrib/python/prompt-toolkit/py2/prompt_toolkit/renderer.py +++ b/contrib/python/prompt-toolkit/py2/prompt_toolkit/renderer.py @@ -4,23 +4,23 @@ Renders the command line on the console. """ from __future__ import unicode_literals -from prompt_toolkit.filters import to_cli_filter -from prompt_toolkit.layout.mouse_handlers import MouseHandlers +from prompt_toolkit.filters import to_cli_filter +from prompt_toolkit.layout.mouse_handlers import MouseHandlers from prompt_toolkit.layout.screen import Point, Screen, WritePosition from prompt_toolkit.output import Output -from prompt_toolkit.styles import Style -from prompt_toolkit.token import Token +from prompt_toolkit.styles import Style +from prompt_toolkit.token import Token from prompt_toolkit.utils import is_windows -from six.moves import range - +from six.moves import range + __all__ = ( 'Renderer', 'print_tokens', ) -def _output_screen_diff(output, screen, current_pos, previous_screen=None, last_token=None, +def _output_screen_diff(output, screen, current_pos, previous_screen=None, last_token=None, is_done=False, use_alternate_screen=False, attrs_for_token=None, size=None, previous_width=0): # XXX: drop is_done """ @@ -36,7 +36,7 @@ def _output_screen_diff(output, screen, current_pos, previous_screen=None, last_ Don't change things without profiling first. :param current_pos: Current cursor position. - :param last_token: `Token` instance that represents the output attributes of + :param last_token: `Token` instance that represents the output attributes of the last drawn character. (Color/attributes.) :param attrs_for_token: :class:`._TokenToAttrsCache` instance. :param width: The width of the terminal. @@ -45,11 +45,11 @@ def _output_screen_diff(output, screen, current_pos, previous_screen=None, last_ width, height = size.columns, size.rows #: Remember the last printed character. - last_token = [last_token] # nonlocal + last_token = [last_token] # nonlocal #: Variable for capturing the output. write = output.write - write_raw = output.write_raw + write_raw = output.write_raw # Create locals for the most used output methods. # (Save expensive attribute lookups.) @@ -65,7 +65,7 @@ def _output_screen_diff(output, screen, current_pos, previous_screen=None, last_ def reset_attributes(): " Wrapper around Output.reset_attributes. " _output_reset_attributes() - last_token[0] = None # Forget last char after resetting attributes. + last_token[0] = None # Forget last char after resetting attributes. def move_cursor(new): " Move cursor to this `new` point. Returns the given Point. " @@ -100,14 +100,14 @@ def _output_screen_diff(output, screen, current_pos, previous_screen=None, last_ """ # If the last printed character has the same token, it also has the # same style, so we don't output it. - the_last_token = last_token[0] - - if the_last_token and the_last_token == char.token: + the_last_token = last_token[0] + + if the_last_token and the_last_token == char.token: write(char.char) else: - _output_set_attributes(attrs_for_token[char.token]) + _output_set_attributes(attrs_for_token[char.token]) write(char.char) - last_token[0] = char.token + last_token[0] = char.token # Render for the first time: reset styling. if not previous_screen: @@ -138,10 +138,10 @@ def _output_screen_diff(output, screen, current_pos, previous_screen=None, last_ row_count = min(max(screen.height, previous_screen.height), height) c = 0 # Column counter. - for y in range(row_count): - new_row = screen.data_buffer[y] - previous_row = previous_screen.data_buffer[y] - zero_width_escapes_row = screen.zero_width_escapes[y] + for y in range(row_count): + new_row = screen.data_buffer[y] + previous_row = previous_screen.data_buffer[y] + zero_width_escapes_row = screen.zero_width_escapes[y] new_max_line_len = min(width - 1, max(new_row.keys()) if new_row else 0) previous_max_line_len = min(width - 1, max(previous_row.keys()) if previous_row else 0) @@ -158,11 +158,11 @@ def _output_screen_diff(output, screen, current_pos, previous_screen=None, last_ # `Char.__ne__`, but inline the same expression.) if new_char.char != old_char.char or new_char.token != old_char.token: current_pos = move_cursor(Point(y=y, x=c)) - - # Send injected escape sequences to output. - if c in zero_width_escapes_row: - write_raw(zero_width_escapes_row[c]) - + + # Send injected escape sequences to output. + if c in zero_width_escapes_row: + write_raw(zero_width_escapes_row[c]) + output_char(new_char) current_pos = current_pos._replace(x=current_pos.x + char_width) @@ -197,16 +197,16 @@ def _output_screen_diff(output, screen, current_pos, previous_screen=None, last_ if is_done or not use_alternate_screen: output.enable_autowrap() - # Always reset the color attributes. This is important because a background - # thread could print data to stdout and we want that to be displayed in the - # default colors. (Also, if a background color has been set, many terminals - # give weird artifacs on resize events.) - reset_attributes() + # Always reset the color attributes. This is important because a background + # thread could print data to stdout and we want that to be displayed in the + # default colors. (Also, if a background color has been set, many terminals + # give weird artifacs on resize events.) + reset_attributes() if screen.show_cursor or is_done: output.show_cursor() - return current_pos, last_token[0] + return current_pos, last_token[0] class HeightIsUnknownError(Exception): @@ -254,13 +254,13 @@ class Renderer(object): self._mouse_support_enabled = False self._bracketed_paste_enabled = False - # Waiting for CPR flag. True when we send the request, but didn't got a - # response. - self.waiting_for_cpr = False - + # Waiting for CPR flag. True when we send the request, but didn't got a + # response. + self.waiting_for_cpr = False + self.reset(_scroll=True) - def reset(self, _scroll=False, leave_alternate_screen=True): + def reset(self, _scroll=False, leave_alternate_screen=True): # Reset position self._cursor_pos = Point(x=0, y=0) @@ -270,7 +270,7 @@ class Renderer(object): # instance a toolbar at the bottom position.) self._last_screen = None self._last_size = None - self._last_token = None + self._last_token = None # When the style hash changes, we have to do a full redraw as well as # clear the `_attrs_for_token` dictionary. @@ -293,7 +293,7 @@ class Renderer(object): self.output.scroll_buffer_to_prompt() # Quit alternate screen. - if self._in_alternate_screen and leave_alternate_screen: + if self._in_alternate_screen and leave_alternate_screen: self.output.quit_alternate_screen() self._in_alternate_screen = False @@ -353,7 +353,7 @@ class Renderer(object): self._min_available_height = self.output.get_size().rows else: # Asks for a cursor position report (CPR). - self.waiting_for_cpr = True + self.waiting_for_cpr = True self.output.ask_for_cpr() def report_absolute_cursor_row(self, row): @@ -369,8 +369,8 @@ class Renderer(object): # Set the self._min_available_height = rows_below_cursor - self.waiting_for_cpr = False - + self.waiting_for_cpr = False + def render(self, cli, layout, is_done=False): """ Render the current interface to the output. @@ -441,9 +441,9 @@ class Renderer(object): screen.replace_all_tokens(Token.Aborted) # Process diff and write to output. - self._cursor_pos, self._last_token = _output_screen_diff( + self._cursor_pos, self._last_token = _output_screen_diff( output, screen, self._cursor_pos, - self._last_screen, self._last_token, is_done, + self._last_screen, self._last_token, is_done, use_alternate_screen=self.use_alternate_screen, attrs_for_token=self._attrs_for_token, size=size, @@ -464,15 +464,15 @@ class Renderer(object): output.flush() - def erase(self, leave_alternate_screen=True, erase_title=True): + def erase(self, leave_alternate_screen=True, erase_title=True): """ Hide all output and put the cursor back at the first line. This is for instance used for running a system command (while hiding the CLI) and later resuming the same CLI.) - - :param leave_alternate_screen: When True, and when inside an alternate - screen buffer, quit the alternate screen. - :param erase_title: When True, clear the title from the title bar. + + :param leave_alternate_screen: When True, and when inside an alternate + screen buffer, quit the alternate screen. + :param erase_title: When True, clear the title from the title bar. """ output = self.output @@ -484,10 +484,10 @@ class Renderer(object): output.flush() # Erase title. - if self._last_title and erase_title: + if self._last_title and erase_title: output.clear_title() - self.reset(leave_alternate_screen=leave_alternate_screen) + self.reset(leave_alternate_screen=leave_alternate_screen) def clear(self): """ diff --git a/contrib/python/prompt-toolkit/py2/prompt_toolkit/selection.py b/contrib/python/prompt-toolkit/py2/prompt_toolkit/selection.py index 6582921222..4490f15c0d 100644 --- a/contrib/python/prompt-toolkit/py2/prompt_toolkit/selection.py +++ b/contrib/python/prompt-toolkit/py2/prompt_toolkit/selection.py @@ -15,13 +15,13 @@ class SelectionType(object): Type of selection. """ #: Characters. (Visual in Vi.) - CHARACTERS = 'CHARACTERS' + CHARACTERS = 'CHARACTERS' #: Whole lines. (Visual-Line in Vi.) - LINES = 'LINES' + LINES = 'LINES' #: A block selection. (Visual-Block in Vi.) - BLOCK = 'BLOCK' + BLOCK = 'BLOCK' class PasteMode(object): diff --git a/contrib/python/prompt-toolkit/py2/prompt_toolkit/shortcuts.py b/contrib/python/prompt-toolkit/py2/prompt_toolkit/shortcuts.py index 9893624c6e..2bb34177de 100644 --- a/contrib/python/prompt-toolkit/py2/prompt_toolkit/shortcuts.py +++ b/contrib/python/prompt-toolkit/py2/prompt_toolkit/shortcuts.py @@ -23,45 +23,45 @@ from __future__ import unicode_literals from .buffer import Buffer, AcceptAction from .document import Document -from .enums import DEFAULT_BUFFER, SEARCH_BUFFER, EditingMode +from .enums import DEFAULT_BUFFER, SEARCH_BUFFER, EditingMode from .filters import IsDone, HasFocus, RendererHeightIsKnown, to_simple_filter, to_cli_filter, Condition from .history import InMemoryHistory from .interface import CommandLineInterface, Application, AbortAction from .key_binding.defaults import load_key_bindings_for_prompt -from .key_binding.registry import Registry -from .keys import Keys -from .layout import Window, HSplit, FloatContainer, Float +from .key_binding.registry import Registry +from .keys import Keys +from .layout import Window, HSplit, FloatContainer, Float from .layout.containers import ConditionalContainer from .layout.controls import BufferControl, TokenListControl from .layout.dimension import LayoutDimension from .layout.lexers import PygmentsLexer -from .layout.margins import PromptMargin, ConditionalMargin +from .layout.margins import PromptMargin, ConditionalMargin from .layout.menus import CompletionsMenu, MultiColumnCompletionsMenu -from .layout.processors import PasswordProcessor, ConditionalProcessor, AppendAutoSuggestion, HighlightSearchProcessor, HighlightSelectionProcessor, DisplayMultipleCursors +from .layout.processors import PasswordProcessor, ConditionalProcessor, AppendAutoSuggestion, HighlightSearchProcessor, HighlightSelectionProcessor, DisplayMultipleCursors from .layout.prompt import DefaultPrompt from .layout.screen import Char from .layout.toolbars import ValidationToolbar, SystemToolbar, ArgToolbar, SearchToolbar from .layout.utils import explode_tokens -from .renderer import print_tokens as renderer_print_tokens -from .styles import DEFAULT_STYLE, Style, style_from_dict -from .token import Token +from .renderer import print_tokens as renderer_print_tokens +from .styles import DEFAULT_STYLE, Style, style_from_dict +from .token import Token from .utils import is_conemu_ansi, is_windows, DummyContext -from six import text_type, exec_, PY2 +from six import text_type, exec_, PY2 -import os +import os import sys import textwrap -import threading -import time - -try: - from pygments.lexer import Lexer as pygments_Lexer - from pygments.style import Style as pygments_Style -except ImportError: - pygments_Lexer = None - pygments_Style = None - +import threading +import time + +try: + from pygments.lexer import Lexer as pygments_Lexer + from pygments.style import Style as pygments_Style +except ImportError: + pygments_Lexer = None + pygments_Style = None + if is_windows(): from .terminal.win32_output import Win32Output from .terminal.conemu_output import ConEmuOutput @@ -76,15 +76,15 @@ __all__ = ( 'create_prompt_application', 'prompt', 'prompt_async', - 'create_confirm_application', + 'create_confirm_application', 'run_application', - 'confirm', - 'print_tokens', + 'confirm', + 'print_tokens', 'clear', ) -def create_eventloop(inputhook=None, recognize_win32_paste=True): +def create_eventloop(inputhook=None, recognize_win32_paste=True): """ Create and return an :class:`~prompt_toolkit.eventloop.base.EventLoop` instance for a @@ -92,21 +92,21 @@ def create_eventloop(inputhook=None, recognize_win32_paste=True): """ if is_windows(): from prompt_toolkit.eventloop.win32 import Win32EventLoop as Loop - return Loop(inputhook=inputhook, recognize_paste=recognize_win32_paste) + return Loop(inputhook=inputhook, recognize_paste=recognize_win32_paste) else: from prompt_toolkit.eventloop.posix import PosixEventLoop as Loop - return Loop(inputhook=inputhook) + return Loop(inputhook=inputhook) -def create_output(stdout=None, true_color=False, ansi_colors_only=None): +def create_output(stdout=None, true_color=False, ansi_colors_only=None): """ Return an :class:`~prompt_toolkit.output.Output` instance for the command line. :param true_color: When True, use 24bit colors instead of 256 colors. (`bool` or :class:`~prompt_toolkit.filters.SimpleFilter`.) - :param ansi_colors_only: When True, restrict to 16 ANSI colors only. - (`bool` or :class:`~prompt_toolkit.filters.SimpleFilter`.) + :param ansi_colors_only: When True, restrict to 16 ANSI colors only. + (`bool` or :class:`~prompt_toolkit.filters.SimpleFilter`.) """ stdout = stdout or sys.__stdout__ true_color = to_simple_filter(true_color) @@ -117,15 +117,15 @@ def create_output(stdout=None, true_color=False, ansi_colors_only=None): else: return Win32Output(stdout) else: - term = os.environ.get('TERM', '') - if PY2: - term = term.decode('utf-8') - - return Vt100_Output.from_pty( - stdout, true_color=true_color, - ansi_colors_only=ansi_colors_only, term=term) + term = os.environ.get('TERM', '') + if PY2: + term = term.decode('utf-8') + return Vt100_Output.from_pty( + stdout, true_color=true_color, + ansi_colors_only=ansi_colors_only, term=term) + def create_asyncio_eventloop(loop=None): """ Returns an asyncio :class:`~prompt_toolkit.eventloop.EventLoop` instance @@ -147,24 +147,24 @@ def create_asyncio_eventloop(loop=None): def _split_multiline_prompt(get_prompt_tokens): """ - Take a `get_prompt_tokens` function and return three new functions instead. - One that tells whether this prompt consists of multiple lines; one that - returns the tokens to be shown on the lines above the input; and another - one with the tokens to be shown at the first line of the input. + Take a `get_prompt_tokens` function and return three new functions instead. + One that tells whether this prompt consists of multiple lines; one that + returns the tokens to be shown on the lines above the input; and another + one with the tokens to be shown at the first line of the input. """ - def has_before_tokens(cli): - for token, char in get_prompt_tokens(cli): - if '\n' in char: - return True - return False - + def has_before_tokens(cli): + for token, char in get_prompt_tokens(cli): + if '\n' in char: + return True + return False + def before(cli): result = [] found_nl = False for token, char in reversed(explode_tokens(get_prompt_tokens(cli))): - if found_nl: - result.insert(0, (token, char)) - elif char == '\n': + if found_nl: + result.insert(0, (token, char)) + elif char == '\n': found_nl = True return result @@ -177,23 +177,23 @@ def _split_multiline_prompt(get_prompt_tokens): result.insert(0, (token, char)) return result - return has_before_tokens, before, first_input_line - - -class _RPrompt(Window): - " The prompt that is displayed on the right side of the Window. " - def __init__(self, get_tokens=None): - get_tokens = get_tokens or (lambda cli: []) - - super(_RPrompt, self).__init__( - TokenListControl(get_tokens, align_right=True)) + return has_before_tokens, before, first_input_line +class _RPrompt(Window): + " The prompt that is displayed on the right side of the Window. " + def __init__(self, get_tokens=None): + get_tokens = get_tokens or (lambda cli: []) + + super(_RPrompt, self).__init__( + TokenListControl(get_tokens, align_right=True)) + + def create_prompt_layout(message='', lexer=None, is_password=False, reserve_space_for_menu=8, - get_prompt_tokens=None, get_continuation_tokens=None, - get_rprompt_tokens=None, - get_bottom_toolbar_tokens=None, + get_prompt_tokens=None, get_continuation_tokens=None, + get_rprompt_tokens=None, + get_bottom_toolbar_tokens=None, display_completions_in_columns=False, extra_input_processors=None, multiline=False, wrap_lines=True): @@ -210,9 +210,9 @@ def create_prompt_layout(message='', lexer=None, is_password=False, to display the completion menu. :param get_prompt_tokens: An optional callable that returns the tokens to be shown in the menu. (To be used instead of a `message`.) - :param get_continuation_tokens: An optional callable that takes a - CommandLineInterface and width as input and returns a list of (Token, - text) tuples to be used for the continuation. + :param get_continuation_tokens: An optional callable that takes a + CommandLineInterface and width as input and returns a list of (Token, + text) tuples to be used for the continuation. :param get_bottom_toolbar_tokens: An optional callable that returns the tokens for a toolbar at the bottom. :param display_completions_in_columns: `bool` or @@ -226,10 +226,10 @@ def create_prompt_layout(message='', lexer=None, is_password=False, When True (the default), automatically wrap long lines instead of scrolling horizontally. """ - assert isinstance(message, text_type), 'Please provide a unicode string.' + assert isinstance(message, text_type), 'Please provide a unicode string.' assert get_bottom_toolbar_tokens is None or callable(get_bottom_toolbar_tokens) assert get_prompt_tokens is None or callable(get_prompt_tokens) - assert get_rprompt_tokens is None or callable(get_rprompt_tokens) + assert get_rprompt_tokens is None or callable(get_rprompt_tokens) assert not (message and get_prompt_tokens) display_completions_in_columns = to_cli_filter(display_completions_in_columns) @@ -238,33 +238,33 @@ def create_prompt_layout(message='', lexer=None, is_password=False, if get_prompt_tokens is None: get_prompt_tokens = lambda _: [(Token.Prompt, message)] - has_before_tokens, get_prompt_tokens_1, get_prompt_tokens_2 = \ - _split_multiline_prompt(get_prompt_tokens) + has_before_tokens, get_prompt_tokens_1, get_prompt_tokens_2 = \ + _split_multiline_prompt(get_prompt_tokens) # `lexer` is supposed to be a `Lexer` instance. But if a Pygments lexer # class is given, turn it into a PygmentsLexer. (Important for # backwards-compatibility.) try: - if pygments_Lexer and issubclass(lexer, pygments_Lexer): - lexer = PygmentsLexer(lexer, sync_from_start=True) + if pygments_Lexer and issubclass(lexer, pygments_Lexer): + lexer = PygmentsLexer(lexer, sync_from_start=True) except TypeError: # Happens when lexer is `None` or an instance of something else. pass - # Create processors list. - input_processors = [ - ConditionalProcessor( + # Create processors list. + input_processors = [ + ConditionalProcessor( # By default, only highlight search when the search # input has the focus. (Note that this doesn't mean # there is no search: the Vi 'n' binding for instance # still allows to jump to the next match in # navigation mode.) - HighlightSearchProcessor(preview_search=True), - HasFocus(SEARCH_BUFFER)), - HighlightSelectionProcessor(), + HighlightSearchProcessor(preview_search=True), + HasFocus(SEARCH_BUFFER)), + HighlightSelectionProcessor(), ConditionalProcessor(AppendAutoSuggestion(), HasFocus(DEFAULT_BUFFER) & ~IsDone()), - ConditionalProcessor(PasswordProcessor(), is_password), - DisplayMultipleCursors(DEFAULT_BUFFER), - ] + ConditionalProcessor(PasswordProcessor(), is_password), + DisplayMultipleCursors(DEFAULT_BUFFER), + ] if extra_input_processors: input_processors.extend(extra_input_processors) @@ -274,7 +274,7 @@ def create_prompt_layout(message='', lexer=None, is_password=False, # (Only for single line mode.) # (DefaultPrompt should always be at the end of the processors.) input_processors.append(ConditionalProcessor( - DefaultPrompt(get_prompt_tokens_2), ~multiline)) + DefaultPrompt(get_prompt_tokens_2), ~multiline)) # Create bottom toolbar. if get_bottom_toolbar_tokens: @@ -290,26 +290,26 @@ def create_prompt_layout(message='', lexer=None, is_password=False, # If there is an autocompletion menu to be shown, make sure that our # layout has at least a minimal height in order to display it. if reserve_space_for_menu and not cli.is_done: - buff = cli.current_buffer - - # Reserve the space, either when there are completions, or when - # `complete_while_typing` is true and we expect completions very - # soon. - if buff.complete_while_typing() or buff.complete_state is not None: - return LayoutDimension(min=reserve_space_for_menu) - - return LayoutDimension() - + buff = cli.current_buffer + + # Reserve the space, either when there are completions, or when + # `complete_while_typing` is true and we expect completions very + # soon. + if buff.complete_while_typing() or buff.complete_state is not None: + return LayoutDimension(min=reserve_space_for_menu) + + return LayoutDimension() + # Create and return Container instance. return HSplit([ - # The main input, with completion menus floating on top of it. - FloatContainer( - HSplit([ - ConditionalContainer( - Window( - TokenListControl(get_prompt_tokens_1), - dont_extend_height=True), - Condition(has_before_tokens) + # The main input, with completion menus floating on top of it. + FloatContainer( + HSplit([ + ConditionalContainer( + Window( + TokenListControl(get_prompt_tokens_1), + dont_extend_height=True), + Condition(has_before_tokens) ), Window( BufferControl( @@ -319,38 +319,38 @@ def create_prompt_layout(message='', lexer=None, is_password=False, # in reverse-i-search mode. preview_search=True), get_height=get_height, - left_margins=[ - # In multiline mode, use the window margin to display - # the prompt and continuation tokens. - ConditionalMargin( - PromptMargin(get_prompt_tokens_2, get_continuation_tokens), - filter=multiline - ) - ], - wrap_lines=wrap_lines, + left_margins=[ + # In multiline mode, use the window margin to display + # the prompt and continuation tokens. + ConditionalMargin( + PromptMargin(get_prompt_tokens_2, get_continuation_tokens), + filter=multiline + ) + ], + wrap_lines=wrap_lines, ), - ]), - [ - # Completion menus. - Float(xcursor=True, - ycursor=True, - content=CompletionsMenu( - max_height=16, - scroll_offset=1, - extra_filter=HasFocus(DEFAULT_BUFFER) & - ~display_completions_in_columns)), - Float(xcursor=True, - ycursor=True, - content=MultiColumnCompletionsMenu( - extra_filter=HasFocus(DEFAULT_BUFFER) & - display_completions_in_columns, - show_meta=True)), - - # The right prompt. - Float(right=0, top=0, hide_when_covering_content=True, - content=_RPrompt(get_rprompt_tokens)), - ] - ), + ]), + [ + # Completion menus. + Float(xcursor=True, + ycursor=True, + content=CompletionsMenu( + max_height=16, + scroll_offset=1, + extra_filter=HasFocus(DEFAULT_BUFFER) & + ~display_completions_in_columns)), + Float(xcursor=True, + ycursor=True, + content=MultiColumnCompletionsMenu( + extra_filter=HasFocus(DEFAULT_BUFFER) & + display_completions_in_columns, + show_meta=True)), + + # The right prompt. + Float(right=0, top=0, hide_when_covering_content=True, + content=_RPrompt(get_rprompt_tokens)), + ] + ), ValidationToolbar(), SystemToolbar(), @@ -366,7 +366,7 @@ def create_prompt_application( wrap_lines=True, is_password=False, vi_mode=False, - editing_mode=EditingMode.EMACS, + editing_mode=EditingMode.EMACS, complete_while_typing=True, enable_history_search=False, lexer=None, @@ -380,8 +380,8 @@ def create_prompt_application( history=None, clipboard=None, get_prompt_tokens=None, - get_continuation_tokens=None, - get_rprompt_tokens=None, + get_continuation_tokens=None, + get_rprompt_tokens=None, get_bottom_toolbar_tokens=None, display_completions_in_columns=False, get_title=None, @@ -391,7 +391,7 @@ def create_prompt_application( on_abort=AbortAction.RAISE_EXCEPTION, on_exit=AbortAction.RAISE_EXCEPTION, accept_action=AcceptAction.RETURN_DOCUMENT, - erase_when_done=False, + erase_when_done=False, default=''): """ Create an :class:`~Application` instance for a prompt. @@ -407,13 +407,13 @@ def create_prompt_application( When True (the default), automatically wrap long lines instead of scrolling horizontally. :param is_password: Show asterisks instead of the actual typed characters. - :param editing_mode: ``EditingMode.VI`` or ``EditingMode.EMACS``. - :param vi_mode: `bool`, if True, Identical to ``editing_mode=EditingMode.VI``. + :param editing_mode: ``EditingMode.VI`` or ``EditingMode.EMACS``. + :param vi_mode: `bool`, if True, Identical to ``editing_mode=EditingMode.VI``. :param complete_while_typing: `bool` or - :class:`~prompt_toolkit.filters.SimpleFilter`. Enable autocompletion - while typing. + :class:`~prompt_toolkit.filters.SimpleFilter`. Enable autocompletion + while typing. :param enable_history_search: `bool` or - :class:`~prompt_toolkit.filters.SimpleFilter`. Enable up-arrow parting + :class:`~prompt_toolkit.filters.SimpleFilter`. Enable up-arrow parting string matching. :param lexer: :class:`~prompt_toolkit.layout.lexers.Lexer` to be used for the syntax highlighting. @@ -425,7 +425,7 @@ def create_prompt_application( (0 means that no space needs to be reserved.) :param auto_suggest: :class:`~prompt_toolkit.auto_suggest.AutoSuggest` instance for input suggestions. - :param style: :class:`.Style` instance for the color scheme. + :param style: :class:`.Style` instance for the color scheme. :param enable_system_bindings: `bool` or :class:`~prompt_toolkit.filters.CLIFilter`. Pressing Meta+'!' will show a system prompt. @@ -453,10 +453,10 @@ def create_prompt_application( enable_system_bindings=enable_system_bindings, enable_open_in_editor=enable_open_in_editor) - # Ensure backwards-compatibility, when `vi_mode` is passed. - if vi_mode: - editing_mode = EditingMode.VI - + # Ensure backwards-compatibility, when `vi_mode` is passed. + if vi_mode: + editing_mode = EditingMode.VI + # Make sure that complete_while_typing is disabled when enable_history_search # is enabled. (First convert to SimpleFilter, to avoid doing bitwise operations # on bool objects.) @@ -468,9 +468,9 @@ def create_prompt_application( # Accept Pygments styles as well for backwards compatibility. try: - if pygments_Style and issubclass(style, pygments_Style): - style = style_from_dict(style.styles) - except TypeError: # Happens when style is `None` or an instance of something else. + if pygments_Style and issubclass(style, pygments_Style): + style = style_from_dict(style.styles) + except TypeError: # Happens when style is `None` or an instance of something else. pass # Create application @@ -482,8 +482,8 @@ def create_prompt_application( reserve_space_for_menu=(reserve_space_for_menu if completer is not None else 0), multiline=Condition(lambda cli: multiline()), get_prompt_tokens=get_prompt_tokens, - get_continuation_tokens=get_continuation_tokens, - get_rprompt_tokens=get_rprompt_tokens, + get_continuation_tokens=get_continuation_tokens, + get_rprompt_tokens=get_rprompt_tokens, get_bottom_toolbar_tokens=get_bottom_toolbar_tokens, display_completions_in_columns=display_completions_in_columns, extra_input_processors=extra_input_processors, @@ -504,8 +504,8 @@ def create_prompt_application( key_bindings_registry=key_bindings_registry, get_title=get_title, mouse_support=mouse_support, - editing_mode=editing_mode, - erase_when_done=erase_when_done, + editing_mode=editing_mode, + erase_when_done=erase_when_done, reverse_vi_search_direction=True, on_abort=on_abort, on_exit=on_exit) @@ -529,93 +529,93 @@ def prompt(message='', **kwargs): will be printed above the prompt instead.) :param return_asyncio_coroutine: When True, return a asyncio coroutine. (Python >3.3) :param true_color: When True, use 24bit colors instead of 256 colors. - :param refresh_interval: (number; in seconds) When given, refresh the UI - every so many seconds. + :param refresh_interval: (number; in seconds) When given, refresh the UI + every so many seconds. """ patch_stdout = kwargs.pop('patch_stdout', False) return_asyncio_coroutine = kwargs.pop('return_asyncio_coroutine', False) true_color = kwargs.pop('true_color', False) - refresh_interval = kwargs.pop('refresh_interval', 0) - eventloop = kwargs.pop('eventloop', None) - - application = create_prompt_application(message, **kwargs) - - return run_application(application, - patch_stdout=patch_stdout, - return_asyncio_coroutine=return_asyncio_coroutine, - true_color=true_color, - refresh_interval=refresh_interval, - eventloop=eventloop) - - -def run_application( - application, patch_stdout=False, return_asyncio_coroutine=False, - true_color=False, refresh_interval=0, eventloop=None): - """ - Run a prompt toolkit application. - - :param patch_stdout: Replace ``sys.stdout`` by a proxy that ensures that - print statements from other threads won't destroy the prompt. (They - will be printed above the prompt instead.) - :param return_asyncio_coroutine: When True, return a asyncio coroutine. (Python >3.3) - :param true_color: When True, use 24bit colors instead of 256 colors. - :param refresh_interval: (number; in seconds) When given, refresh the UI - every so many seconds. - """ - assert isinstance(application, Application) - + refresh_interval = kwargs.pop('refresh_interval', 0) + eventloop = kwargs.pop('eventloop', None) + + application = create_prompt_application(message, **kwargs) + + return run_application(application, + patch_stdout=patch_stdout, + return_asyncio_coroutine=return_asyncio_coroutine, + true_color=true_color, + refresh_interval=refresh_interval, + eventloop=eventloop) + + +def run_application( + application, patch_stdout=False, return_asyncio_coroutine=False, + true_color=False, refresh_interval=0, eventloop=None): + """ + Run a prompt toolkit application. + + :param patch_stdout: Replace ``sys.stdout`` by a proxy that ensures that + print statements from other threads won't destroy the prompt. (They + will be printed above the prompt instead.) + :param return_asyncio_coroutine: When True, return a asyncio coroutine. (Python >3.3) + :param true_color: When True, use 24bit colors instead of 256 colors. + :param refresh_interval: (number; in seconds) When given, refresh the UI + every so many seconds. + """ + assert isinstance(application, Application) + if return_asyncio_coroutine: eventloop = create_asyncio_eventloop() else: - eventloop = eventloop or create_eventloop() + eventloop = eventloop or create_eventloop() # Create CommandLineInterface. cli = CommandLineInterface( - application=application, + application=application, eventloop=eventloop, output=create_output(true_color=true_color)) - # Set up refresh interval. - if refresh_interval: - done = [False] - def start_refresh_loop(cli): - def run(): - while not done[0]: - time.sleep(refresh_interval) - cli.request_redraw() - t = threading.Thread(target=run) - t.daemon = True - t.start() - - def stop_refresh_loop(cli): - done[0] = True - - cli.on_start += start_refresh_loop - cli.on_stop += stop_refresh_loop - + # Set up refresh interval. + if refresh_interval: + done = [False] + def start_refresh_loop(cli): + def run(): + while not done[0]: + time.sleep(refresh_interval) + cli.request_redraw() + t = threading.Thread(target=run) + t.daemon = True + t.start() + + def stop_refresh_loop(cli): + done[0] = True + + cli.on_start += start_refresh_loop + cli.on_stop += stop_refresh_loop + # Replace stdout. patch_context = cli.patch_stdout_context(raw=True) if patch_stdout else DummyContext() # Read input and return it. if return_asyncio_coroutine: # Create an asyncio coroutine and call it. - exec_context = {'patch_context': patch_context, 'cli': cli, - 'Document': Document} + exec_context = {'patch_context': patch_context, 'cli': cli, + 'Document': Document} exec_(textwrap.dedent(''' def prompt_coro(): - # Inline import, because it slows down startup when asyncio is not - # needed. - import asyncio + # Inline import, because it slows down startup when asyncio is not + # needed. + import asyncio - @asyncio.coroutine - def run(): - with patch_context: + @asyncio.coroutine + def run(): + with patch_context: result = yield from cli.run_async() - - if isinstance(result, Document): # Backwards-compatibility. - return result.text - return result - return run() + + if isinstance(result, Document): # Backwards-compatibility. + return result.text + return result + return run() '''), exec_context) return exec_context['prompt_coro']() @@ -624,9 +624,9 @@ def run_application( with patch_context: result = cli.run() - if isinstance(result, Document): # Backwards-compatibility. - return result.text - return result + if isinstance(result, Document): # Backwards-compatibility. + return result.text + return result finally: eventloop.close() @@ -639,79 +639,79 @@ def prompt_async(message='', **kwargs): return prompt(message, **kwargs) -def create_confirm_application(message): - """ - Create a confirmation `Application` that returns True/False. - """ - registry = Registry() - - @registry.add_binding('y') - @registry.add_binding('Y') - def _(event): - event.cli.buffers[DEFAULT_BUFFER].text = 'y' - event.cli.set_return_value(True) - - @registry.add_binding('n') - @registry.add_binding('N') - @registry.add_binding(Keys.ControlC) - def _(event): - event.cli.buffers[DEFAULT_BUFFER].text = 'n' - event.cli.set_return_value(False) - - return create_prompt_application(message, key_bindings_registry=registry) - - -def confirm(message='Confirm (y or n) '): - """ - Display a confirmation prompt. - """ - assert isinstance(message, text_type) - - app = create_confirm_application(message) - return run_application(app) - - +def create_confirm_application(message): + """ + Create a confirmation `Application` that returns True/False. + """ + registry = Registry() + + @registry.add_binding('y') + @registry.add_binding('Y') + def _(event): + event.cli.buffers[DEFAULT_BUFFER].text = 'y' + event.cli.set_return_value(True) + + @registry.add_binding('n') + @registry.add_binding('N') + @registry.add_binding(Keys.ControlC) + def _(event): + event.cli.buffers[DEFAULT_BUFFER].text = 'n' + event.cli.set_return_value(False) + + return create_prompt_application(message, key_bindings_registry=registry) + + +def confirm(message='Confirm (y or n) '): + """ + Display a confirmation prompt. + """ + assert isinstance(message, text_type) + + app = create_confirm_application(message) + return run_application(app) + + def print_tokens(tokens, style=None, true_color=False, file=None): - """ - Print a list of (Token, text) tuples in the given style to the output. - E.g.:: - - style = style_from_dict({ - Token.Hello: '#ff0066', - Token.World: '#884444 italic', - }) - tokens = [ - (Token.Hello, 'Hello'), - (Token.World, 'World'), - ] - print_tokens(tokens, style=style) - - :param tokens: List of ``(Token, text)`` tuples. - :param style: :class:`.Style` instance for the color scheme. - :param true_color: When True, use 24bit colors instead of 256 colors. + """ + Print a list of (Token, text) tuples in the given style to the output. + E.g.:: + + style = style_from_dict({ + Token.Hello: '#ff0066', + Token.World: '#884444 italic', + }) + tokens = [ + (Token.Hello, 'Hello'), + (Token.World, 'World'), + ] + print_tokens(tokens, style=style) + + :param tokens: List of ``(Token, text)`` tuples. + :param style: :class:`.Style` instance for the color scheme. + :param true_color: When True, use 24bit colors instead of 256 colors. :param file: The output file. This can be `sys.stdout` or `sys.stderr`. - """ + """ if style is None: style = DEFAULT_STYLE - assert isinstance(style, Style) - + assert isinstance(style, Style) + output = create_output(true_color=true_color, stdout=file) - renderer_print_tokens(output, tokens, style) - - -def clear(): - """ - Clear the screen. - """ - out = create_output() - out.erase_screen() - out.cursor_goto(0, 0) - out.flush() - - + renderer_print_tokens(output, tokens, style) + + +def clear(): + """ + Clear the screen. + """ + out = create_output() + out.erase_screen() + out.cursor_goto(0, 0) + out.flush() + + # Deprecated alias for `prompt`. get_input = prompt -# Deprecated alias for create_prompt_layout -create_default_layout = create_prompt_layout -# Deprecated alias for create_prompt_application -create_default_application = create_prompt_application +# Deprecated alias for create_prompt_layout +create_default_layout = create_prompt_layout +# Deprecated alias for create_prompt_application +create_default_application = create_prompt_application diff --git a/contrib/python/prompt-toolkit/py2/prompt_toolkit/styles/__init__.py b/contrib/python/prompt-toolkit/py2/prompt_toolkit/styles/__init__.py index 9d641f0447..4735ab2155 100644 --- a/contrib/python/prompt-toolkit/py2/prompt_toolkit/styles/__init__.py +++ b/contrib/python/prompt-toolkit/py2/prompt_toolkit/styles/__init__.py @@ -1,21 +1,21 @@ -""" -Styling for prompt_toolkit applications. -""" -from __future__ import unicode_literals - -from .base import * -from .defaults import * -from .from_dict import * -from .from_pygments import * -from .utils import * - - -#: The default built-in style. -#: (For backwards compatibility, when Pygments is installed, this includes the -#: default Pygments style.) -try: - import pygments -except ImportError: - DEFAULT_STYLE = style_from_dict(DEFAULT_STYLE_EXTENSIONS) -else: - DEFAULT_STYLE = style_from_pygments() +""" +Styling for prompt_toolkit applications. +""" +from __future__ import unicode_literals + +from .base import * +from .defaults import * +from .from_dict import * +from .from_pygments import * +from .utils import * + + +#: The default built-in style. +#: (For backwards compatibility, when Pygments is installed, this includes the +#: default Pygments style.) +try: + import pygments +except ImportError: + DEFAULT_STYLE = style_from_dict(DEFAULT_STYLE_EXTENSIONS) +else: + DEFAULT_STYLE = style_from_pygments() diff --git a/contrib/python/prompt-toolkit/py2/prompt_toolkit/styles/base.py b/contrib/python/prompt-toolkit/py2/prompt_toolkit/styles/base.py index e9ddaa524d..d1009ba3b2 100644 --- a/contrib/python/prompt-toolkit/py2/prompt_toolkit/styles/base.py +++ b/contrib/python/prompt-toolkit/py2/prompt_toolkit/styles/base.py @@ -1,86 +1,86 @@ -""" -The base classes for the styling. -""" -from __future__ import unicode_literals -from abc import ABCMeta, abstractmethod -from collections import namedtuple -from six import with_metaclass - -__all__ = ( - 'Attrs', - 'DEFAULT_ATTRS', - 'ANSI_COLOR_NAMES', - 'Style', - 'DynamicStyle', -) - - -#: Style attributes. -Attrs = namedtuple('Attrs', 'color bgcolor bold underline italic blink reverse') -""" -:param color: Hexadecimal string. E.g. '000000' or Ansi color name: e.g. 'ansiblue' -:param bgcolor: Hexadecimal string. E.g. 'ffffff' or Ansi color name: e.g. 'ansired' -:param bold: Boolean -:param underline: Boolean -:param italic: Boolean -:param blink: Boolean -:param reverse: Boolean -""" - -#: The default `Attrs`. -DEFAULT_ATTRS = Attrs(color=None, bgcolor=None, bold=False, underline=False, - italic=False, blink=False, reverse=False) - - -#: ``Attrs.bgcolor/fgcolor`` can be in either 'ffffff' format, or can be any of -#: the following in case we want to take colors from the 8/16 color palette. -#: Usually, in that case, the terminal application allows to configure the RGB -#: values for these names. -ANSI_COLOR_NAMES = [ - 'ansiblack', 'ansiwhite', 'ansidefault', - - # Low intensity. - 'ansired', 'ansigreen', 'ansiyellow', 'ansiblue', 'ansifuchsia', 'ansiturquoise', 'ansilightgray', - - # High intensity. (Not supported everywhere.) - 'ansidarkgray', 'ansidarkred', 'ansidarkgreen', 'ansibrown', 'ansidarkblue', - 'ansipurple', 'ansiteal', -] - - -class Style(with_metaclass(ABCMeta, object)): - """ - Abstract base class for prompt_toolkit styles. - """ - @abstractmethod - def get_attrs_for_token(self, token): - """ - Return :class:`.Attrs` for the given token. - """ - - @abstractmethod - def invalidation_hash(self): - """ - Invalidation hash for the style. When this changes over time, the - renderer knows that something in the style changed, and that everything - has to be redrawn. - """ - - -class DynamicStyle(Style): - """ - Style class that can dynamically returns an other Style. - - :param get_style: Callable that returns a :class:`.Style` instance. - """ - def __init__(self, get_style): - self.get_style = get_style - - def get_attrs_for_token(self, token): - style = self.get_style() - assert isinstance(style, Style) - - return style.get_attrs_for_token(token) - - def invalidation_hash(self): - return self.get_style().invalidation_hash() +""" +The base classes for the styling. +""" +from __future__ import unicode_literals +from abc import ABCMeta, abstractmethod +from collections import namedtuple +from six import with_metaclass + +__all__ = ( + 'Attrs', + 'DEFAULT_ATTRS', + 'ANSI_COLOR_NAMES', + 'Style', + 'DynamicStyle', +) + + +#: Style attributes. +Attrs = namedtuple('Attrs', 'color bgcolor bold underline italic blink reverse') +""" +:param color: Hexadecimal string. E.g. '000000' or Ansi color name: e.g. 'ansiblue' +:param bgcolor: Hexadecimal string. E.g. 'ffffff' or Ansi color name: e.g. 'ansired' +:param bold: Boolean +:param underline: Boolean +:param italic: Boolean +:param blink: Boolean +:param reverse: Boolean +""" + +#: The default `Attrs`. +DEFAULT_ATTRS = Attrs(color=None, bgcolor=None, bold=False, underline=False, + italic=False, blink=False, reverse=False) + + +#: ``Attrs.bgcolor/fgcolor`` can be in either 'ffffff' format, or can be any of +#: the following in case we want to take colors from the 8/16 color palette. +#: Usually, in that case, the terminal application allows to configure the RGB +#: values for these names. +ANSI_COLOR_NAMES = [ + 'ansiblack', 'ansiwhite', 'ansidefault', + + # Low intensity. + 'ansired', 'ansigreen', 'ansiyellow', 'ansiblue', 'ansifuchsia', 'ansiturquoise', 'ansilightgray', + + # High intensity. (Not supported everywhere.) + 'ansidarkgray', 'ansidarkred', 'ansidarkgreen', 'ansibrown', 'ansidarkblue', + 'ansipurple', 'ansiteal', +] + + +class Style(with_metaclass(ABCMeta, object)): + """ + Abstract base class for prompt_toolkit styles. + """ + @abstractmethod + def get_attrs_for_token(self, token): + """ + Return :class:`.Attrs` for the given token. + """ + + @abstractmethod + def invalidation_hash(self): + """ + Invalidation hash for the style. When this changes over time, the + renderer knows that something in the style changed, and that everything + has to be redrawn. + """ + + +class DynamicStyle(Style): + """ + Style class that can dynamically returns an other Style. + + :param get_style: Callable that returns a :class:`.Style` instance. + """ + def __init__(self, get_style): + self.get_style = get_style + + def get_attrs_for_token(self, token): + style = self.get_style() + assert isinstance(style, Style) + + return style.get_attrs_for_token(token) + + def invalidation_hash(self): + return self.get_style().invalidation_hash() diff --git a/contrib/python/prompt-toolkit/py2/prompt_toolkit/styles/defaults.py b/contrib/python/prompt-toolkit/py2/prompt_toolkit/styles/defaults.py index 5357eaa111..f280dd4646 100644 --- a/contrib/python/prompt-toolkit/py2/prompt_toolkit/styles/defaults.py +++ b/contrib/python/prompt-toolkit/py2/prompt_toolkit/styles/defaults.py @@ -1,95 +1,95 @@ -""" -The default styling. -""" -from __future__ import unicode_literals - -from prompt_toolkit.token import Token - -__all__ = ( - 'DEFAULT_STYLE_EXTENSIONS', - 'default_style_extensions', -) - - -#: Styling of prompt-toolkit specific tokens, that are not know by the default -#: Pygments style. -DEFAULT_STYLE_EXTENSIONS = { - # Highlighting of search matches in document. - Token.SearchMatch: 'noinherit reverse', - Token.SearchMatch.Current: 'noinherit #ffffff bg:#448844 underline', - - # Highlighting of select text in document. - Token.SelectedText: 'reverse', - - Token.CursorColumn: 'bg:#dddddd', - Token.CursorLine: 'underline', - Token.ColorColumn: 'bg:#ccaacc', - - # Highlighting of matching brackets. - Token.MatchingBracket: '', - Token.MatchingBracket.Other: '#000000 bg:#aacccc', - Token.MatchingBracket.Cursor: '#ff8888 bg:#880000', - - Token.MultipleCursors.Cursor: '#000000 bg:#ccccaa', - - # Line numbers. - Token.LineNumber: '#888888', - Token.LineNumber.Current: 'bold', - Token.Tilde: '#8888ff', - - # Default prompt. - Token.Prompt: '', - Token.Prompt.Arg: 'noinherit', - Token.Prompt.Search: 'noinherit', - Token.Prompt.Search.Text: '', - - # Search toolbar. - Token.Toolbar.Search: 'bold', - Token.Toolbar.Search.Text: 'nobold', - - # System toolbar - Token.Toolbar.System: 'bold', - Token.Toolbar.System.Text: 'nobold', - - # "arg" toolbar. - Token.Toolbar.Arg: 'bold', - Token.Toolbar.Arg.Text: 'nobold', - - # Validation toolbar. - Token.Toolbar.Validation: 'bg:#550000 #ffffff', - Token.WindowTooSmall: 'bg:#550000 #ffffff', - - # Completions toolbar. - Token.Toolbar.Completions: 'bg:#bbbbbb #000000', - Token.Toolbar.Completions.Arrow: 'bg:#bbbbbb #000000 bold', - Token.Toolbar.Completions.Completion: 'bg:#bbbbbb #000000', - Token.Toolbar.Completions.Completion.Current: 'bg:#444444 #ffffff', - - # Completions menu. - Token.Menu.Completions: 'bg:#bbbbbb #000000', - Token.Menu.Completions.Completion: '', - Token.Menu.Completions.Completion.Current: 'bg:#888888 #ffffff', - Token.Menu.Completions.Meta: 'bg:#999999 #000000', - Token.Menu.Completions.Meta.Current: 'bg:#aaaaaa #000000', - Token.Menu.Completions.MultiColumnMeta: 'bg:#aaaaaa #000000', - - # Scrollbars. - Token.Scrollbar: 'bg:#888888', - Token.Scrollbar.Button: 'bg:#444444', - Token.Scrollbar.Arrow: 'bg:#222222 #888888 bold', - - # Auto suggestion text. - Token.AutoSuggestion: '#666666', - - # Trailing whitespace and tabs. - Token.TrailingWhiteSpace: '#999999', - Token.Tab: '#999999', - - # When Control-C has been pressed. Grayed. - Token.Aborted: '#888888', - - # Entering a Vi digraph. - Token.Digraph: '#4444ff', -} - -default_style_extensions = DEFAULT_STYLE_EXTENSIONS # Old name. +""" +The default styling. +""" +from __future__ import unicode_literals + +from prompt_toolkit.token import Token + +__all__ = ( + 'DEFAULT_STYLE_EXTENSIONS', + 'default_style_extensions', +) + + +#: Styling of prompt-toolkit specific tokens, that are not know by the default +#: Pygments style. +DEFAULT_STYLE_EXTENSIONS = { + # Highlighting of search matches in document. + Token.SearchMatch: 'noinherit reverse', + Token.SearchMatch.Current: 'noinherit #ffffff bg:#448844 underline', + + # Highlighting of select text in document. + Token.SelectedText: 'reverse', + + Token.CursorColumn: 'bg:#dddddd', + Token.CursorLine: 'underline', + Token.ColorColumn: 'bg:#ccaacc', + + # Highlighting of matching brackets. + Token.MatchingBracket: '', + Token.MatchingBracket.Other: '#000000 bg:#aacccc', + Token.MatchingBracket.Cursor: '#ff8888 bg:#880000', + + Token.MultipleCursors.Cursor: '#000000 bg:#ccccaa', + + # Line numbers. + Token.LineNumber: '#888888', + Token.LineNumber.Current: 'bold', + Token.Tilde: '#8888ff', + + # Default prompt. + Token.Prompt: '', + Token.Prompt.Arg: 'noinherit', + Token.Prompt.Search: 'noinherit', + Token.Prompt.Search.Text: '', + + # Search toolbar. + Token.Toolbar.Search: 'bold', + Token.Toolbar.Search.Text: 'nobold', + + # System toolbar + Token.Toolbar.System: 'bold', + Token.Toolbar.System.Text: 'nobold', + + # "arg" toolbar. + Token.Toolbar.Arg: 'bold', + Token.Toolbar.Arg.Text: 'nobold', + + # Validation toolbar. + Token.Toolbar.Validation: 'bg:#550000 #ffffff', + Token.WindowTooSmall: 'bg:#550000 #ffffff', + + # Completions toolbar. + Token.Toolbar.Completions: 'bg:#bbbbbb #000000', + Token.Toolbar.Completions.Arrow: 'bg:#bbbbbb #000000 bold', + Token.Toolbar.Completions.Completion: 'bg:#bbbbbb #000000', + Token.Toolbar.Completions.Completion.Current: 'bg:#444444 #ffffff', + + # Completions menu. + Token.Menu.Completions: 'bg:#bbbbbb #000000', + Token.Menu.Completions.Completion: '', + Token.Menu.Completions.Completion.Current: 'bg:#888888 #ffffff', + Token.Menu.Completions.Meta: 'bg:#999999 #000000', + Token.Menu.Completions.Meta.Current: 'bg:#aaaaaa #000000', + Token.Menu.Completions.MultiColumnMeta: 'bg:#aaaaaa #000000', + + # Scrollbars. + Token.Scrollbar: 'bg:#888888', + Token.Scrollbar.Button: 'bg:#444444', + Token.Scrollbar.Arrow: 'bg:#222222 #888888 bold', + + # Auto suggestion text. + Token.AutoSuggestion: '#666666', + + # Trailing whitespace and tabs. + Token.TrailingWhiteSpace: '#999999', + Token.Tab: '#999999', + + # When Control-C has been pressed. Grayed. + Token.Aborted: '#888888', + + # Entering a Vi digraph. + Token.Digraph: '#4444ff', +} + +default_style_extensions = DEFAULT_STYLE_EXTENSIONS # Old name. diff --git a/contrib/python/prompt-toolkit/py2/prompt_toolkit/styles/from_dict.py b/contrib/python/prompt-toolkit/py2/prompt_toolkit/styles/from_dict.py index b50325710f..e000aceb93 100644 --- a/contrib/python/prompt-toolkit/py2/prompt_toolkit/styles/from_dict.py +++ b/contrib/python/prompt-toolkit/py2/prompt_toolkit/styles/from_dict.py @@ -1,151 +1,151 @@ -""" -Tool for creating styles from a dictionary. - -This is very similar to the Pygments style dictionary, with some additions: -- Support for reverse and blink. -- Support for ANSI color names. (These will map directly to the 16 terminal - colors.) -""" +""" +Tool for creating styles from a dictionary. + +This is very similar to the Pygments style dictionary, with some additions: +- Support for reverse and blink. +- Support for ANSI color names. (These will map directly to the 16 terminal + colors.) +""" try: from collections.abc import Mapping except ImportError: from collections import Mapping - -from .base import Style, DEFAULT_ATTRS, ANSI_COLOR_NAMES -from .defaults import DEFAULT_STYLE_EXTENSIONS -from .utils import merge_attrs, split_token_in_parts -from six.moves import range - -__all__ = ( - 'style_from_dict', -) - - -def _colorformat(text): - """ - Parse/validate color format. - - Like in Pygments, but also support the ANSI color names. - (These will map to the colors of the 16 color palette.) - """ - if text[0:1] == '#': - col = text[1:] - if col in ANSI_COLOR_NAMES: - return col - elif len(col) == 6: - return col - elif len(col) == 3: - return col[0]*2 + col[1]*2 + col[2]*2 - elif text == '': - return text - - raise ValueError('Wrong color format %r' % text) - - -def style_from_dict(style_dict, include_defaults=True): - """ - Create a ``Style`` instance from a dictionary or other mapping. - - The dictionary is equivalent to the ``Style.styles`` dictionary from - pygments, with a few additions: it supports 'reverse' and 'blink'. - - Usage:: - - style_from_dict({ - Token: '#ff0000 bold underline', - Token.Title: 'blink', - Token.SomethingElse: 'reverse', - }) - - :param include_defaults: Include the defaults (built-in) styling for - selected text, etc...) - """ - assert isinstance(style_dict, Mapping) - - if include_defaults: - s2 = {} - s2.update(DEFAULT_STYLE_EXTENSIONS) - s2.update(style_dict) - style_dict = s2 - - # Expand token inheritance and turn style description into Attrs. - token_to_attrs = {} - - # (Loop through the tokens in order. Sorting makes sure that - # we process the parent first.) - for ttype, styledef in sorted(style_dict.items()): - # Start from parent Attrs or default Attrs. - attrs = DEFAULT_ATTRS - - if 'noinherit' not in styledef: - for i in range(1, len(ttype) + 1): - try: - attrs = token_to_attrs[ttype[:-i]] - except KeyError: - pass - else: - break - - # Now update with the given attributes. - for part in styledef.split(): - if part == 'noinherit': - pass - elif part == 'bold': - attrs = attrs._replace(bold=True) - elif part == 'nobold': - attrs = attrs._replace(bold=False) - elif part == 'italic': - attrs = attrs._replace(italic=True) - elif part == 'noitalic': - attrs = attrs._replace(italic=False) - elif part == 'underline': - attrs = attrs._replace(underline=True) - elif part == 'nounderline': - attrs = attrs._replace(underline=False) - - # prompt_toolkit extensions. Not in Pygments. - elif part == 'blink': - attrs = attrs._replace(blink=True) - elif part == 'noblink': - attrs = attrs._replace(blink=False) - elif part == 'reverse': - attrs = attrs._replace(reverse=True) - elif part == 'noreverse': - attrs = attrs._replace(reverse=False) - - # Pygments properties that we ignore. - elif part in ('roman', 'sans', 'mono'): - pass - elif part.startswith('border:'): - pass - - # Colors. - - elif part.startswith('bg:'): - attrs = attrs._replace(bgcolor=_colorformat(part[3:])) - else: - attrs = attrs._replace(color=_colorformat(part)) - - token_to_attrs[ttype] = attrs - - return _StyleFromDict(token_to_attrs) - - -class _StyleFromDict(Style): - """ - Turn a dictionary that maps `Token` to `Attrs` into a style class. - - :param token_to_attrs: Dictionary that maps `Token` to `Attrs`. - """ - def __init__(self, token_to_attrs): - self.token_to_attrs = token_to_attrs - - def get_attrs_for_token(self, token): - # Split Token. - list_of_attrs = [] - for token in split_token_in_parts(token): - list_of_attrs.append(self.token_to_attrs.get(token, DEFAULT_ATTRS)) - return merge_attrs(list_of_attrs) - - def invalidation_hash(self): - return id(self.token_to_attrs) + +from .base import Style, DEFAULT_ATTRS, ANSI_COLOR_NAMES +from .defaults import DEFAULT_STYLE_EXTENSIONS +from .utils import merge_attrs, split_token_in_parts +from six.moves import range + +__all__ = ( + 'style_from_dict', +) + + +def _colorformat(text): + """ + Parse/validate color format. + + Like in Pygments, but also support the ANSI color names. + (These will map to the colors of the 16 color palette.) + """ + if text[0:1] == '#': + col = text[1:] + if col in ANSI_COLOR_NAMES: + return col + elif len(col) == 6: + return col + elif len(col) == 3: + return col[0]*2 + col[1]*2 + col[2]*2 + elif text == '': + return text + + raise ValueError('Wrong color format %r' % text) + + +def style_from_dict(style_dict, include_defaults=True): + """ + Create a ``Style`` instance from a dictionary or other mapping. + + The dictionary is equivalent to the ``Style.styles`` dictionary from + pygments, with a few additions: it supports 'reverse' and 'blink'. + + Usage:: + + style_from_dict({ + Token: '#ff0000 bold underline', + Token.Title: 'blink', + Token.SomethingElse: 'reverse', + }) + + :param include_defaults: Include the defaults (built-in) styling for + selected text, etc...) + """ + assert isinstance(style_dict, Mapping) + + if include_defaults: + s2 = {} + s2.update(DEFAULT_STYLE_EXTENSIONS) + s2.update(style_dict) + style_dict = s2 + + # Expand token inheritance and turn style description into Attrs. + token_to_attrs = {} + + # (Loop through the tokens in order. Sorting makes sure that + # we process the parent first.) + for ttype, styledef in sorted(style_dict.items()): + # Start from parent Attrs or default Attrs. + attrs = DEFAULT_ATTRS + + if 'noinherit' not in styledef: + for i in range(1, len(ttype) + 1): + try: + attrs = token_to_attrs[ttype[:-i]] + except KeyError: + pass + else: + break + + # Now update with the given attributes. + for part in styledef.split(): + if part == 'noinherit': + pass + elif part == 'bold': + attrs = attrs._replace(bold=True) + elif part == 'nobold': + attrs = attrs._replace(bold=False) + elif part == 'italic': + attrs = attrs._replace(italic=True) + elif part == 'noitalic': + attrs = attrs._replace(italic=False) + elif part == 'underline': + attrs = attrs._replace(underline=True) + elif part == 'nounderline': + attrs = attrs._replace(underline=False) + + # prompt_toolkit extensions. Not in Pygments. + elif part == 'blink': + attrs = attrs._replace(blink=True) + elif part == 'noblink': + attrs = attrs._replace(blink=False) + elif part == 'reverse': + attrs = attrs._replace(reverse=True) + elif part == 'noreverse': + attrs = attrs._replace(reverse=False) + + # Pygments properties that we ignore. + elif part in ('roman', 'sans', 'mono'): + pass + elif part.startswith('border:'): + pass + + # Colors. + + elif part.startswith('bg:'): + attrs = attrs._replace(bgcolor=_colorformat(part[3:])) + else: + attrs = attrs._replace(color=_colorformat(part)) + + token_to_attrs[ttype] = attrs + + return _StyleFromDict(token_to_attrs) + + +class _StyleFromDict(Style): + """ + Turn a dictionary that maps `Token` to `Attrs` into a style class. + + :param token_to_attrs: Dictionary that maps `Token` to `Attrs`. + """ + def __init__(self, token_to_attrs): + self.token_to_attrs = token_to_attrs + + def get_attrs_for_token(self, token): + # Split Token. + list_of_attrs = [] + for token in split_token_in_parts(token): + list_of_attrs.append(self.token_to_attrs.get(token, DEFAULT_ATTRS)) + return merge_attrs(list_of_attrs) + + def invalidation_hash(self): + return id(self.token_to_attrs) diff --git a/contrib/python/prompt-toolkit/py2/prompt_toolkit/styles/from_pygments.py b/contrib/python/prompt-toolkit/py2/prompt_toolkit/styles/from_pygments.py index 0af8c53cf2..9be932f2e0 100644 --- a/contrib/python/prompt-toolkit/py2/prompt_toolkit/styles/from_pygments.py +++ b/contrib/python/prompt-toolkit/py2/prompt_toolkit/styles/from_pygments.py @@ -1,77 +1,77 @@ -""" -Adaptor for building prompt_toolkit styles, starting from a Pygments style. - -Usage:: - - from pygments.styles.tango import TangoStyle - style = style_from_pygments(pygments_style_cls=TangoStyle) -""" -from __future__ import unicode_literals - -from .base import Style -from .from_dict import style_from_dict - -__all__ = ( - 'PygmentsStyle', - 'style_from_pygments', -) - - -# Following imports are only needed when a ``PygmentsStyle`` class is used. -try: - from pygments.style import Style as pygments_Style - from pygments.styles.default import DefaultStyle as pygments_DefaultStyle -except ImportError: - pygments_Style = None - pygments_DefaultStyle = None - - -def style_from_pygments(style_cls=pygments_DefaultStyle, - style_dict=None, - include_defaults=True): - """ - Shortcut to create a :class:`.Style` instance from a Pygments style class - and a style dictionary. - +""" +Adaptor for building prompt_toolkit styles, starting from a Pygments style. + +Usage:: + + from pygments.styles.tango import TangoStyle + style = style_from_pygments(pygments_style_cls=TangoStyle) +""" +from __future__ import unicode_literals + +from .base import Style +from .from_dict import style_from_dict + +__all__ = ( + 'PygmentsStyle', + 'style_from_pygments', +) + + +# Following imports are only needed when a ``PygmentsStyle`` class is used. +try: + from pygments.style import Style as pygments_Style + from pygments.styles.default import DefaultStyle as pygments_DefaultStyle +except ImportError: + pygments_Style = None + pygments_DefaultStyle = None + + +def style_from_pygments(style_cls=pygments_DefaultStyle, + style_dict=None, + include_defaults=True): + """ + Shortcut to create a :class:`.Style` instance from a Pygments style class + and a style dictionary. + Example:: from prompt_toolkit.styles.from_pygments import style_from_pygments from pygments.styles import get_style_by_name style = style_from_pygments(get_style_by_name('monokai')) - :param style_cls: Pygments style class to start from. - :param style_dict: Dictionary for this style. `{Token: style}`. - :param include_defaults: (`bool`) Include prompt_toolkit extensions. - """ - assert style_dict is None or isinstance(style_dict, dict) - assert style_cls is None or issubclass(style_cls, pygments_Style) - - styles_dict = {} - - if style_cls is not None: - styles_dict.update(style_cls.styles) - - if style_dict is not None: - styles_dict.update(style_dict) - - return style_from_dict(styles_dict, include_defaults=include_defaults) - - -class PygmentsStyle(Style): - " Deprecated. " - def __new__(cls, pygments_style_cls): - assert issubclass(pygments_style_cls, pygments_Style) - return style_from_dict(pygments_style_cls.styles) - - def invalidation_hash(self): - pass - - @classmethod - def from_defaults(cls, style_dict=None, - pygments_style_cls=pygments_DefaultStyle, - include_extensions=True): - " Deprecated. " - return style_from_pygments( - style_cls=pygments_style_cls, - style_dict=style_dict, - include_defaults=include_extensions) + :param style_cls: Pygments style class to start from. + :param style_dict: Dictionary for this style. `{Token: style}`. + :param include_defaults: (`bool`) Include prompt_toolkit extensions. + """ + assert style_dict is None or isinstance(style_dict, dict) + assert style_cls is None or issubclass(style_cls, pygments_Style) + + styles_dict = {} + + if style_cls is not None: + styles_dict.update(style_cls.styles) + + if style_dict is not None: + styles_dict.update(style_dict) + + return style_from_dict(styles_dict, include_defaults=include_defaults) + + +class PygmentsStyle(Style): + " Deprecated. " + def __new__(cls, pygments_style_cls): + assert issubclass(pygments_style_cls, pygments_Style) + return style_from_dict(pygments_style_cls.styles) + + def invalidation_hash(self): + pass + + @classmethod + def from_defaults(cls, style_dict=None, + pygments_style_cls=pygments_DefaultStyle, + include_extensions=True): + " Deprecated. " + return style_from_pygments( + style_cls=pygments_style_cls, + style_dict=style_dict, + include_defaults=include_extensions) diff --git a/contrib/python/prompt-toolkit/py2/prompt_toolkit/styles/utils.py b/contrib/python/prompt-toolkit/py2/prompt_toolkit/styles/utils.py index 6087e76abe..75982af3ab 100644 --- a/contrib/python/prompt-toolkit/py2/prompt_toolkit/styles/utils.py +++ b/contrib/python/prompt-toolkit/py2/prompt_toolkit/styles/utils.py @@ -1,45 +1,45 @@ -from __future__ import unicode_literals -from .base import DEFAULT_ATTRS, Attrs - -__all__ = ( - 'split_token_in_parts', - 'merge_attrs', -) - - -def split_token_in_parts(token): - """ - Take a Token, and turn it in a list of tokens, by splitting - it on ':' (taking that as a separator.) - """ - result = [] - current = [] - for part in token + (':', ): - if part == ':': - if current: - result.append(tuple(current)) - current = [] - else: - current.append(part) - - return result - - -def merge_attrs(list_of_attrs): - """ - Take a list of :class:`.Attrs` instances and merge them into one. - Every `Attr` in the list can override the styling of the previous one. - """ - result = DEFAULT_ATTRS - - for attr in list_of_attrs: - result = Attrs( - color=attr.color or result.color, - bgcolor=attr.bgcolor or result.bgcolor, - bold=attr.bold or result.bold, - underline=attr.underline or result.underline, - italic=attr.italic or result.italic, - blink=attr.blink or result.blink, - reverse=attr.reverse or result.reverse) - - return result +from __future__ import unicode_literals +from .base import DEFAULT_ATTRS, Attrs + +__all__ = ( + 'split_token_in_parts', + 'merge_attrs', +) + + +def split_token_in_parts(token): + """ + Take a Token, and turn it in a list of tokens, by splitting + it on ':' (taking that as a separator.) + """ + result = [] + current = [] + for part in token + (':', ): + if part == ':': + if current: + result.append(tuple(current)) + current = [] + else: + current.append(part) + + return result + + +def merge_attrs(list_of_attrs): + """ + Take a list of :class:`.Attrs` instances and merge them into one. + Every `Attr` in the list can override the styling of the previous one. + """ + result = DEFAULT_ATTRS + + for attr in list_of_attrs: + result = Attrs( + color=attr.color or result.color, + bgcolor=attr.bgcolor or result.bgcolor, + bold=attr.bold or result.bold, + underline=attr.underline or result.underline, + italic=attr.italic or result.italic, + blink=attr.blink or result.blink, + reverse=attr.reverse or result.reverse) + + return result diff --git a/contrib/python/prompt-toolkit/py2/prompt_toolkit/terminal/conemu_output.py b/contrib/python/prompt-toolkit/py2/prompt_toolkit/terminal/conemu_output.py index 16b7bde8f3..1b7e69fbd4 100644 --- a/contrib/python/prompt-toolkit/py2/prompt_toolkit/terminal/conemu_output.py +++ b/contrib/python/prompt-toolkit/py2/prompt_toolkit/terminal/conemu_output.py @@ -32,8 +32,8 @@ class ConEmuOutput(object): def __getattr__(self, name): if name in ('get_size', 'get_rows_below_cursor_position', 'enable_mouse_support', 'disable_mouse_support', - 'scroll_buffer_to_prompt', 'get_win32_screen_buffer_info', - 'enable_bracketed_paste', 'disable_bracketed_paste'): + 'scroll_buffer_to_prompt', 'get_win32_screen_buffer_info', + 'enable_bracketed_paste', 'disable_bracketed_paste'): return getattr(self.win32_output, name) else: return getattr(self.vt100_output, name) diff --git a/contrib/python/prompt-toolkit/py2/prompt_toolkit/terminal/vt100_input.py b/contrib/python/prompt-toolkit/py2/prompt_toolkit/terminal/vt100_input.py index 74841312fa..a66afc28c6 100644 --- a/contrib/python/prompt-toolkit/py2/prompt_toolkit/terminal/vt100_input.py +++ b/contrib/python/prompt-toolkit/py2/prompt_toolkit/terminal/vt100_input.py @@ -9,8 +9,8 @@ import six import termios import tty -from six.moves import range - +from six.moves import range + from ..keys import Keys from ..key_binding.input_processor import KeyPress @@ -93,7 +93,7 @@ ANSI_SEQUENCES = { '\x1bOF': Keys.End, '\x1b[3~': Keys.Delete, '\x1b[3;2~': Keys.ShiftDelete, # xterm, gnome-terminal. - '\x1b[3;5~': Keys.ControlDelete, # xterm, gnome-terminal. + '\x1b[3;5~': Keys.ControlDelete, # xterm, gnome-terminal. '\x1b[1~': Keys.Home, # tmux '\x1b[4~': Keys.End, # tmux '\x1b[5~': Keys.PageUp, @@ -107,11 +107,11 @@ ANSI_SEQUENCES = { '\x1bOQ': Keys.F2, '\x1bOR': Keys.F3, '\x1bOS': Keys.F4, - '\x1b[[A': Keys.F1, # Linux console. - '\x1b[[B': Keys.F2, # Linux console. - '\x1b[[C': Keys.F3, # Linux console. - '\x1b[[D': Keys.F4, # Linux console. - '\x1b[[E': Keys.F5, # Linux console. + '\x1b[[A': Keys.F1, # Linux console. + '\x1b[[B': Keys.F2, # Linux console. + '\x1b[[C': Keys.F3, # Linux console. + '\x1b[[D': Keys.F4, # Linux console. + '\x1b[[E': Keys.F5, # Linux console. '\x1b[11~': Keys.F1, # rxvt-unicode '\x1b[12~': Keys.F2, # rxvt-unicode '\x1b[13~': Keys.F3, # rxvt-unicode @@ -132,39 +132,39 @@ ANSI_SEQUENCES = { '\x1b[32~': Keys.F18, '\x1b[33~': Keys.F19, '\x1b[34~': Keys.F20, - - # Xterm - '\x1b[1;2P': Keys.F13, - '\x1b[1;2Q': Keys.F14, - # '\x1b[1;2R': Keys.F15, # Conflicts with CPR response. - '\x1b[1;2S': Keys.F16, - '\x1b[15;2~': Keys.F17, - '\x1b[17;2~': Keys.F18, - '\x1b[18;2~': Keys.F19, - '\x1b[19;2~': Keys.F20, - '\x1b[20;2~': Keys.F21, - '\x1b[21;2~': Keys.F22, - '\x1b[23;2~': Keys.F23, - '\x1b[24;2~': Keys.F24, - + + # Xterm + '\x1b[1;2P': Keys.F13, + '\x1b[1;2Q': Keys.F14, + # '\x1b[1;2R': Keys.F15, # Conflicts with CPR response. + '\x1b[1;2S': Keys.F16, + '\x1b[15;2~': Keys.F17, + '\x1b[17;2~': Keys.F18, + '\x1b[18;2~': Keys.F19, + '\x1b[19;2~': Keys.F20, + '\x1b[20;2~': Keys.F21, + '\x1b[21;2~': Keys.F22, + '\x1b[23;2~': Keys.F23, + '\x1b[24;2~': Keys.F24, + '\x1b[1;5A': Keys.ControlUp, # Cursor Mode '\x1b[1;5B': Keys.ControlDown, # Cursor Mode '\x1b[1;5C': Keys.ControlRight, # Cursor Mode '\x1b[1;5D': Keys.ControlLeft, # Cursor Mode - '\x1b[1;2A': Keys.ShiftUp, - '\x1b[1;2B': Keys.ShiftDown, - '\x1b[1;2C': Keys.ShiftRight, - '\x1b[1;2D': Keys.ShiftLeft, - - # Tmux sends following keystrokes when control+arrow is pressed, but for - # Emacs ansi-term sends the same sequences for normal arrow keys. Consider - # it a normal arrow press, because that's more important. - '\x1bOA': Keys.Up, - '\x1bOB': Keys.Down, - '\x1bOC': Keys.Right, - '\x1bOD': Keys.Left, - + '\x1b[1;2A': Keys.ShiftUp, + '\x1b[1;2B': Keys.ShiftDown, + '\x1b[1;2C': Keys.ShiftRight, + '\x1b[1;2D': Keys.ShiftLeft, + + # Tmux sends following keystrokes when control+arrow is pressed, but for + # Emacs ansi-term sends the same sequences for normal arrow keys. Consider + # it a normal arrow press, because that's more important. + '\x1bOA': Keys.Up, + '\x1bOB': Keys.Down, + '\x1bOC': Keys.Right, + '\x1bOD': Keys.Left, + '\x1b[5A': Keys.ControlUp, '\x1b[5B': Keys.ControlDown, '\x1b[5C': Keys.ControlRight, @@ -188,11 +188,11 @@ ANSI_SEQUENCES = { '\x1b[1;3C': (Keys.Escape, Keys.Right), '\x1b[1;3A': (Keys.Escape, Keys.Up), '\x1b[1;3B': (Keys.Escape, Keys.Down), - - # Sequences generated by numpad 5. Not sure what it means. (It doesn't - # appear in 'infocmp'. Just ignore. - '\x1b[E': Keys.Ignore, # Xterm. - '\x1b[G': Keys.Ignore, # Linux console. + + # Sequences generated by numpad 5. Not sure what it means. (It doesn't + # appear in 'infocmp'. Just ignore. + '\x1b[E': Keys.Ignore, # Xterm. + '\x1b[G': Keys.Ignore, # Linux console. } @@ -367,11 +367,11 @@ class InputStream(object): # Quit bracketed paste mode and handle remaining input. self._in_bracketed_paste = False - remaining = self._paste_buffer[end_index + len(end_mark):] + remaining = self._paste_buffer[end_index + len(end_mark):] self._paste_buffer = '' - self.feed(remaining) - + self.feed(remaining) + # Handle normal input character by character. else: for i, c in enumerate(data): @@ -383,16 +383,16 @@ class InputStream(object): else: # Replace \r by \n. (Some clients send \r instead of \n # when enter is pressed. E.g. telnet and some other - # terminals.) - - # XXX: We should remove this in a future version. It *is* - # now possible to recognise the difference. - # (We remove ICRNL/INLCR/IGNCR below.) - # However, this breaks IPython and maybe other applications, - # because they bind ControlJ (\n) for handling the Enter key. - - # When this is removed, replace Enter=ControlJ by - # Enter=ControlM in keys.py. + # terminals.) + + # XXX: We should remove this in a future version. It *is* + # now possible to recognise the difference. + # (We remove ICRNL/INLCR/IGNCR below.) + # However, this breaks IPython and maybe other applications, + # because they bind ControlJ (\n) for handling the Enter key. + + # When this is removed, replace Enter=ControlJ by + # Enter=ControlM in keys.py. if c == '\r': c = '\n' self._input_parser.send(c) @@ -425,40 +425,40 @@ class raw_mode(object): with raw_mode(stdin): ''' the pseudo-terminal stdin is now used in raw mode ''' - - We ignore errors when executing `tcgetattr` fails. + + We ignore errors when executing `tcgetattr` fails. """ - # There are several reasons for ignoring errors: - # 1. To avoid the "Inappropriate ioctl for device" crash if somebody would - # execute this code (In a Python REPL, for instance): - # - # import os; f = open(os.devnull); os.dup2(f.fileno(), 0) - # - # The result is that the eventloop will stop correctly, because it has - # to logic to quit when stdin is closed. However, we should not fail at - # this point. See: - # https://github.com/jonathanslenders/python-prompt-toolkit/pull/393 - # https://github.com/jonathanslenders/python-prompt-toolkit/issues/392 - - # 2. Related, when stdin is an SSH pipe, and no full terminal was allocated. - # See: https://github.com/jonathanslenders/python-prompt-toolkit/pull/165 + # There are several reasons for ignoring errors: + # 1. To avoid the "Inappropriate ioctl for device" crash if somebody would + # execute this code (In a Python REPL, for instance): + # + # import os; f = open(os.devnull); os.dup2(f.fileno(), 0) + # + # The result is that the eventloop will stop correctly, because it has + # to logic to quit when stdin is closed. However, we should not fail at + # this point. See: + # https://github.com/jonathanslenders/python-prompt-toolkit/pull/393 + # https://github.com/jonathanslenders/python-prompt-toolkit/issues/392 + + # 2. Related, when stdin is an SSH pipe, and no full terminal was allocated. + # See: https://github.com/jonathanslenders/python-prompt-toolkit/pull/165 def __init__(self, fileno): self.fileno = fileno - try: - self.attrs_before = termios.tcgetattr(fileno) - except termios.error: - # Ignore attribute errors. - self.attrs_before = None + try: + self.attrs_before = termios.tcgetattr(fileno) + except termios.error: + # Ignore attribute errors. + self.attrs_before = None def __enter__(self): # NOTE: On os X systems, using pty.setraw() fails. Therefor we are using this: - try: - newattr = termios.tcgetattr(self.fileno) - except termios.error: - pass - else: - newattr[tty.LFLAG] = self._patch_lflag(newattr[tty.LFLAG]) - newattr[tty.IFLAG] = self._patch_iflag(newattr[tty.IFLAG]) + try: + newattr = termios.tcgetattr(self.fileno) + except termios.error: + pass + else: + newattr[tty.LFLAG] = self._patch_lflag(newattr[tty.LFLAG]) + newattr[tty.IFLAG] = self._patch_iflag(newattr[tty.IFLAG]) # VMIN defines the number of characters read at a time in # non-canonical mode. It seems to default to 1 on Linux, but on @@ -467,54 +467,54 @@ class raw_mode(object): # defaults to ASCII EOT = Ctrl-D = 4.) newattr[tty.CC][termios.VMIN] = 1 - termios.tcsetattr(self.fileno, termios.TCSANOW, newattr) + termios.tcsetattr(self.fileno, termios.TCSANOW, newattr) - # Put the terminal in cursor mode. (Instead of application mode.) - os.write(self.fileno, b'\x1b[?1l') + # Put the terminal in cursor mode. (Instead of application mode.) + os.write(self.fileno, b'\x1b[?1l') - @classmethod - def _patch_lflag(cls, attrs): + @classmethod + def _patch_lflag(cls, attrs): return attrs & ~(termios.ECHO | termios.ICANON | termios.IEXTEN | termios.ISIG) - @classmethod - def _patch_iflag(cls, attrs): - return attrs & ~( - # Disable XON/XOFF flow control on output and input. - # (Don't capture Ctrl-S and Ctrl-Q.) - # Like executing: "stty -ixon." - termios.IXON | termios.IXOFF | - - # Don't translate carriage return into newline on input. - termios.ICRNL | termios.INLCR | termios.IGNCR - ) - + @classmethod + def _patch_iflag(cls, attrs): + return attrs & ~( + # Disable XON/XOFF flow control on output and input. + # (Don't capture Ctrl-S and Ctrl-Q.) + # Like executing: "stty -ixon." + termios.IXON | termios.IXOFF | + + # Don't translate carriage return into newline on input. + termios.ICRNL | termios.INLCR | termios.IGNCR + ) + def __exit__(self, *a, **kw): - if self.attrs_before is not None: - try: - termios.tcsetattr(self.fileno, termios.TCSANOW, self.attrs_before) - except termios.error: - pass + if self.attrs_before is not None: + try: + termios.tcsetattr(self.fileno, termios.TCSANOW, self.attrs_before) + except termios.error: + pass - # # Put the terminal in application mode. - # self._stdout.write('\x1b[?1h') + # # Put the terminal in application mode. + # self._stdout.write('\x1b[?1h') class cooked_mode(raw_mode): """ - The opposide of ``raw_mode``, used when we need cooked mode inside a - `raw_mode` block. Used in `CommandLineInterface.run_in_terminal`.:: + The opposide of ``raw_mode``, used when we need cooked mode inside a + `raw_mode` block. Used in `CommandLineInterface.run_in_terminal`.:: with cooked_mode(stdin): ''' the pseudo-terminal stdin is now used in cooked mode. ''' """ - @classmethod - def _patch_lflag(cls, attrs): + @classmethod + def _patch_lflag(cls, attrs): return attrs | (termios.ECHO | termios.ICANON | termios.IEXTEN | termios.ISIG) - - @classmethod - def _patch_iflag(cls, attrs): - # Turn the ICRNL flag back on. (Without this, calling `input()` in - # run_in_terminal doesn't work and displays ^M instead. Ptpython - # evaluates commands using `run_in_terminal`, so it's important that - # they translate ^M back into ^J.) - return attrs | termios.ICRNL + + @classmethod + def _patch_iflag(cls, attrs): + # Turn the ICRNL flag back on. (Without this, calling `input()` in + # run_in_terminal doesn't work and displays ^M instead. Ptpython + # evaluates commands using `run_in_terminal`, so it's important that + # they translate ^M back into ^J.) + return attrs | termios.ICRNL diff --git a/contrib/python/prompt-toolkit/py2/prompt_toolkit/terminal/vt100_output.py b/contrib/python/prompt-toolkit/py2/prompt_toolkit/terminal/vt100_output.py index b800aaacec..f9ebbcbb24 100644 --- a/contrib/python/prompt-toolkit/py2/prompt_toolkit/terminal/vt100_output.py +++ b/contrib/python/prompt-toolkit/py2/prompt_toolkit/terminal/vt100_output.py @@ -1,22 +1,22 @@ -""" -Output for vt100 terminals. - -A lot of thanks, regarding outputting of colors, goes to the Pygments project: -(We don't rely on Pygments anymore, because many things are very custom, and -everything has been highly optimized.) -http://pygments.org/ -""" +""" +Output for vt100 terminals. + +A lot of thanks, regarding outputting of colors, goes to the Pygments project: +(We don't rely on Pygments anymore, because many things are very custom, and +everything has been highly optimized.) +http://pygments.org/ +""" from __future__ import unicode_literals -from prompt_toolkit.filters import to_simple_filter, Condition +from prompt_toolkit.filters import to_simple_filter, Condition from prompt_toolkit.layout.screen import Size from prompt_toolkit.renderer import Output from prompt_toolkit.styles import ANSI_COLOR_NAMES -from six.moves import range +from six.moves import range import array import errno -import os +import os import six __all__ = ( @@ -25,219 +25,219 @@ __all__ = ( FG_ANSI_COLORS = { - 'ansidefault': 39, + 'ansidefault': 39, # Low intensity. 'ansiblack': 30, - 'ansidarkred': 31, - 'ansidarkgreen': 32, - 'ansibrown': 33, - 'ansidarkblue': 34, - 'ansipurple': 35, - 'ansiteal': 36, + 'ansidarkred': 31, + 'ansidarkgreen': 32, + 'ansibrown': 33, + 'ansidarkblue': 34, + 'ansipurple': 35, + 'ansiteal': 36, 'ansilightgray': 37, # High intensity. 'ansidarkgray': 90, - 'ansired': 91, - 'ansigreen': 92, - 'ansiyellow': 93, - 'ansiblue': 94, - 'ansifuchsia': 95, - 'ansiturquoise': 96, + 'ansired': 91, + 'ansigreen': 92, + 'ansiyellow': 93, + 'ansiblue': 94, + 'ansifuchsia': 95, + 'ansiturquoise': 96, 'ansiwhite': 97, } BG_ANSI_COLORS = { - 'ansidefault': 49, + 'ansidefault': 49, # Low intensity. 'ansiblack': 40, - 'ansidarkred': 41, - 'ansidarkgreen': 42, - 'ansibrown': 43, - 'ansidarkblue': 44, - 'ansipurple': 45, - 'ansiteal': 46, + 'ansidarkred': 41, + 'ansidarkgreen': 42, + 'ansibrown': 43, + 'ansidarkblue': 44, + 'ansipurple': 45, + 'ansiteal': 46, 'ansilightgray': 47, # High intensity. 'ansidarkgray': 100, - 'ansired': 101, - 'ansigreen': 102, - 'ansiyellow': 103, - 'ansiblue': 104, - 'ansifuchsia': 105, - 'ansiturquoise': 106, + 'ansired': 101, + 'ansigreen': 102, + 'ansiyellow': 103, + 'ansiblue': 104, + 'ansifuchsia': 105, + 'ansiturquoise': 106, 'ansiwhite': 107, } - -ANSI_COLORS_TO_RGB = { - 'ansidefault': (0x00, 0x00, 0x00), # Don't use, 'default' doesn't really have a value. - 'ansiblack': (0x00, 0x00, 0x00), - 'ansidarkgray': (0x7f, 0x7f, 0x7f), - 'ansiwhite': (0xff, 0xff, 0xff), - 'ansilightgray': (0xe5, 0xe5, 0xe5), - - # Low intensity. - 'ansidarkred': (0xcd, 0x00, 0x00), - 'ansidarkgreen': (0x00, 0xcd, 0x00), - 'ansibrown': (0xcd, 0xcd, 0x00), - 'ansidarkblue': (0x00, 0x00, 0xcd), - 'ansipurple': (0xcd, 0x00, 0xcd), - 'ansiteal': (0x00, 0xcd, 0xcd), - - # High intensity. - 'ansired': (0xff, 0x00, 0x00), - 'ansigreen': (0x00, 0xff, 0x00), - 'ansiyellow': (0xff, 0xff, 0x00), - 'ansiblue': (0x00, 0x00, 0xff), - 'ansifuchsia': (0xff, 0x00, 0xff), - 'ansiturquoise': (0x00, 0xff, 0xff), -} - - + +ANSI_COLORS_TO_RGB = { + 'ansidefault': (0x00, 0x00, 0x00), # Don't use, 'default' doesn't really have a value. + 'ansiblack': (0x00, 0x00, 0x00), + 'ansidarkgray': (0x7f, 0x7f, 0x7f), + 'ansiwhite': (0xff, 0xff, 0xff), + 'ansilightgray': (0xe5, 0xe5, 0xe5), + + # Low intensity. + 'ansidarkred': (0xcd, 0x00, 0x00), + 'ansidarkgreen': (0x00, 0xcd, 0x00), + 'ansibrown': (0xcd, 0xcd, 0x00), + 'ansidarkblue': (0x00, 0x00, 0xcd), + 'ansipurple': (0xcd, 0x00, 0xcd), + 'ansiteal': (0x00, 0xcd, 0xcd), + + # High intensity. + 'ansired': (0xff, 0x00, 0x00), + 'ansigreen': (0x00, 0xff, 0x00), + 'ansiyellow': (0xff, 0xff, 0x00), + 'ansiblue': (0x00, 0x00, 0xff), + 'ansifuchsia': (0xff, 0x00, 0xff), + 'ansiturquoise': (0x00, 0xff, 0xff), +} + + assert set(FG_ANSI_COLORS) == set(ANSI_COLOR_NAMES) assert set(BG_ANSI_COLORS) == set(ANSI_COLOR_NAMES) -assert set(ANSI_COLORS_TO_RGB) == set(ANSI_COLOR_NAMES) - - -def _get_closest_ansi_color(r, g, b, exclude=()): - """ - Find closest ANSI color. Return it by name. - - :param r: Red (Between 0 and 255.) - :param g: Green (Between 0 and 255.) - :param b: Blue (Between 0 and 255.) - :param exclude: A tuple of color names to exclude. (E.g. ``('ansired', )``.) - """ - assert isinstance(exclude, tuple) - - # When we have a bit of saturation, avoid the gray-like colors, otherwise, - # too often the distance to the gray color is less. - saturation = abs(r - g) + abs(g - b) + abs(b - r) # Between 0..510 - - if saturation > 30: - exclude += ('ansilightgray', 'ansidarkgray', 'ansiwhite', 'ansiblack') - - # Take the closest color. - # (Thanks to Pygments for this part.) - distance = 257*257*3 # "infinity" (>distance from #000000 to #ffffff) - match = 'ansidefault' - - for name, (r2, g2, b2) in ANSI_COLORS_TO_RGB.items(): - if name != 'ansidefault' and name not in exclude: - d = (r - r2) ** 2 + (g - g2) ** 2 + (b - b2) ** 2 - - if d < distance: - match = name - distance = d - - return match - - -class _16ColorCache(dict): - """ - Cache which maps (r, g, b) tuples to 16 ansi colors. - - :param bg: Cache for background colors, instead of foreground. - """ - def __init__(self, bg=False): - assert isinstance(bg, bool) - self.bg = bg - - def get_code(self, value, exclude=()): - """ - Return a (ansi_code, ansi_name) tuple. (E.g. ``(44, 'ansiblue')``.) for - a given (r,g,b) value. - """ - key = (value, exclude) - if key not in self: - self[key] = self._get(value, exclude) - return self[key] - - def _get(self, value, exclude=()): - r, g, b = value - match = _get_closest_ansi_color(r, g, b, exclude=exclude) - - # Turn color name into code. - if self.bg: - code = BG_ANSI_COLORS[match] - else: - code = FG_ANSI_COLORS[match] - - self[value] = code - return code, match - - -class _256ColorCache(dict): - """ - Cach which maps (r, g, b) tuples to 256 colors. - """ - def __init__(self): - # Build color table. - colors = [] - - # colors 0..15: 16 basic colors - colors.append((0x00, 0x00, 0x00)) # 0 - colors.append((0xcd, 0x00, 0x00)) # 1 - colors.append((0x00, 0xcd, 0x00)) # 2 - colors.append((0xcd, 0xcd, 0x00)) # 3 - colors.append((0x00, 0x00, 0xee)) # 4 - colors.append((0xcd, 0x00, 0xcd)) # 5 - colors.append((0x00, 0xcd, 0xcd)) # 6 - colors.append((0xe5, 0xe5, 0xe5)) # 7 - colors.append((0x7f, 0x7f, 0x7f)) # 8 - colors.append((0xff, 0x00, 0x00)) # 9 - colors.append((0x00, 0xff, 0x00)) # 10 - colors.append((0xff, 0xff, 0x00)) # 11 - colors.append((0x5c, 0x5c, 0xff)) # 12 - colors.append((0xff, 0x00, 0xff)) # 13 - colors.append((0x00, 0xff, 0xff)) # 14 - colors.append((0xff, 0xff, 0xff)) # 15 - - # colors 16..232: the 6x6x6 color cube - valuerange = (0x00, 0x5f, 0x87, 0xaf, 0xd7, 0xff) - - for i in range(217): - r = valuerange[(i // 36) % 6] - g = valuerange[(i // 6) % 6] - b = valuerange[i % 6] - colors.append((r, g, b)) - - # colors 233..253: grayscale - for i in range(1, 22): - v = 8 + i * 10 - colors.append((v, v, v)) - - self.colors = colors - - def __missing__(self, value): - r, g, b = value - - # Find closest color. - # (Thanks to Pygments for this!) - distance = 257*257*3 # "infinity" (>distance from #000000 to #ffffff) - match = 0 - - for i, (r2, g2, b2) in enumerate(self.colors): - d = (r - r2) ** 2 + (g - g2) ** 2 + (b - b2) ** 2 - - if d < distance: - match = i - distance = d - - # Turn color name into code. - self[value] = match - return match - - -_16_fg_colors = _16ColorCache(bg=False) -_16_bg_colors = _16ColorCache(bg=True) -_256_colors = _256ColorCache() - - +assert set(ANSI_COLORS_TO_RGB) == set(ANSI_COLOR_NAMES) + + +def _get_closest_ansi_color(r, g, b, exclude=()): + """ + Find closest ANSI color. Return it by name. + + :param r: Red (Between 0 and 255.) + :param g: Green (Between 0 and 255.) + :param b: Blue (Between 0 and 255.) + :param exclude: A tuple of color names to exclude. (E.g. ``('ansired', )``.) + """ + assert isinstance(exclude, tuple) + + # When we have a bit of saturation, avoid the gray-like colors, otherwise, + # too often the distance to the gray color is less. + saturation = abs(r - g) + abs(g - b) + abs(b - r) # Between 0..510 + + if saturation > 30: + exclude += ('ansilightgray', 'ansidarkgray', 'ansiwhite', 'ansiblack') + + # Take the closest color. + # (Thanks to Pygments for this part.) + distance = 257*257*3 # "infinity" (>distance from #000000 to #ffffff) + match = 'ansidefault' + + for name, (r2, g2, b2) in ANSI_COLORS_TO_RGB.items(): + if name != 'ansidefault' and name not in exclude: + d = (r - r2) ** 2 + (g - g2) ** 2 + (b - b2) ** 2 + + if d < distance: + match = name + distance = d + + return match + + +class _16ColorCache(dict): + """ + Cache which maps (r, g, b) tuples to 16 ansi colors. + + :param bg: Cache for background colors, instead of foreground. + """ + def __init__(self, bg=False): + assert isinstance(bg, bool) + self.bg = bg + + def get_code(self, value, exclude=()): + """ + Return a (ansi_code, ansi_name) tuple. (E.g. ``(44, 'ansiblue')``.) for + a given (r,g,b) value. + """ + key = (value, exclude) + if key not in self: + self[key] = self._get(value, exclude) + return self[key] + + def _get(self, value, exclude=()): + r, g, b = value + match = _get_closest_ansi_color(r, g, b, exclude=exclude) + + # Turn color name into code. + if self.bg: + code = BG_ANSI_COLORS[match] + else: + code = FG_ANSI_COLORS[match] + + self[value] = code + return code, match + + +class _256ColorCache(dict): + """ + Cach which maps (r, g, b) tuples to 256 colors. + """ + def __init__(self): + # Build color table. + colors = [] + + # colors 0..15: 16 basic colors + colors.append((0x00, 0x00, 0x00)) # 0 + colors.append((0xcd, 0x00, 0x00)) # 1 + colors.append((0x00, 0xcd, 0x00)) # 2 + colors.append((0xcd, 0xcd, 0x00)) # 3 + colors.append((0x00, 0x00, 0xee)) # 4 + colors.append((0xcd, 0x00, 0xcd)) # 5 + colors.append((0x00, 0xcd, 0xcd)) # 6 + colors.append((0xe5, 0xe5, 0xe5)) # 7 + colors.append((0x7f, 0x7f, 0x7f)) # 8 + colors.append((0xff, 0x00, 0x00)) # 9 + colors.append((0x00, 0xff, 0x00)) # 10 + colors.append((0xff, 0xff, 0x00)) # 11 + colors.append((0x5c, 0x5c, 0xff)) # 12 + colors.append((0xff, 0x00, 0xff)) # 13 + colors.append((0x00, 0xff, 0xff)) # 14 + colors.append((0xff, 0xff, 0xff)) # 15 + + # colors 16..232: the 6x6x6 color cube + valuerange = (0x00, 0x5f, 0x87, 0xaf, 0xd7, 0xff) + + for i in range(217): + r = valuerange[(i // 36) % 6] + g = valuerange[(i // 6) % 6] + b = valuerange[i % 6] + colors.append((r, g, b)) + + # colors 233..253: grayscale + for i in range(1, 22): + v = 8 + i * 10 + colors.append((v, v, v)) + + self.colors = colors + + def __missing__(self, value): + r, g, b = value + + # Find closest color. + # (Thanks to Pygments for this!) + distance = 257*257*3 # "infinity" (>distance from #000000 to #ffffff) + match = 0 + + for i, (r2, g2, b2) in enumerate(self.colors): + d = (r - r2) ** 2 + (g - g2) ** 2 + (b - b2) ** 2 + + if d < distance: + match = i + distance = d + + # Turn color name into code. + self[value] = match + return match + + +_16_fg_colors = _16ColorCache(bg=False) +_16_bg_colors = _16ColorCache(bg=True) +_256_colors = _256ColorCache() + + class _EscapeCodeCache(dict): """ Cache for VT100 escape codes. It maps @@ -245,17 +245,17 @@ class _EscapeCodeCache(dict): :param true_color: When True, use 24bit colors instead of 256 colors. """ - def __init__(self, true_color=False, ansi_colors_only=False): + def __init__(self, true_color=False, ansi_colors_only=False): assert isinstance(true_color, bool) self.true_color = true_color - self.ansi_colors_only = to_simple_filter(ansi_colors_only) + self.ansi_colors_only = to_simple_filter(ansi_colors_only) def __missing__(self, attrs): fgcolor, bgcolor, bold, underline, italic, blink, reverse = attrs parts = [] - parts.extend(self._colors_to_code(fgcolor, bgcolor)) - + parts.extend(self._colors_to_code(fgcolor, bgcolor)) + if bold: parts.append('1') if italic: @@ -275,72 +275,72 @@ class _EscapeCodeCache(dict): self[attrs] = result return result - def _color_name_to_rgb(self, color): - " Turn 'ffffff', into (0xff, 0xff, 0xff). " - try: - rgb = int(color, 16) - except ValueError: - raise - else: + def _color_name_to_rgb(self, color): + " Turn 'ffffff', into (0xff, 0xff, 0xff). " + try: + rgb = int(color, 16) + except ValueError: + raise + else: r = (rgb >> 16) & 0xff g = (rgb >> 8) & 0xff b = rgb & 0xff - return r, g, b - - def _colors_to_code(self, fg_color, bg_color): - " Return a tuple with the vt100 values that represent this color. " - # When requesting ANSI colors only, and both fg/bg color were converted - # to ANSI, ensure that the foreground and background color are not the - # same. (Unless they were explicitely defined to be the same color.) - fg_ansi = [()] - - def get(color, bg): - table = BG_ANSI_COLORS if bg else FG_ANSI_COLORS - - if color is None: - return () - - # 16 ANSI colors. (Given by name.) - elif color in table: - return (table[color], ) - - # RGB colors. (Defined as 'ffffff'.) - else: - try: - rgb = self._color_name_to_rgb(color) - except ValueError: - return () - - # When only 16 colors are supported, use that. - if self.ansi_colors_only(): - if bg: # Background. - if fg_color != bg_color: - exclude = (fg_ansi[0], ) - else: - exclude = () - code, name = _16_bg_colors.get_code(rgb, exclude=exclude) - return (code, ) - else: # Foreground. - code, name = _16_fg_colors.get_code(rgb) - fg_ansi[0] = name - return (code, ) - - # True colors. (Only when this feature is enabled.) - elif self.true_color: - r, g, b = rgb - return (48 if bg else 38, 2, r, g, b) - - # 256 RGB colors. - else: - return (48 if bg else 38, 5, _256_colors[rgb]) - - result = [] - result.extend(get(fg_color, False)) - result.extend(get(bg_color, True)) - - return map(six.text_type, result) - - + return r, g, b + + def _colors_to_code(self, fg_color, bg_color): + " Return a tuple with the vt100 values that represent this color. " + # When requesting ANSI colors only, and both fg/bg color were converted + # to ANSI, ensure that the foreground and background color are not the + # same. (Unless they were explicitely defined to be the same color.) + fg_ansi = [()] + + def get(color, bg): + table = BG_ANSI_COLORS if bg else FG_ANSI_COLORS + + if color is None: + return () + + # 16 ANSI colors. (Given by name.) + elif color in table: + return (table[color], ) + + # RGB colors. (Defined as 'ffffff'.) + else: + try: + rgb = self._color_name_to_rgb(color) + except ValueError: + return () + + # When only 16 colors are supported, use that. + if self.ansi_colors_only(): + if bg: # Background. + if fg_color != bg_color: + exclude = (fg_ansi[0], ) + else: + exclude = () + code, name = _16_bg_colors.get_code(rgb, exclude=exclude) + return (code, ) + else: # Foreground. + code, name = _16_fg_colors.get_code(rgb) + fg_ansi[0] = name + return (code, ) + + # True colors. (Only when this feature is enabled.) + elif self.true_color: + r, g, b = rgb + return (48 if bg else 38, 2, r, g, b) + + # 256 RGB colors. + else: + return (48 if bg else 38, 5, _256_colors[rgb]) + + result = [] + result.extend(get(fg_color, False)) + result.extend(get(bg_color, True)) + + return map(six.text_type, result) + + def _get_size(fileno): # Thanks to fabric (fabfile.org), and # http://sqizit.bartletts.id.au/2011/02/14/pseudo-terminals-in-python/ @@ -356,13 +356,13 @@ def _get_size(fileno): import termios # Buffer for the C call - buf = array.array(b'h' if six.PY2 else u'h', [0, 0, 0, 0]) + buf = array.array(b'h' if six.PY2 else u'h', [0, 0, 0, 0]) # Do TIOCGWINSZ (Get) - # Note: We should not pass 'True' as a fourth parameter to 'ioctl'. (True - # is the default.) This causes segmentation faults on some systems. - # See: https://github.com/jonathanslenders/python-prompt-toolkit/pull/364 - fcntl.ioctl(fileno, termios.TIOCGWINSZ, buf) + # Note: We should not pass 'True' as a fourth parameter to 'ioctl'. (True + # is the default.) This causes segmentation faults on some systems. + # See: https://github.com/jonathanslenders/python-prompt-toolkit/pull/364 + fcntl.ioctl(fileno, termios.TIOCGWINSZ, buf) # Return rows, cols return buf[0], buf[1] @@ -371,74 +371,74 @@ def _get_size(fileno): class Vt100_Output(Output): """ :param get_size: A callable which returns the `Size` of the output terminal. - :param stdout: Any object with has a `write` and `flush` method + an 'encoding' property. + :param stdout: Any object with has a `write` and `flush` method + an 'encoding' property. :param true_color: Use 24bit color instead of 256 colors. (Can be a :class:`SimpleFilter`.) - When `ansi_colors_only` is set, only 16 colors are used. - :param ansi_colors_only: Restrict to 16 ANSI colors only. - :param term: The terminal environment variable. (xterm, xterm-256color, linux, ...) - :param write_binary: Encode the output before writing it. If `True` (the - default), the `stdout` object is supposed to expose an `encoding` attribute. + When `ansi_colors_only` is set, only 16 colors are used. + :param ansi_colors_only: Restrict to 16 ANSI colors only. + :param term: The terminal environment variable. (xterm, xterm-256color, linux, ...) + :param write_binary: Encode the output before writing it. If `True` (the + default), the `stdout` object is supposed to expose an `encoding` attribute. """ - def __init__(self, stdout, get_size, true_color=False, - ansi_colors_only=None, term=None, write_binary=True): - assert callable(get_size) - assert term is None or isinstance(term, six.text_type) - assert all(hasattr(stdout, a) for a in ('write', 'flush')) - - if write_binary: - assert hasattr(stdout, 'encoding') - + def __init__(self, stdout, get_size, true_color=False, + ansi_colors_only=None, term=None, write_binary=True): + assert callable(get_size) + assert term is None or isinstance(term, six.text_type) + assert all(hasattr(stdout, a) for a in ('write', 'flush')) + + if write_binary: + assert hasattr(stdout, 'encoding') + self._buffer = [] self.stdout = stdout - self.write_binary = write_binary + self.write_binary = write_binary self.get_size = get_size self.true_color = to_simple_filter(true_color) - self.term = term or 'xterm' - - # ANSI colors only? - if ansi_colors_only is None: - # When not given, use the following default. - ANSI_COLORS_ONLY = bool(os.environ.get( - 'PROMPT_TOOLKIT_ANSI_COLORS_ONLY', False)) - - @Condition - def ansi_colors_only(): - return ANSI_COLORS_ONLY or term in ('linux', 'eterm-color') - else: - ansi_colors_only = to_simple_filter(ansi_colors_only) - - self.ansi_colors_only = ansi_colors_only - - # Cache for escape codes. - self._escape_code_cache = _EscapeCodeCache(ansi_colors_only=ansi_colors_only) - self._escape_code_cache_true_color = _EscapeCodeCache( - true_color=True, ansi_colors_only=ansi_colors_only) - + self.term = term or 'xterm' + + # ANSI colors only? + if ansi_colors_only is None: + # When not given, use the following default. + ANSI_COLORS_ONLY = bool(os.environ.get( + 'PROMPT_TOOLKIT_ANSI_COLORS_ONLY', False)) + + @Condition + def ansi_colors_only(): + return ANSI_COLORS_ONLY or term in ('linux', 'eterm-color') + else: + ansi_colors_only = to_simple_filter(ansi_colors_only) + + self.ansi_colors_only = ansi_colors_only + + # Cache for escape codes. + self._escape_code_cache = _EscapeCodeCache(ansi_colors_only=ansi_colors_only) + self._escape_code_cache_true_color = _EscapeCodeCache( + true_color=True, ansi_colors_only=ansi_colors_only) + @classmethod - def from_pty(cls, stdout, true_color=False, ansi_colors_only=None, term=None): + def from_pty(cls, stdout, true_color=False, ansi_colors_only=None, term=None): """ Create an Output class from a pseudo terminal. (This will take the dimensions by reading the pseudo terminal attributes.) """ - assert stdout.isatty() + assert stdout.isatty() def get_size(): rows, columns = _get_size(stdout.fileno()) # If terminal (incorrectly) reports its size as 0, pick a reasonable default. # See https://github.com/ipython/ipython/issues/10071 return Size(rows=(rows or 24), columns=(columns or 80)) - return cls(stdout, get_size, true_color=true_color, - ansi_colors_only=ansi_colors_only, term=term) - - def fileno(self): - " Return file descriptor. " - return self.stdout.fileno() - - def encoding(self): - " Return encoding used for stdout. " - return self.stdout.encoding - + return cls(stdout, get_size, true_color=true_color, + ansi_colors_only=ansi_colors_only, term=term) + + def fileno(self): + " Return file descriptor. " + return self.stdout.fileno() + + def encoding(self): + " Return encoding used for stdout. " + return self.stdout.encoding + def write_raw(self, data): """ Write raw data to output. @@ -456,8 +456,8 @@ class Vt100_Output(Output): """ Set terminal title. """ - if self.term not in ('linux', 'eterm-color'): # Not supported by the Linux console. - self.write_raw('\x1b]2;%s\x07' % title.replace('\x1b', '').replace('\x07', '')) + if self.term not in ('linux', 'eterm-color'): # Not supported by the Linux console. + self.write_raw('\x1b]2;%s\x07' % title.replace('\x1b', '').replace('\x07', '')) def clear_title(self): self.set_title('') @@ -514,10 +514,10 @@ class Vt100_Output(Output): :param attrs: `Attrs` instance. """ - if self.true_color() and not self.ansi_colors_only(): - self.write_raw(self._escape_code_cache_true_color[attrs]) + if self.true_color() and not self.ansi_colors_only(): + self.write_raw(self._escape_code_cache_true_color[attrs]) else: - self.write_raw(self._escape_code_cache[attrs]) + self.write_raw(self._escape_code_cache[attrs]) def disable_autowrap(self): self.write_raw('\x1b[?7l') @@ -537,7 +537,7 @@ class Vt100_Output(Output): def cursor_up(self, amount): if amount == 0: - pass + pass elif amount == 1: self.write_raw('\x1b[A') else: @@ -545,7 +545,7 @@ class Vt100_Output(Output): def cursor_down(self, amount): if amount == 0: - pass + pass elif amount == 1: # Note: Not the same as '\n', '\n' can cause the window content to # scroll. @@ -555,7 +555,7 @@ class Vt100_Output(Output): def cursor_forward(self, amount): if amount == 0: - pass + pass elif amount == 1: self.write_raw('\x1b[C') else: @@ -563,7 +563,7 @@ class Vt100_Output(Output): def cursor_backward(self, amount): if amount == 0: - pass + pass elif amount == 1: self.write_raw('\b') # '\x1b[D' else: @@ -590,11 +590,11 @@ class Vt100_Output(Output): # UnicodeEncodeError crashes. E.g. u'\xb7' does not appear in 'ascii'.) # My Arch Linux installation of july 2015 reported 'ANSI_X3.4-1968' # for sys.stdout.encoding in xterm. - if self.write_binary: - if hasattr(self.stdout, 'buffer'): - out = self.stdout.buffer # Py3. - else: - out = self.stdout + if self.write_binary: + if hasattr(self.stdout, 'buffer'): + out = self.stdout.buffer # Py3. + else: + out = self.stdout out.write(data.encode(self.stdout.encoding or 'utf-8', 'replace')) else: self.stdout.write(data) diff --git a/contrib/python/prompt-toolkit/py2/prompt_toolkit/terminal/win32_input.py b/contrib/python/prompt-toolkit/py2/prompt_toolkit/terminal/win32_input.py index 410e5fa517..74a7decd61 100644 --- a/contrib/python/prompt-toolkit/py2/prompt_toolkit/terminal/win32_input.py +++ b/contrib/python/prompt-toolkit/py2/prompt_toolkit/terminal/win32_input.py @@ -1,18 +1,18 @@ -from __future__ import unicode_literals +from __future__ import unicode_literals from ctypes import windll, pointer from ctypes.wintypes import DWORD, HANDLE -from six.moves import range +from six.moves import range from prompt_toolkit.key_binding.input_processor import KeyPress from prompt_toolkit.keys import Keys -from prompt_toolkit.mouse_events import MouseEventType +from prompt_toolkit.mouse_events import MouseEventType from prompt_toolkit.win32_types import EventTypes, KEY_EVENT_RECORD, MOUSE_EVENT_RECORD, INPUT_RECORD, STD_INPUT_HANDLE -import msvcrt -import os -import sys -import six - +import msvcrt +import os +import sys +import six + __all__ = ( 'ConsoleInputReader', 'raw_mode', @@ -21,10 +21,10 @@ __all__ = ( class ConsoleInputReader(object): - """ - :param recognize_paste: When True, try to discover paste actions and turn - the event into a BracketedPaste. - """ + """ + :param recognize_paste: When True, try to discover paste actions and turn + the event into a BracketedPaste. + """ # Keys with character data. mappings = { b'\x1b': Keys.Escape, @@ -104,70 +104,70 @@ class ConsoleInputReader(object): LEFT_CTRL_PRESSED = 0x0008 RIGHT_CTRL_PRESSED = 0x0004 - def __init__(self, recognize_paste=True): - self._fdcon = None - self.recognize_paste = recognize_paste + def __init__(self, recognize_paste=True): + self._fdcon = None + self.recognize_paste = recognize_paste - # When stdin is a tty, use that handle, otherwise, create a handle from - # CONIN$. - if sys.stdin.isatty(): + # When stdin is a tty, use that handle, otherwise, create a handle from + # CONIN$. + if sys.stdin.isatty(): self.handle = HANDLE(windll.kernel32.GetStdHandle(STD_INPUT_HANDLE)) - else: - self._fdcon = os.open('CONIN$', os.O_RDWR | os.O_BINARY) + else: + self._fdcon = os.open('CONIN$', os.O_RDWR | os.O_BINARY) self.handle = HANDLE(msvcrt.get_osfhandle(self._fdcon)) - - def close(self): - " Close fdcon. " - if self._fdcon is not None: - os.close(self._fdcon) - + + def close(self): + " Close fdcon. " + if self._fdcon is not None: + os.close(self._fdcon) + def read(self): """ - Return a list of `KeyPress` instances. It won't return anything when - there was nothing to read. (This function doesn't block.) + Return a list of `KeyPress` instances. It won't return anything when + there was nothing to read. (This function doesn't block.) http://msdn.microsoft.com/en-us/library/windows/desktop/ms684961(v=vs.85).aspx """ - max_count = 2048 # Max events to read at the same time. + max_count = 2048 # Max events to read at the same time. read = DWORD(0) arrtype = INPUT_RECORD * max_count input_records = arrtype() # Get next batch of input event. - windll.kernel32.ReadConsoleInputW( - self.handle, pointer(input_records), max_count, pointer(read)) - - # First, get all the keys from the input buffer, in order to determine - # whether we should consider this a paste event or not. - all_keys = list(self._get_keys(read, input_records)) - - if self.recognize_paste and self._is_paste(all_keys): - gen = iter(all_keys) - for k in gen: - # Pasting: if the current key consists of text or \n, turn it - # into a BracketedPaste. - data = [] - while k and (isinstance(k.key, six.text_type) or - k.key == Keys.ControlJ): - data.append(k.data) - try: - k = next(gen) - except StopIteration: - k = None - - if data: - yield KeyPress(Keys.BracketedPaste, ''.join(data)) - if k is not None: - yield k - else: - for k in all_keys: - yield k - - def _get_keys(self, read, input_records): - """ - Generator that yields `KeyPress` objects from the input records. - """ + windll.kernel32.ReadConsoleInputW( + self.handle, pointer(input_records), max_count, pointer(read)) + + # First, get all the keys from the input buffer, in order to determine + # whether we should consider this a paste event or not. + all_keys = list(self._get_keys(read, input_records)) + + if self.recognize_paste and self._is_paste(all_keys): + gen = iter(all_keys) + for k in gen: + # Pasting: if the current key consists of text or \n, turn it + # into a BracketedPaste. + data = [] + while k and (isinstance(k.key, six.text_type) or + k.key == Keys.ControlJ): + data.append(k.data) + try: + k = next(gen) + except StopIteration: + k = None + + if data: + yield KeyPress(Keys.BracketedPaste, ''.join(data)) + if k is not None: + yield k + else: + for k in all_keys: + yield k + + def _get_keys(self, read, input_records): + """ + Generator that yields `KeyPress` objects from the input records. + """ for i in range(read.value): ir = input_records[i] @@ -181,35 +181,35 @@ class ConsoleInputReader(object): # Process if this is a key event. (We also have mouse, menu and # focus events.) if type(ev) == KEY_EVENT_RECORD and ev.KeyDown: - for key_press in self._event_to_key_presses(ev): - yield key_press + for key_press in self._event_to_key_presses(ev): + yield key_press elif type(ev) == MOUSE_EVENT_RECORD: - for key_press in self._handle_mouse(ev): - yield key_press - - @staticmethod - def _is_paste(keys): - """ - Return `True` when we should consider this list of keys as a paste - event. Pasted text on windows will be turned into a - `Keys.BracketedPaste` event. (It's not 100% correct, but it is probably - the best possible way to detect pasting of text and handle that - correctly.) - """ - # Consider paste when it contains at least one newline and at least one - # other character. - text_count = 0 - newline_count = 0 - - for k in keys: - if isinstance(k.key, six.text_type): - text_count += 1 - if k.key == Keys.ControlJ: - newline_count += 1 - - return newline_count >= 1 and text_count > 1 - + for key_press in self._handle_mouse(ev): + yield key_press + + @staticmethod + def _is_paste(keys): + """ + Return `True` when we should consider this list of keys as a paste + event. Pasted text on windows will be turned into a + `Keys.BracketedPaste` event. (It's not 100% correct, but it is probably + the best possible way to detect pasting of text and handle that + correctly.) + """ + # Consider paste when it contains at least one newline and at least one + # other character. + text_count = 0 + newline_count = 0 + + for k in keys: + if isinstance(k.key, six.text_type): + text_count += 1 + if k.key == Keys.ControlJ: + newline_count += 1 + + return newline_count >= 1 and text_count > 1 + def _event_to_key_presses(self, ev): """ For this `KEY_EVENT_RECORD`, return a list of `KeyPress` instances. @@ -219,20 +219,20 @@ class ConsoleInputReader(object): result = None u_char = ev.uChar.UnicodeChar - ascii_char = u_char.encode('utf-8') - - # NOTE: We don't use `ev.uChar.AsciiChar`. That appears to be latin-1 - # encoded. See also: - # https://github.com/ipython/ipython/issues/10004 - # https://github.com/jonathanslenders/python-prompt-toolkit/issues/389 + ascii_char = u_char.encode('utf-8') + # NOTE: We don't use `ev.uChar.AsciiChar`. That appears to be latin-1 + # encoded. See also: + # https://github.com/ipython/ipython/issues/10004 + # https://github.com/jonathanslenders/python-prompt-toolkit/issues/389 + if u_char == '\x00': if ev.VirtualKeyCode in self.keycodes: result = KeyPress(self.keycodes[ev.VirtualKeyCode], '') else: if ascii_char in self.mappings: - if self.mappings[ascii_char] == Keys.ControlJ: - u_char = '\n' # Windows sends \n, turn into \r for unix compatibility. + if self.mappings[ascii_char] == Keys.ControlJ: + u_char = '\n' # Windows sends \n, turn into \r for unix compatibility. result = KeyPress(self.mappings[ascii_char], u_char) else: result = KeyPress(u_char, u_char) @@ -299,7 +299,7 @@ class ConsoleInputReader(object): # Check event type. if ev.ButtonState == FROM_LEFT_1ST_BUTTON_PRESSED: # On a key press, generate both the mouse down and up event. - for event_type in [MouseEventType.MOUSE_DOWN, MouseEventType.MOUSE_UP]: + for event_type in [MouseEventType.MOUSE_DOWN, MouseEventType.MOUSE_UP]: data = ';'.join([ event_type, str(ev.MousePosition.X), diff --git a/contrib/python/prompt-toolkit/py2/prompt_toolkit/terminal/win32_output.py b/contrib/python/prompt-toolkit/py2/prompt_toolkit/terminal/win32_output.py index d4dddbab42..577c61c130 100644 --- a/contrib/python/prompt-toolkit/py2/prompt_toolkit/terminal/win32_output.py +++ b/contrib/python/prompt-toolkit/py2/prompt_toolkit/terminal/win32_output.py @@ -7,7 +7,7 @@ from prompt_toolkit.renderer import Output from prompt_toolkit.styles import ANSI_COLOR_NAMES from prompt_toolkit.win32_types import CONSOLE_SCREEN_BUFFER_INFO, STD_OUTPUT_HANDLE, STD_INPUT_HANDLE, COORD, SMALL_RECT -import os +import os import six __all__ = ( @@ -40,26 +40,26 @@ _DEBUG_RENDER_OUTPUT = False _DEBUG_RENDER_OUTPUT_FILENAME = r'prompt-toolkit-windows-output.log' -class NoConsoleScreenBufferError(Exception): - """ - Raised when the application is not running inside a Windows Console, but - the user tries to instantiate Win32Output. - """ - def __init__(self): - # Are we running in 'xterm' on Windows, like git-bash for instance? - xterm = 'xterm' in os.environ.get('TERM', '') - - if xterm: - message = ('Found %s, while expecting a Windows console. ' - 'Maybe try to run this program using "winpty" ' - 'or run it in cmd.exe instead. Or otherwise, ' - 'in case of Cygwin, use the Python executable ' - 'that is compiled for Cygwin.' % os.environ['TERM']) - else: - message = 'No Windows console found. Are you running cmd.exe?' - super(NoConsoleScreenBufferError, self).__init__(message) - - +class NoConsoleScreenBufferError(Exception): + """ + Raised when the application is not running inside a Windows Console, but + the user tries to instantiate Win32Output. + """ + def __init__(self): + # Are we running in 'xterm' on Windows, like git-bash for instance? + xterm = 'xterm' in os.environ.get('TERM', '') + + if xterm: + message = ('Found %s, while expecting a Windows console. ' + 'Maybe try to run this program using "winpty" ' + 'or run it in cmd.exe instead. Or otherwise, ' + 'in case of Cygwin, use the Python executable ' + 'that is compiled for Cygwin.' % os.environ['TERM']) + else: + message = 'No Windows console found. Are you running cmd.exe?' + super(NoConsoleScreenBufferError, self).__init__(message) + + class Win32Output(Output): """ I/O abstraction for rendering to Windows consoles. @@ -76,21 +76,21 @@ class Win32Output(Output): self.color_lookup_table = ColorLookupTable() - # Remember the default console colors. - info = self.get_win32_screen_buffer_info() - self.default_attrs = info.wAttributes if info else 15 - + # Remember the default console colors. + info = self.get_win32_screen_buffer_info() + self.default_attrs = info.wAttributes if info else 15 + if _DEBUG_RENDER_OUTPUT: self.LOG = open(_DEBUG_RENDER_OUTPUT_FILENAME, 'ab') - def fileno(self): - " Return file descriptor. " - return self.stdout.fileno() - - def encoding(self): - " Return encoding used for stdout. " - return self.stdout.encoding - + def fileno(self): + " Return file descriptor. " + return self.stdout.fileno() + + def encoding(self): + " Return encoding used for stdout. " + return self.stdout.encoding + def write(self, data): self._buffer.append(data) @@ -168,8 +168,8 @@ class Win32Output(Output): if success: return sbinfo - else: - raise NoConsoleScreenBufferError + else: + raise NoConsoleScreenBufferError def set_title(self, title): """ @@ -221,31 +221,31 @@ class Win32Output(Output): byref(chars_written)) def reset_attributes(self): - " Reset the console foreground/background color. " - self._winapi(windll.kernel32.SetConsoleTextAttribute, self.hconsole, - self.default_attrs) + " Reset the console foreground/background color. " + self._winapi(windll.kernel32.SetConsoleTextAttribute, self.hconsole, + self.default_attrs) def set_attributes(self, attrs): fgcolor, bgcolor, bold, underline, italic, blink, reverse = attrs - # Start from the default attributes. - attrs = self.default_attrs - - # Override the last four bits: foreground color. - if fgcolor is not None: - attrs = attrs & ~0xf - attrs |= self.color_lookup_table.lookup_fg_color(fgcolor) - - # Override the next four bits: background color. - if bgcolor is not None: - attrs = attrs & ~0xf0 - attrs |= self.color_lookup_table.lookup_bg_color(bgcolor) - - # Reverse: swap these four bits groups. + # Start from the default attributes. + attrs = self.default_attrs + + # Override the last four bits: foreground color. + if fgcolor is not None: + attrs = attrs & ~0xf + attrs |= self.color_lookup_table.lookup_fg_color(fgcolor) + + # Override the next four bits: background color. + if bgcolor is not None: + attrs = attrs & ~0xf0 + attrs |= self.color_lookup_table.lookup_bg_color(bgcolor) + + # Reverse: swap these four bits groups. if reverse: - attrs = (attrs & ~0xff) | ((attrs & 0xf) << 4) | ((attrs & 0xf0) >> 4) + attrs = (attrs & ~0xff) | ((attrs & 0xf) << 4) | ((attrs & 0xf0) >> 4) - self._winapi(windll.kernel32.SetConsoleTextAttribute, self.hconsole, attrs) + self._winapi(windll.kernel32.SetConsoleTextAttribute, self.hconsole, attrs) def disable_autowrap(self): # Not supported by Windows. @@ -327,11 +327,11 @@ class Win32Output(Output): # Scroll vertical win_height = sr.Bottom - sr.Top - if 0 < sr.Bottom - cursor_pos.Y < win_height - 1: - # no vertical scroll if cursor already on the screen - result.Bottom = sr.Bottom - else: - result.Bottom = max(win_height, cursor_pos.Y) + if 0 < sr.Bottom - cursor_pos.Y < win_height - 1: + # no vertical scroll if cursor already on the screen + result.Bottom = sr.Bottom + else: + result.Bottom = max(win_height, cursor_pos.Y) result.Top = result.Bottom - win_height # Scroll API @@ -429,27 +429,27 @@ class BACKROUND_COLOR: def _create_ansi_color_dict(color_cls): " Create a table that maps the 16 named ansi colors to their Windows code. " return { - 'ansidefault': color_cls.BLACK, - 'ansiblack': color_cls.BLACK, - 'ansidarkgray': color_cls.BLACK | color_cls.INTENSITY, - 'ansilightgray': color_cls.GRAY, - 'ansiwhite': color_cls.GRAY | color_cls.INTENSITY, - + 'ansidefault': color_cls.BLACK, + 'ansiblack': color_cls.BLACK, + 'ansidarkgray': color_cls.BLACK | color_cls.INTENSITY, + 'ansilightgray': color_cls.GRAY, + 'ansiwhite': color_cls.GRAY | color_cls.INTENSITY, + # Low intensity. - 'ansidarkred': color_cls.RED, - 'ansidarkgreen': color_cls.GREEN, - 'ansibrown': color_cls.YELLOW, - 'ansidarkblue': color_cls.BLUE, - 'ansipurple': color_cls.MAGENTA, - 'ansiteal': color_cls.CYAN, + 'ansidarkred': color_cls.RED, + 'ansidarkgreen': color_cls.GREEN, + 'ansibrown': color_cls.YELLOW, + 'ansidarkblue': color_cls.BLUE, + 'ansipurple': color_cls.MAGENTA, + 'ansiteal': color_cls.CYAN, # High intensity. - 'ansired': color_cls.RED | color_cls.INTENSITY, - 'ansigreen': color_cls.GREEN | color_cls.INTENSITY, - 'ansiyellow': color_cls.YELLOW | color_cls.INTENSITY, - 'ansiblue': color_cls.BLUE | color_cls.INTENSITY, - 'ansifuchsia': color_cls.MAGENTA | color_cls.INTENSITY, - 'ansiturquoise': color_cls.CYAN | color_cls.INTENSITY, + 'ansired': color_cls.RED | color_cls.INTENSITY, + 'ansigreen': color_cls.GREEN | color_cls.INTENSITY, + 'ansiyellow': color_cls.YELLOW | color_cls.INTENSITY, + 'ansiblue': color_cls.BLUE | color_cls.INTENSITY, + 'ansifuchsia': color_cls.MAGENTA | color_cls.INTENSITY, + 'ansiturquoise': color_cls.CYAN | color_cls.INTENSITY, } FG_ANSI_COLORS = _create_ansi_color_dict(FOREGROUND_COLOR) @@ -492,7 +492,7 @@ class ColorLookupTable(object): (0xff, 0x44, 0xff, FG.MAGENTA | FG.INTENSITY, BG.MAGENTA | BG.INTENSITY), (0xff, 0xff, 0x44, FG.YELLOW | FG.INTENSITY, BG.YELLOW | BG.INTENSITY), - (0x44, 0x44, 0x44, FG.BLACK | FG.INTENSITY, BG.BLACK | BG.INTENSITY), + (0x44, 0x44, 0x44, FG.BLACK | FG.INTENSITY, BG.BLACK | BG.INTENSITY), (0xff, 0xff, 0xff, FG.GRAY | FG.INTENSITY, BG.GRAY | BG.INTENSITY), ] @@ -529,7 +529,7 @@ class ColorLookupTable(object): self.best_match[color] = indexes return indexes - def lookup_fg_color(self, fg_color): + def lookup_fg_color(self, fg_color): """ Return the color for use in the `windll.kernel32.SetConsoleTextAttribute` API call. @@ -538,19 +538,19 @@ class ColorLookupTable(object): """ # Foreground. if fg_color in FG_ANSI_COLORS: - return FG_ANSI_COLORS[fg_color] + return FG_ANSI_COLORS[fg_color] else: - return self._color_indexes(fg_color)[0] - - def lookup_bg_color(self, bg_color): - """ - Return the color for use in the - `windll.kernel32.SetConsoleTextAttribute` API call. - - :param bg_color: Background as text. E.g. 'ffffff' or 'red' - """ + return self._color_indexes(fg_color)[0] + + def lookup_bg_color(self, bg_color): + """ + Return the color for use in the + `windll.kernel32.SetConsoleTextAttribute` API call. + + :param bg_color: Background as text. E.g. 'ffffff' or 'red' + """ # Background. if bg_color in BG_ANSI_COLORS: - return BG_ANSI_COLORS[bg_color] + return BG_ANSI_COLORS[bg_color] else: - return self._color_indexes(bg_color)[1] + return self._color_indexes(bg_color)[1] diff --git a/contrib/python/prompt-toolkit/py2/prompt_toolkit/token.py b/contrib/python/prompt-toolkit/py2/prompt_toolkit/token.py index 5170daf38a..5e2a15787c 100644 --- a/contrib/python/prompt-toolkit/py2/prompt_toolkit/token.py +++ b/contrib/python/prompt-toolkit/py2/prompt_toolkit/token.py @@ -1,47 +1,47 @@ -""" -The Token class, interchangeable with ``pygments.token``. - -A `Token` has some semantics for a piece of text that is given a style through -a :class:`~prompt_toolkit.styles.Style` class. A pygments lexer for instance, -returns a list of (Token, text) tuples. Each fragment of text has a token -assigned, which when combined with a style sheet, will determine the fine -style. -""" - -# If we don't need any lexers or style classes from Pygments, we don't want -# Pygments to be installed for only the following 10 lines of code. So, there -# is some duplication, but this should stay compatible with Pygments. - -__all__ = ( - 'Token', - 'ZeroWidthEscape', -) - - -class _TokenType(tuple): - def __getattr__(self, val): - if not val or not val[0].isupper(): - return tuple.__getattribute__(self, val) - - new = _TokenType(self + (val,)) - setattr(self, val, new) - return new - - def __repr__(self): - return 'Token' + (self and '.' or '') + '.'.join(self) - - -# Prefer the Token class from Pygments. If Pygments is not installed, use our -# minimalistic Token class. -try: - from pygments.token import Token -except ImportError: - Token = _TokenType() - - -# Built-in tokens: - -#: `ZeroWidthEscape` can be used for raw VT escape sequences that don't -#: cause the cursor position to move. (E.g. FinalTerm's escape sequences -#: for shell integration.) -ZeroWidthEscape = Token.ZeroWidthEscape +""" +The Token class, interchangeable with ``pygments.token``. + +A `Token` has some semantics for a piece of text that is given a style through +a :class:`~prompt_toolkit.styles.Style` class. A pygments lexer for instance, +returns a list of (Token, text) tuples. Each fragment of text has a token +assigned, which when combined with a style sheet, will determine the fine +style. +""" + +# If we don't need any lexers or style classes from Pygments, we don't want +# Pygments to be installed for only the following 10 lines of code. So, there +# is some duplication, but this should stay compatible with Pygments. + +__all__ = ( + 'Token', + 'ZeroWidthEscape', +) + + +class _TokenType(tuple): + def __getattr__(self, val): + if not val or not val[0].isupper(): + return tuple.__getattribute__(self, val) + + new = _TokenType(self + (val,)) + setattr(self, val, new) + return new + + def __repr__(self): + return 'Token' + (self and '.' or '') + '.'.join(self) + + +# Prefer the Token class from Pygments. If Pygments is not installed, use our +# minimalistic Token class. +try: + from pygments.token import Token +except ImportError: + Token = _TokenType() + + +# Built-in tokens: + +#: `ZeroWidthEscape` can be used for raw VT escape sequences that don't +#: cause the cursor position to move. (E.g. FinalTerm's escape sequences +#: for shell integration.) +ZeroWidthEscape = Token.ZeroWidthEscape diff --git a/contrib/python/prompt-toolkit/py2/prompt_toolkit/utils.py b/contrib/python/prompt-toolkit/py2/prompt_toolkit/utils.py index 3cd931883c..233821e6ff 100644 --- a/contrib/python/prompt-toolkit/py2/prompt_toolkit/utils.py +++ b/contrib/python/prompt-toolkit/py2/prompt_toolkit/utils.py @@ -1,17 +1,17 @@ from __future__ import unicode_literals -import inspect +import inspect import os import signal import sys import threading -import weakref +import weakref from wcwidth import wcwidth -from six.moves import range +from six.moves import range __all__ = ( - 'Event', + 'Event', 'DummyContext', 'get_cwidth', 'suspend_to_background_supported', @@ -19,58 +19,58 @@ __all__ = ( 'is_windows', 'in_main_thread', 'take_using_weights', - 'test_callable_args', + 'test_callable_args', ) -class Event(object): +class Event(object): """ - Simple event to which event handlers can be attached. For instance:: + Simple event to which event handlers can be attached. For instance:: - class Cls: - def __init__(self): - # Define event. The first parameter is the sender. - self.event = Event(self) + class Cls: + def __init__(self): + # Define event. The first parameter is the sender. + self.event = Event(self) - obj = Cls() + obj = Cls() - def handler(sender): - pass + def handler(sender): + pass - # Add event handler by using the += operator. - obj.event += handler - - # Fire event. - obj.event() + # Add event handler by using the += operator. + obj.event += handler + + # Fire event. + obj.event() """ - def __init__(self, sender, handler=None): - self.sender = sender - self._handlers = [] - - if handler is not None: - self += handler + def __init__(self, sender, handler=None): + self.sender = sender + self._handlers = [] - def __call__(self): - " Fire event. " + if handler is not None: + self += handler + + def __call__(self): + " Fire event. " for handler in self._handlers: - handler(self.sender) - - def fire(self): - " Alias for just calling the event. " - self() + handler(self.sender) + def fire(self): + " Alias for just calling the event. " + self() + def __iadd__(self, handler): """ Add another handler to this callback. - (Handler should be a callable that takes exactly one parameter: the - sender object.) + (Handler should be a callable that takes exactly one parameter: the + sender object.) """ - # Test handler. - assert callable(handler) - if not test_callable_args(handler, [None]): - raise TypeError("%r doesn't take exactly one argument." % handler) - - # Add to list of event handlers. + # Test handler. + assert callable(handler) + if not test_callable_args(handler, [None]): + raise TypeError("%r doesn't take exactly one argument." % handler) + + # Add to list of event handlers. self._handlers.append(handler) return self @@ -82,53 +82,53 @@ class Event(object): return self -# Cache of signatures. Improves the performance of `test_callable_args`. -_signatures_cache = weakref.WeakKeyDictionary() - - -def test_callable_args(func, args): - """ - Return True when this function can be called with the given arguments. - """ - assert isinstance(args, (list, tuple)) - signature = getattr(inspect, 'signature', None) - - if signature is not None: - # For Python 3, use inspect.signature. - try: - sig = _signatures_cache[func] - except KeyError: - sig = signature(func) - _signatures_cache[func] = sig - - try: - sig.bind(*args) - except TypeError: - return False - else: - return True - else: - # For older Python versions, fall back to using getargspec. - spec = inspect.getargspec(func) - - # Drop the 'self' - def drop_self(spec): - args, varargs, varkw, defaults = spec - if args[0:1] == ['self']: - args = args[1:] - return inspect.ArgSpec(args, varargs, varkw, defaults) - - spec = drop_self(spec) - - # When taking *args, always return True. - if spec.varargs is not None: - return True - - # Test whether the given amount of args is between the min and max - # accepted argument counts. - return len(spec.args) - len(spec.defaults or []) <= len(args) <= len(spec.args) - - +# Cache of signatures. Improves the performance of `test_callable_args`. +_signatures_cache = weakref.WeakKeyDictionary() + + +def test_callable_args(func, args): + """ + Return True when this function can be called with the given arguments. + """ + assert isinstance(args, (list, tuple)) + signature = getattr(inspect, 'signature', None) + + if signature is not None: + # For Python 3, use inspect.signature. + try: + sig = _signatures_cache[func] + except KeyError: + sig = signature(func) + _signatures_cache[func] = sig + + try: + sig.bind(*args) + except TypeError: + return False + else: + return True + else: + # For older Python versions, fall back to using getargspec. + spec = inspect.getargspec(func) + + # Drop the 'self' + def drop_self(spec): + args, varargs, varkw, defaults = spec + if args[0:1] == ['self']: + args = args[1:] + return inspect.ArgSpec(args, varargs, varkw, defaults) + + spec = drop_self(spec) + + # When taking *args, always return True. + if spec.varargs is not None: + return True + + # Test whether the given amount of args is between the min and max + # accepted argument counts. + return len(spec.args) - len(spec.defaults or []) <= len(args) <= len(spec.args) + + class DummyContext(object): """ (contextlib.nested is not available on Py3) @@ -154,11 +154,11 @@ class _CharSizesCache(dict): else: result = sum(max(0, wcwidth(c)) for c in string) - # Cache for short strings. - # (It's hard to tell what we can consider short...) - if len(string) < 256: - self[string] = result - + # Cache for short strings. + # (It's hard to tell what we can consider short...) + if len(string) < 256: + self[string] = result + return result diff --git a/contrib/python/prompt-toolkit/py2/prompt_toolkit/validation.py b/contrib/python/prompt-toolkit/py2/prompt_toolkit/validation.py index 0027873f88..384805226f 100644 --- a/contrib/python/prompt-toolkit/py2/prompt_toolkit/validation.py +++ b/contrib/python/prompt-toolkit/py2/prompt_toolkit/validation.py @@ -56,7 +56,7 @@ class ConditionalValidator(Validator): assert isinstance(validator, Validator) self.validator = validator - self.filter = to_simple_filter(filter) + self.filter = to_simple_filter(filter) def validate(self, document): # Call the validator only if the filter is active. diff --git a/contrib/python/prompt-toolkit/py2/ya.make b/contrib/python/prompt-toolkit/py2/ya.make index db22aa0a70..dd98b8cc65 100644 --- a/contrib/python/prompt-toolkit/py2/ya.make +++ b/contrib/python/prompt-toolkit/py2/ya.make @@ -5,7 +5,7 @@ OWNER(blinkov nslus g:python-contrib) VERSION(1.0.18) LICENSE(BSD-3-Clause) - + PEERDIR( contrib/python/six contrib/python/wcwidth @@ -40,7 +40,7 @@ PY_SRCS( prompt_toolkit/auto_suggest.py prompt_toolkit/buffer.py prompt_toolkit/buffer_mapping.py - prompt_toolkit/cache.py + prompt_toolkit/cache.py prompt_toolkit/clipboard/__init__.py prompt_toolkit/clipboard/base.py prompt_toolkit/clipboard/in_memory.py @@ -75,7 +75,7 @@ PY_SRCS( prompt_toolkit/eventloop/inputhook.py prompt_toolkit/eventloop/posix.py prompt_toolkit/eventloop/posix_utils.py - prompt_toolkit/eventloop/select.py + prompt_toolkit/eventloop/select.py prompt_toolkit/eventloop/utils.py prompt_toolkit/eventloop/win32.py prompt_toolkit/filters/__init__.py @@ -89,14 +89,14 @@ PY_SRCS( prompt_toolkit/key_binding/__init__.py prompt_toolkit/key_binding/bindings/__init__.py prompt_toolkit/key_binding/bindings/basic.py - prompt_toolkit/key_binding/bindings/completion.py + prompt_toolkit/key_binding/bindings/completion.py prompt_toolkit/key_binding/bindings/emacs.py - prompt_toolkit/key_binding/bindings/named_commands.py + prompt_toolkit/key_binding/bindings/named_commands.py prompt_toolkit/key_binding/bindings/scroll.py prompt_toolkit/key_binding/bindings/utils.py prompt_toolkit/key_binding/bindings/vi.py prompt_toolkit/key_binding/defaults.py - prompt_toolkit/key_binding/digraphs.py + prompt_toolkit/key_binding/digraphs.py prompt_toolkit/key_binding/input_processor.py prompt_toolkit/key_binding/manager.py prompt_toolkit/key_binding/registry.py @@ -122,19 +122,19 @@ PY_SRCS( prompt_toolkit/search_state.py prompt_toolkit/selection.py prompt_toolkit/shortcuts.py - prompt_toolkit/styles/__init__.py - prompt_toolkit/styles/base.py - prompt_toolkit/styles/defaults.py - prompt_toolkit/styles/from_dict.py - prompt_toolkit/styles/from_pygments.py - prompt_toolkit/styles/utils.py + prompt_toolkit/styles/__init__.py + prompt_toolkit/styles/base.py + prompt_toolkit/styles/defaults.py + prompt_toolkit/styles/from_dict.py + prompt_toolkit/styles/from_pygments.py + prompt_toolkit/styles/utils.py prompt_toolkit/terminal/__init__.py prompt_toolkit/terminal/conemu_output.py prompt_toolkit/terminal/vt100_input.py prompt_toolkit/terminal/vt100_output.py prompt_toolkit/terminal/win32_input.py prompt_toolkit/terminal/win32_output.py - prompt_toolkit/token.py + prompt_toolkit/token.py prompt_toolkit/utils.py prompt_toolkit/validation.py prompt_toolkit/win32_types.py @@ -147,7 +147,7 @@ RESOURCE_FILES( ) END() - + RECURSE_FOR_TESTS( tests ) diff --git a/contrib/python/prompt-toolkit/ya.make b/contrib/python/prompt-toolkit/ya.make index f1f936eb3f..807b031a88 100644 --- a/contrib/python/prompt-toolkit/ya.make +++ b/contrib/python/prompt-toolkit/ya.make @@ -3,7 +3,7 @@ PY23_LIBRARY() LICENSE(Service-Py23-Proxy) OWNER(g:python-contrib) - + IF (PYTHON2) PEERDIR(contrib/python/prompt-toolkit/py2) ELSE() @@ -13,7 +13,7 @@ ENDIF() NO_LINT() END() - + RECURSE( py2 py3 diff --git a/contrib/python/py/ya.make b/contrib/python/py/ya.make index cc86cb7fa9..ff0ad933d3 100644 --- a/contrib/python/py/ya.make +++ b/contrib/python/py/ya.make @@ -5,7 +5,7 @@ PY23_LIBRARY() OWNER(g:python-contrib) VERSION(1.11.0) - + LICENSE(MIT) NO_LINT() diff --git a/contrib/python/traitlets/py2/traitlets/config/application.py b/contrib/python/traitlets/py2/traitlets/config/application.py index d3a4c45e77..5f750b5138 100644 --- a/contrib/python/traitlets/py2/traitlets/config/application.py +++ b/contrib/python/traitlets/py2/traitlets/config/application.py @@ -6,13 +6,13 @@ from __future__ import print_function -from copy import deepcopy +from copy import deepcopy import json import logging import os import re import sys -from collections import defaultdict, OrderedDict +from collections import defaultdict, OrderedDict from decorator import decorator @@ -22,14 +22,14 @@ from traitlets.config.loader import ( ) from traitlets.traitlets import ( - Bool, Unicode, List, Enum, Dict, Instance, TraitError, observe, observe_compat, default, + Bool, Unicode, List, Enum, Dict, Instance, TraitError, observe, observe_compat, default, ) from ipython_genutils.importstring import import_item from ipython_genutils.text import indent, wrap_paragraphs, dedent from ipython_genutils import py3compat -import six - +import six + #----------------------------------------------------------------------------- # Descriptions for the various sections #----------------------------------------------------------------------------- @@ -63,24 +63,24 @@ subcommand 'cmd', do: `{app} cmd -h`. # Application class #----------------------------------------------------------------------------- - - -_envvar = os.environ.get('TRAITLETS_APPLICATION_RAISE_CONFIG_FILE_ERROR','') -if _envvar.lower() in {'1','true'}: - TRAITLETS_APPLICATION_RAISE_CONFIG_FILE_ERROR = True -elif _envvar.lower() in {'0','false',''} : - TRAITLETS_APPLICATION_RAISE_CONFIG_FILE_ERROR = False -else: - raise ValueError("Unsupported value for environment variable: 'TRAITLETS_APPLICATION_RAISE_CONFIG_FILE_ERROR' is set to '%s' which is none of {'0', '1', 'false', 'true', ''}."% _envvar ) - - + + +_envvar = os.environ.get('TRAITLETS_APPLICATION_RAISE_CONFIG_FILE_ERROR','') +if _envvar.lower() in {'1','true'}: + TRAITLETS_APPLICATION_RAISE_CONFIG_FILE_ERROR = True +elif _envvar.lower() in {'0','false',''} : + TRAITLETS_APPLICATION_RAISE_CONFIG_FILE_ERROR = False +else: + raise ValueError("Unsupported value for environment variable: 'TRAITLETS_APPLICATION_RAISE_CONFIG_FILE_ERROR' is set to '%s' which is none of {'0', '1', 'false', 'true', ''}."% _envvar ) + + @decorator def catch_config_error(method, app, *args, **kwargs): """Method decorator for catching invalid config (Trait/ArgumentErrors) during init. On a TraitError (generally caused by bad config), this will print the trait's message, and exit the app. - + For use on init methods, to prevent invoking excepthook on invalid input. """ try: @@ -99,16 +99,16 @@ class ApplicationError(Exception): class LevelFormatter(logging.Formatter): """Formatter with additional `highlevel` record - + This field is empty if log level is less than highlevel_limit, otherwise it is formatted with self.highlevel_format. - + Useful for adding 'WARNING' to warning messages, without adding 'INFO' to info, etc. """ highlevel_limit = logging.WARN highlevel_format = " %(levelname)s |" - + def format(self, record): if record.levelno >= self.highlevel_limit: record.highlevel = self.highlevel_format % record.__dict__ @@ -116,7 +116,7 @@ class LevelFormatter(logging.Formatter): record.highlevel = "" return super(LevelFormatter, self).format(record) - + class Application(SingletonConfigurable): """A singleton application with full configuration support.""" @@ -131,7 +131,7 @@ class Application(SingletonConfigurable): option_description = Unicode(option_description) keyvalue_description = Unicode(keyvalue_description) subcommand_description = Unicode(subcommand_description) - + python_config_loader_class = PyFileConfigLoader json_config_loader_class = JSONFileConfigLoader @@ -158,13 +158,13 @@ class Application(SingletonConfigurable): # The version string of this application. version = Unicode(u'0.0') - + # the argv used to initialize the application argv = List() - # Whether failing to load config files should prevent startup - raise_config_file_errors = Bool(TRAITLETS_APPLICATION_RAISE_CONFIG_FILE_ERROR) - + # Whether failing to load config files should prevent startup + raise_config_file_errors = Bool(TRAITLETS_APPLICATION_RAISE_CONFIG_FILE_ERROR) + # The log level for the application log_level = Enum((0,10,20,30,40,50,'DEBUG','INFO','WARN','ERROR','CRITICAL'), default_value=logging.WARN, @@ -174,15 +174,15 @@ class Application(SingletonConfigurable): @observe_compat def _log_level_changed(self, change): """Adjust the log level when log_level is set.""" - new = change.new - if isinstance(new, six.string_types): + new = change.new + if isinstance(new, six.string_types): new = getattr(logging, new) self.log_level = new self.log.setLevel(new) - + _log_formatter_cls = LevelFormatter - - log_datefmt = Unicode("%Y-%m-%d %H:%M:%S", + + log_datefmt = Unicode("%Y-%m-%d %H:%M:%S", help="The date format used by logging formatters for %(asctime)s" ).tag(config=True) @@ -197,7 +197,7 @@ class Application(SingletonConfigurable): _log_handler = self.log.handlers[0] _log_formatter = self._log_formatter_cls(fmt=self.log_format, datefmt=self.log_datefmt) _log_handler.setFormatter(_log_formatter) - + @default('log') def _log_default(self): """Start logging for this application. @@ -217,7 +217,7 @@ class Application(SingletonConfigurable): break else: _log = _log.parent - if sys.executable and sys.executable.endswith('pythonw.exe'): + if sys.executable and sys.executable.endswith('pythonw.exe'): # this should really go to a file, but file-logging is only # hooked up in parallel applications _log_handler = logging.StreamHandler(open(os.devnull, 'w')) @@ -240,11 +240,11 @@ class Application(SingletonConfigurable): @observe_compat def _flags_changed(self, change): """ensure flags dict is valid""" - new = change.new + new = change.new for key, value in new.items(): assert len(value) == 2, "Bad flag: %r:%s" % (key, value) assert isinstance(value[0], (dict, Config)), "Bad flag: %r:%s" % (key, value) - assert isinstance(value[1], six.string_types), "Bad flag: %r:%s" % (key, value) + assert isinstance(value[1], six.string_types), "Bad flag: %r:%s" % (key, value) # subcommands for launching other applications @@ -259,34 +259,34 @@ class Application(SingletonConfigurable): # extra command-line arguments that don't set config values extra_args = List(Unicode()) - cli_config = Instance(Config, (), {}, - help="""The subset of our configuration that came from the command-line - - We re-load this configuration after loading config files, - to ensure that it maintains highest priority. - """ - ) + cli_config = Instance(Config, (), {}, + help="""The subset of our configuration that came from the command-line + We re-load this configuration after loading config files, + to ensure that it maintains highest priority. + """ + ) + _loaded_config_files = List() - + def __init__(self, **kwargs): SingletonConfigurable.__init__(self, **kwargs) # Ensure my class is in self.classes, so my attributes appear in command line # options and config files. - cls = self.__class__ - if cls not in self.classes: - if self.classes is cls.classes: - # class attr, assign instead of insert - cls.classes = [cls] + self.classes - else: - self.classes.insert(0, self.__class__) - + cls = self.__class__ + if cls not in self.classes: + if self.classes is cls.classes: + # class attr, assign instead of insert + cls.classes = [cls] + self.classes + else: + self.classes.insert(0, self.__class__) + @observe('config') @observe_compat def _config_changed(self, change): super(Application, self)._config_changed(change) self.log.debug('Config changed:') - self.log.debug(repr(change.new)) + self.log.debug(repr(change.new)) @catch_config_error def initialize(self, argv=None): @@ -317,7 +317,7 @@ class Application(SingletonConfigurable): for c in cls.mro()[:-3]: classdict[c.__name__] = c - for alias, longname in self.aliases.items(): + for alias, longname in self.aliases.items(): classname, traitname = longname.split('.',1) cls = classdict[classname] @@ -337,7 +337,7 @@ class Application(SingletonConfigurable): return lines = [] - for m, (cfg,help) in self.flags.items(): + for m, (cfg,help) in self.flags.items(): prefix = '--' if len(m) > 1 else '-' lines.append(prefix+m) lines.append(indent(dedent(help.strip()))) @@ -370,7 +370,7 @@ class Application(SingletonConfigurable): app=self.name)): lines.append(p) lines.append('') - for subc, (cls, help) in self.subcommands.items(): + for subc, (cls, help) in self.subcommands.items(): lines.append(subc) if help: lines.append(indent(dedent(help.strip()))) @@ -442,26 +442,26 @@ class Application(SingletonConfigurable): """Initialize a subcommand with argv.""" subapp,help = self.subcommands.get(subc) - if isinstance(subapp, six.string_types): + if isinstance(subapp, six.string_types): subapp = import_item(subapp) # clear existing instances self.__class__.clear_instance() # instantiate - self.subapp = subapp.instance(parent=self) + self.subapp = subapp.instance(parent=self) # and initialize subapp self.subapp.initialize(argv) - + def flatten_flags(self): """flatten flags and aliases, so cl-args override as expected. - + This prevents issues such as an alias pointing to InteractiveShell, but a config file setting the same trait in TerminalInteraciveShell getting inappropriate priority over the command-line arg. Only aliases with exactly one descendent in the class list will be promoted. - + """ # build a tree of classes in our list that inherit from a particular # it will be a dict by parent classname of classes in our list @@ -475,20 +475,20 @@ class Application(SingletonConfigurable): # flatten aliases, which have the form: # { 'alias' : 'Class.trait' } aliases = {} - for alias, cls_trait in self.aliases.items(): + for alias, cls_trait in self.aliases.items(): cls,trait = cls_trait.split('.',1) children = mro_tree[cls] if len(children) == 1: # exactly one descendent, promote alias cls = children[0] aliases[alias] = '.'.join([cls,trait]) - + # flatten flags, which are of the form: # { 'key' : ({'Cls' : {'trait' : value}}, 'help')} flags = {} - for key, (flagdict, help) in self.flags.items(): + for key, (flagdict, help) in self.flags.items(): newflag = {} - for cls, subdict in flagdict.items(): + for cls, subdict in flagdict.items(): children = mro_tree[cls] # exactly one descendent, promote flag section if len(children) == 1: @@ -502,7 +502,7 @@ class Application(SingletonConfigurable): """Parse the command line arguments.""" argv = sys.argv[1:] if argv is None else argv self.argv = [ py3compat.cast_unicode(arg) for arg in argv ] - + if argv and argv[0] == 'help': # turn `ipython help notebook` into `ipython notebook -h` argv = argv[1:] + ['-h'] @@ -530,33 +530,33 @@ class Application(SingletonConfigurable): if '--version' in interpreted_argv or '-V' in interpreted_argv: self.print_version() self.exit(0) - + # flatten flags&aliases, so cl-args get appropriate priority: flags,aliases = self.flatten_flags() loader = KVArgParseConfigLoader(argv=argv, aliases=aliases, flags=flags, log=self.log) - self.cli_config = deepcopy(loader.load_config()) - self.update_config(self.cli_config) + self.cli_config = deepcopy(loader.load_config()) + self.update_config(self.cli_config) # store unparsed args in extra_args self.extra_args = loader.extra_args @classmethod - def _load_config_files(cls, basefilename, path=None, log=None, raise_config_file_errors=False): + def _load_config_files(cls, basefilename, path=None, log=None, raise_config_file_errors=False): """Load config files (py,json) by filename and path. yield each config object in turn. """ - + if not isinstance(path, list): path = [path] for path in path[::-1]: # path list is in descending priority order, so load files backwards: pyloader = cls.python_config_loader_class(basefilename+'.py', path=path, log=log) if log: - log.debug("Looking for %s in %s", basefilename, path or os.getcwd()) + log.debug("Looking for %s in %s", basefilename, path or os.getcwd()) jsonloader = cls.json_config_loader_class(basefilename+'.json', path=path, log=log) - loaded = [] - filenames = [] + loaded = [] + filenames = [] for loader in [pyloader, jsonloader]: config = None try: @@ -568,8 +568,8 @@ class Application(SingletonConfigurable): # unlikely event that the error raised before filefind finished filename = loader.full_filename or basefilename # problem while running the file - if raise_config_file_errors: - raise + if raise_config_file_errors: + raise if log: log.error("Exception while loading config file %s", filename, exc_info=True) @@ -577,16 +577,16 @@ class Application(SingletonConfigurable): if log: log.debug("Loaded config file: %s", loader.full_filename) if config: - for filename, earlier_config in zip(filenames, loaded): - collisions = earlier_config.collisions(config) - if collisions and log: - log.warning("Collisions detected in {0} and {1} config files." - " {1} has higher priority: {2}".format( - filename, loader.full_filename, json.dumps(collisions, indent=2), - )) + for filename, earlier_config in zip(filenames, loaded): + collisions = earlier_config.collisions(config) + if collisions and log: + log.warning("Collisions detected in {0} and {1} config files." + " {1} has higher priority: {2}".format( + filename, loader.full_filename, json.dumps(collisions, indent=2), + )) yield (config, loader.full_filename) - loaded.append(config) - filenames.append(loader.full_filename) + loaded.append(config) + filenames.append(loader.full_filename) @property def loaded_config_files(self): @@ -597,55 +597,55 @@ class Application(SingletonConfigurable): def load_config_file(self, filename, path=None): """Load config files by filename and path.""" filename, ext = os.path.splitext(filename) - new_config = Config() + new_config = Config() for (config, filename) in self._load_config_files(filename, path=path, log=self.log, - raise_config_file_errors=self.raise_config_file_errors, - ): - new_config.merge(config) + raise_config_file_errors=self.raise_config_file_errors, + ): + new_config.merge(config) if filename not in self._loaded_config_files: # only add to list of loaded files if not previously loaded self._loaded_config_files.append(filename) - # add self.cli_config to preserve CLI config priority - new_config.merge(self.cli_config) - self.update_config(new_config) - - - def _classes_in_config_sample(self): - """ - Yields only classes with own traits, and their subclasses. - - Thus, produced sample config-file will contain all classes - on which a trait-value may be overridden: - - - either on the class owning the trait, - - or on its subclasses, even if those subclasses do not define - any traits themselves. - """ - cls_to_config = OrderedDict( (cls, bool(cls.class_own_traits(config=True))) - for cls - in self._classes_inc_parents()) - - def is_any_parent_included(cls): - return any(b in cls_to_config and cls_to_config[b] for b in cls.__bases__) - - ## Mark "empty" classes for inclusion if their parents own-traits, - # and loop until no more classes gets marked. - # - while True: - to_incl_orig = cls_to_config.copy() - cls_to_config = OrderedDict( (cls, inc_yes or is_any_parent_included(cls)) - for cls, inc_yes - in cls_to_config.items()) - if cls_to_config == to_incl_orig: - break - for cl, inc_yes in cls_to_config.items(): - if inc_yes: - yield cl - + # add self.cli_config to preserve CLI config priority + new_config.merge(self.cli_config) + self.update_config(new_config) + + + def _classes_in_config_sample(self): + """ + Yields only classes with own traits, and their subclasses. + + Thus, produced sample config-file will contain all classes + on which a trait-value may be overridden: + + - either on the class owning the trait, + - or on its subclasses, even if those subclasses do not define + any traits themselves. + """ + cls_to_config = OrderedDict( (cls, bool(cls.class_own_traits(config=True))) + for cls + in self._classes_inc_parents()) + + def is_any_parent_included(cls): + return any(b in cls_to_config and cls_to_config[b] for b in cls.__bases__) + + ## Mark "empty" classes for inclusion if their parents own-traits, + # and loop until no more classes gets marked. + # + while True: + to_incl_orig = cls_to_config.copy() + cls_to_config = OrderedDict( (cls, inc_yes or is_any_parent_included(cls)) + for cls, inc_yes + in cls_to_config.items()) + if cls_to_config == to_incl_orig: + break + for cl, inc_yes in cls_to_config.items(): + if inc_yes: + yield cl + def generate_config_file(self): """generate default config file from Configurables""" lines = ["# Configuration file for %s." % self.name] lines.append('') - for cls in self._classes_in_config_sample(): + for cls in self._classes_in_config_sample(): lines.append(cls.class_config_section()) return '\n'.join(lines) @@ -656,7 +656,7 @@ class Application(SingletonConfigurable): @classmethod def launch_instance(cls, argv=None, **kwargs): """Launch a global instance of this Application - + If a global instance already exists, this reinitializes and starts it """ app = cls.instance(**kwargs) @@ -702,7 +702,7 @@ def boolean_flag(name, configurable, set_help='', unset_help=''): def get_config(): """Get the config object for the global Application instance, if there is one - + otherwise return an empty config object """ if Application.initialized(): diff --git a/contrib/python/traitlets/py2/traitlets/config/configurable.py b/contrib/python/traitlets/py2/traitlets/config/configurable.py index 1174fcf017..7e34c5a84a 100644 --- a/contrib/python/traitlets/py2/traitlets/config/configurable.py +++ b/contrib/python/traitlets/py2/traitlets/config/configurable.py @@ -4,12 +4,12 @@ # Copyright (c) IPython Development Team. # Distributed under the terms of the Modified BSD License. -from __future__ import print_function, absolute_import +from __future__ import print_function, absolute_import from copy import deepcopy -import warnings +import warnings -from .loader import Config, LazyConfigValue, _is_section_key +from .loader import Config, LazyConfigValue, _is_section_key from traitlets.traitlets import HasTraits, Instance, observe, observe_compat, default from ipython_genutils.text import indent, dedent, wrap_paragraphs @@ -66,12 +66,12 @@ class Configurable(HasTraits): if kwargs.get('config', None) is None: kwargs['config'] = parent.config self.parent = parent - + config = kwargs.pop('config', None) - + # load kwarg traits, other than config super(Configurable, self).__init__(**kwargs) - + # load config if config is not None: # We used to deepcopy, but for now we are trying to just save @@ -85,7 +85,7 @@ class Configurable(HasTraits): else: # allow _config_default to return something self._load_config(self.config) - + # Ensure explicit kwargs are applied after loading config. # This is usually redundant, but ensures config doesn't override # explicitly assigned values. @@ -95,25 +95,25 @@ class Configurable(HasTraits): #------------------------------------------------------------------------- # Static trait notifiations #------------------------------------------------------------------------- - + @classmethod def section_names(cls): """return section names as a list""" return [c.__name__ for c in reversed(cls.__mro__) if issubclass(c, Configurable) and issubclass(cls, c) ] - + def _find_my_config(self, cfg): """extract my config from a global Config object - + will construct a Config object of only the config values that apply to me based on my mro(), as well as those of my parent(s) if they exist. - + If I am Bar and my parent is Foo, and their parent is Tim, this will return merge following config sections, in this order:: - + [Bar, Foo.bar, Tim.Foo.Bar] - + With the last item being the highest priority. """ cfgs = [cfg] @@ -127,20 +127,20 @@ class Configurable(HasTraits): if c._has_section(sname): my_config.merge(c[sname]) return my_config - + def _load_config(self, cfg, section_names=None, traits=None): """load traits from a Config object""" - + if traits is None: traits = self.traits(config=True) if section_names is None: section_names = self.section_names() - + my_config = self._find_my_config(cfg) - + # hold trait notifications until after all config has been loaded with self.hold_trait_notifications(): - for name, config_value in my_config.items(): + for name, config_value in my_config.items(): if name in traits: if isinstance(config_value, LazyConfigValue): # ConfigValue is a wrapper for using append / update on containers @@ -151,21 +151,21 @@ class Configurable(HasTraits): # config object. If we don't, a mutable config_value will be # shared by all instances, effectively making it a class attribute. setattr(self, name, deepcopy(config_value)) - elif not _is_section_key(name) and not isinstance(config_value, Config): + elif not _is_section_key(name) and not isinstance(config_value, Config): from difflib import get_close_matches - if isinstance(self, LoggingConfigurable): - warn = self.log.warning - else: - warn = lambda msg: warnings.warn(msg, stacklevel=9) + if isinstance(self, LoggingConfigurable): + warn = self.log.warning + else: + warn = lambda msg: warnings.warn(msg, stacklevel=9) matches = get_close_matches(name, traits) - msg = u"Config option `{option}` not recognized by `{klass}`.".format( - option=name, klass=self.__class__.__name__) - + msg = u"Config option `{option}` not recognized by `{klass}`.".format( + option=name, klass=self.__class__.__name__) + if len(matches) == 1: - msg += u" Did you mean `{matches}`?".format(matches=matches[0]) + msg += u" Did you mean `{matches}`?".format(matches=matches[0]) elif len(matches) >= 1: - msg +=" Did you mean one of: `{matches}`?".format(matches=', '.join(sorted(matches))) - warn(msg) + msg +=" Did you mean one of: `{matches}`?".format(matches=', '.join(sorted(matches))) + warn(msg) @observe('config') @observe_compat @@ -183,23 +183,23 @@ class Configurable(HasTraits): # classes that are Configurable subclasses. This starts with Configurable # and works down the mro loading the config for each section. section_names = self.section_names() - self._load_config(change.new, traits=traits, section_names=section_names) + self._load_config(change.new, traits=traits, section_names=section_names) def update_config(self, config): - """Update config and load the new values""" - # traitlets prior to 4.2 created a copy of self.config in order to trigger change events. - # Some projects (IPython < 5) relied upon one side effect of this, - # that self.config prior to update_config was not modified in-place. - # For backward-compatibility, we must ensure that self.config - # is a new object and not modified in-place, - # but config consumers should not rely on this behavior. - self.config = deepcopy(self.config) - # load config - self._load_config(config) - # merge it into self.config + """Update config and load the new values""" + # traitlets prior to 4.2 created a copy of self.config in order to trigger change events. + # Some projects (IPython < 5) relied upon one side effect of this, + # that self.config prior to update_config was not modified in-place. + # For backward-compatibility, we must ensure that self.config + # is a new object and not modified in-place, + # but config consumers should not rely on this behavior. + self.config = deepcopy(self.config) + # load config + self._load_config(config) + # merge it into self.config self.config.merge(config) - # TODO: trigger change event if/when dict-update change events take place - # DO NOT trigger full trait-change + # TODO: trigger change event if/when dict-update change events take place + # DO NOT trigger full trait-change @classmethod def class_get_help(cls, inst=None): @@ -220,7 +220,7 @@ class Configurable(HasTraits): @classmethod def class_get_trait_help(cls, trait, inst=None): """Get the help string for a single trait. - + If `inst` is given, it's current trait values will be used in place of the class default. """ @@ -261,19 +261,19 @@ class Configurable(HasTraits): """return a commented, wrapped block.""" s = '\n\n'.join(wrap_paragraphs(s, 78)) - return '## ' + s.replace('\n', '\n# ') + return '## ' + s.replace('\n', '\n# ') # section header breaker = '#' + '-'*78 - parent_classes = ','.join(p.__name__ for p in cls.__bases__) - s = "# %s(%s) configuration" % (cls.__name__, parent_classes) + parent_classes = ','.join(p.__name__ for p in cls.__bases__) + s = "# %s(%s) configuration" % (cls.__name__, parent_classes) lines = [breaker, s, breaker, ''] # get the description trait desc = cls.class_traits().get('description') if desc: desc = desc.default_value - if not desc: - # no description from trait, use __doc__ + if not desc: + # no description from trait, use __doc__ desc = getattr(cls, '__doc__', '') if desc: lines.append(c(desc)) @@ -281,7 +281,7 @@ class Configurable(HasTraits): for name, trait in sorted(cls.class_own_traits(config=True).items()): lines.append(c(trait.help)) - lines.append('#c.%s.%s = %s' % (cls.__name__, name, trait.default_value_repr())) + lines.append('#c.%s.%s = %s' % (cls.__name__, name, trait.default_value_repr())) lines.append('') return '\n'.join(lines) diff --git a/contrib/python/traitlets/py2/traitlets/config/loader.py b/contrib/python/traitlets/py2/traitlets/config/loader.py index 803b36276f..a79a398c3d 100644 --- a/contrib/python/traitlets/py2/traitlets/config/loader.py +++ b/contrib/python/traitlets/py2/traitlets/config/loader.py @@ -16,7 +16,7 @@ from ast import literal_eval from ipython_genutils.path import filefind from ipython_genutils import py3compat from ipython_genutils.encoding import DEFAULT_ENCODING -from six import text_type +from six import text_type from traitlets.traitlets import HasTraits, List, Any #----------------------------------------------------------------------------- @@ -182,7 +182,7 @@ class Config(dict): def merge(self, other): """merge another config object into this one""" to_update = {} - for k, v in other.items(): + for k, v in other.items(): if k not in self: to_update[k] = v else: # I have this key @@ -385,17 +385,17 @@ class FileConfigLoader(ConfigLoader): self.full_filename = filefind(self.filename, self.path) class JSONFileConfigLoader(FileConfigLoader): - """A JSON file loader for config - - Can also act as a context manager that rewrite the configuration file to disk on exit. - - Example:: - - with JSONFileConfigLoader('myapp.json','/home/jupyter/configurations/') as c: - c.MyNewConfigurable.new_value = 'Updated' - - """ - + """A JSON file loader for config + + Can also act as a context manager that rewrite the configuration file to disk on exit. + + Example:: + + with JSONFileConfigLoader('myapp.json','/home/jupyter/configurations/') as c: + c.MyNewConfigurable.new_value = 'Updated' + + """ + def load_config(self): """Load the config from a file and return it as a Config object.""" self.clear() @@ -422,24 +422,24 @@ class JSONFileConfigLoader(FileConfigLoader): else: raise ValueError('Unknown version of JSON config file: {version}'.format(version=version)) - def __enter__(self): - self.load_config() - return self.config - - def __exit__(self, exc_type, exc_value, traceback): - """ - Exit the context manager but do not handle any errors. - - In case of any error, we do not want to write the potentially broken - configuration to disk. - """ - self.config.version = 1 - json_config = json.dumps(self.config, indent=2) - with open(self.full_filename, 'w') as f: - f.write(json_config) - - - + def __enter__(self): + self.load_config() + return self.config + + def __exit__(self, exc_type, exc_value, traceback): + """ + Exit the context manager but do not handle any errors. + + In case of any error, we do not want to write the potentially broken + configuration to disk. + """ + self.config.version = 1 + json_config = json.dumps(self.config, indent=2) + with open(self.full_filename, 'w') as f: + f.write(json_config) + + + class PyFileConfigLoader(FileConfigLoader): """A config loader for pure python files. @@ -521,7 +521,7 @@ class CommandLineConfigLoader(ConfigLoader): if isinstance(cfg, (dict, Config)): # don't clobber whole config sections, update # each section from config: - for sec,c in cfg.items(): + for sec,c in cfg.items(): self.config[sec].update(c) else: raise TypeError("Invalid flag: %r" % cfg) @@ -603,7 +603,7 @@ class KeyValueConfigLoader(CommandLineConfigLoader): if enc is None: enc = DEFAULT_ENCODING for arg in argv: - if not isinstance(arg, text_type): + if not isinstance(arg, text_type): # only decode if not already decoded arg = arg.decode(enc) uargv.append(arg) @@ -769,7 +769,7 @@ class ArgParseConfigLoader(CommandLineConfigLoader): def _convert_to_config(self): """self.parsed_data->self.config""" - for k, v in vars(self.parsed_data).items(): + for k, v in vars(self.parsed_data).items(): exec("self.config.%s = v"%k, locals(), globals()) class KVArgParseConfigLoader(ArgParseConfigLoader): @@ -786,17 +786,17 @@ class KVArgParseConfigLoader(ArgParseConfigLoader): if flags is None: flags = self.flags paa = self.parser.add_argument - for key,value in aliases.items(): + for key,value in aliases.items(): if key in flags: # flags nargs = '?' else: nargs = None if len(key) is 1: - paa('-'+key, '--'+key, type=text_type, dest=value, nargs=nargs) + paa('-'+key, '--'+key, type=text_type, dest=value, nargs=nargs) else: - paa('--'+key, type=text_type, dest=value, nargs=nargs) - for key, (value, help) in flags.items(): + paa('--'+key, type=text_type, dest=value, nargs=nargs) + for key, (value, help) in flags.items(): if key in self.aliases: # self.alias_flags[self.aliases[key]] = value @@ -815,7 +815,7 @@ class KVArgParseConfigLoader(ArgParseConfigLoader): else: subcs = [] - for k, v in vars(self.parsed_data).items(): + for k, v in vars(self.parsed_data).items(): if v is None: # it was a flag that shares the name of an alias subcs.append(self.alias_flags[k]) diff --git a/contrib/python/traitlets/py2/traitlets/config/manager.py b/contrib/python/traitlets/py2/traitlets/config/manager.py index 5e5ebde9af..f5cf21904e 100644 --- a/contrib/python/traitlets/py2/traitlets/config/manager.py +++ b/contrib/python/traitlets/py2/traitlets/config/manager.py @@ -7,7 +7,7 @@ import io import json import os -from six import PY3 +from six import PY3 from traitlets.config import LoggingConfigurable from traitlets.traitlets import Unicode diff --git a/contrib/python/traitlets/py2/traitlets/log.py b/contrib/python/traitlets/py2/traitlets/log.py index af86b325f5..c7166c14c8 100644 --- a/contrib/python/traitlets/py2/traitlets/log.py +++ b/contrib/python/traitlets/py2/traitlets/log.py @@ -9,19 +9,19 @@ _logger = None def get_logger(): """Grab the global logger instance. - + If a global Application is instantiated, grab its logger. Otherwise, grab the root logger. """ global _logger - + if _logger is None: from .config import Application if Application.initialized(): _logger = Application.instance().log else: - _logger = logging.getLogger('traitlets') - # Add a NullHandler to silence warnings about not being - # initialized, per best practice for libraries. - _logger.addHandler(logging.NullHandler()) + _logger = logging.getLogger('traitlets') + # Add a NullHandler to silence warnings about not being + # initialized, per best practice for libraries. + _logger.addHandler(logging.NullHandler()) return _logger diff --git a/contrib/python/traitlets/py2/traitlets/traitlets.py b/contrib/python/traitlets/py2/traitlets/traitlets.py index c07daf7400..b3134c819b 100644 --- a/contrib/python/traitlets/py2/traitlets/traitlets.py +++ b/contrib/python/traitlets/py2/traitlets/traitlets.py @@ -42,11 +42,11 @@ Inheritance diagram: import contextlib import inspect -import os +import os import re import sys import types -import enum +import enum try: from types import ClassType, InstanceType ClassTypes = (ClassType, type) @@ -54,12 +54,12 @@ except: ClassTypes = (type,) from warnings import warn, warn_explicit -import six +import six from .utils.getargspec import getargspec from .utils.importstring import import_item from .utils.sentinel import Sentinel -from .utils.bunch import Bunch +from .utils.bunch import Bunch SequenceTypes = (list, tuple, set, frozenset) @@ -91,39 +91,39 @@ class TraitError(Exception): # Utilities #----------------------------------------------------------------------------- -from ipython_genutils.py3compat import cast_unicode_py2 - -_name_re = re.compile(r"[a-zA-Z_][a-zA-Z0-9_]*$") - -def isidentifier(s): - if six.PY2: - return bool(_name_re.match(s)) - else: - return s.isidentifier() - -_deprecations_shown = set() -def _should_warn(key): - """Add our own checks for too many deprecation warnings. - - Limit to once per package. - """ - env_flag = os.environ.get('TRAITLETS_ALL_DEPRECATIONS') - if env_flag and env_flag != '0': - return True - - if key not in _deprecations_shown: - _deprecations_shown.add(key) - return True - else: - return False - +from ipython_genutils.py3compat import cast_unicode_py2 + +_name_re = re.compile(r"[a-zA-Z_][a-zA-Z0-9_]*$") + +def isidentifier(s): + if six.PY2: + return bool(_name_re.match(s)) + else: + return s.isidentifier() + +_deprecations_shown = set() +def _should_warn(key): + """Add our own checks for too many deprecation warnings. + + Limit to once per package. + """ + env_flag = os.environ.get('TRAITLETS_ALL_DEPRECATIONS') + if env_flag and env_flag != '0': + return True + + if key not in _deprecations_shown: + _deprecations_shown.add(key) + return True + else: + return False + def _deprecated_method(method, cls, method_name, msg): """Show deprecation warning about a magic method definition. Uses warn_explicit to bind warning to method definition instead of triggering code, which isn't relevant. """ - warn_msg = "{classname}.{method_name} is deprecated in traitlets 4.1: {msg}".format( + warn_msg = "{classname}.{method_name} is deprecated in traitlets 4.1: {msg}".format( classname=cls.__name__, method_name=method_name, msg=msg ) @@ -131,15 +131,15 @@ def _deprecated_method(method, cls, method_name, msg): if method_name in parent.__dict__: cls = parent break - # limit deprecation messages to once per package - package_name = cls.__module__.split('.', 1)[0] - key = (package_name, msg) - if not _should_warn(key): - return + # limit deprecation messages to once per package + package_name = cls.__module__.split('.', 1)[0] + key = (package_name, msg) + if not _should_warn(key): + return try: fname = inspect.getsourcefile(method) or "<unknown>" lineno = inspect.getsourcelines(method)[1] or 0 - except (IOError, TypeError) as e: + except (IOError, TypeError) as e: # Failed to inspect for some reason warn(warn_msg + ('\n(inspection failed) %s' % e), DeprecationWarning) else: @@ -150,7 +150,7 @@ def class_of(object): correct indefinite article ('a' or 'an') preceding it (e.g., 'an Image', 'a PlotValue'). """ - if isinstance( object, six.string_types ): + if isinstance( object, six.string_types ): return add_article( object ) return add_article( object.__class__.__name__ ) @@ -171,7 +171,7 @@ def repr_type(obj): error messages. """ the_type = type(obj) - if six.PY2 and the_type is InstanceType: + if six.PY2 and the_type is InstanceType: # Old-style class. the_type = obj.__class__ msg = '%r %r' % (obj, the_type) @@ -200,14 +200,14 @@ def parse_notifier_name(names): >>> parse_notifier_name(All) [All] """ - if names is All or isinstance(names, six.string_types): + if names is All or isinstance(names, six.string_types): return [names] - else: + else: if not names or All in names: return [All] for n in names: - if not isinstance(n, six.string_types): - raise TypeError("names must be strings, not %r" % n) + if not isinstance(n, six.string_types): + raise TypeError("names must be strings, not %r" % n) return names @@ -288,13 +288,13 @@ class link(object): if self.updating: return with self._busy_updating(): - setattr(self.target[0], self.target[1], change.new) + setattr(self.target[0], self.target[1], change.new) def _update_source(self, change): if self.updating: return with self._busy_updating(): - setattr(self.source[0], self.source[1], change.new) + setattr(self.source[0], self.source[1], change.new) def unlink(self): self.source[0].unobserve(self._update_target, names=self.source[1]) @@ -344,7 +344,7 @@ class directional_link(object): return with self._busy_updating(): setattr(self.target[0], self.target[1], - self._transform(change.new)) + self._transform(change.new)) def unlink(self): self.source[0].unobserve(self._update, names=self.source[1]) @@ -354,7 +354,7 @@ dlink = directional_link #----------------------------------------------------------------------------- -# Base Descriptor Class +# Base Descriptor Class #----------------------------------------------------------------------------- @@ -429,32 +429,32 @@ class TraitType(BaseDescriptor): """ if default_value is not Undefined: self.default_value = default_value - if allow_none: + if allow_none: self.allow_none = allow_none if read_only is not None: self.read_only = read_only self.help = help if help is not None else '' - if len(kwargs) > 0: + if len(kwargs) > 0: stacklevel = 1 f = inspect.currentframe() # count supers to determine stacklevel for warning while f.f_code.co_name == '__init__': stacklevel += 1 f = f.f_back - mod = f.f_globals.get('__name__') or '' - pkg = mod.split('.', 1)[0] - key = tuple(['metadata-tag', pkg] + sorted(kwargs)) - if _should_warn(key): - warn("metadata %s was set from the constructor. " - "With traitlets 4.1, metadata should be set using the .tag() method, " - "e.g., Int().tag(key1='value1', key2='value2')" % (kwargs,), - DeprecationWarning, stacklevel=stacklevel) + mod = f.f_globals.get('__name__') or '' + pkg = mod.split('.', 1)[0] + key = tuple(['metadata-tag', pkg] + sorted(kwargs)) + if _should_warn(key): + warn("metadata %s was set from the constructor. " + "With traitlets 4.1, metadata should be set using the .tag() method, " + "e.g., Int().tag(key1='value1', key2='value2')" % (kwargs,), + DeprecationWarning, stacklevel=stacklevel) if len(self.metadata) > 0: self.metadata = self.metadata.copy() - self.metadata.update(kwargs) + self.metadata.update(kwargs) else: - self.metadata = kwargs + self.metadata = kwargs else: self.metadata = self.metadata.copy() if config is not None: @@ -470,14 +470,14 @@ class TraitType(BaseDescriptor): Use self.default_value instead """ - warn("get_default_value is deprecated in traitlets 4.0: use the .default_value attribute", DeprecationWarning, + warn("get_default_value is deprecated in traitlets 4.0: use the .default_value attribute", DeprecationWarning, stacklevel=2) return self.default_value def init_default_value(self, obj): """DEPRECATED: Set the static default value for the trait type. """ - warn("init_default_value is deprecated in traitlets 4.0, and may be removed in the future", DeprecationWarning, + warn("init_default_value is deprecated in traitlets 4.0, and may be removed in the future", DeprecationWarning, stacklevel=2) value = self._validate(obj, self.default_value) obj._trait_values[self.name] = value @@ -488,7 +488,7 @@ class TraitType(BaseDescriptor): This looks for: - * default generators registered with the @default descriptor. + * default generators registered with the @default descriptor. * obj._{name}_default() on the class with the traitlet, or a subclass that obj belongs to. * trait.make_dynamic_default, which is defined by Instance @@ -516,14 +516,14 @@ class TraitType(BaseDescriptor): def instance_init(self, obj): # If no dynamic initialiser is present, and the trait implementation or # use provides a static default, transfer that to obj._trait_values. - with obj.cross_validation_lock: - if (self._dynamic_default_callable(obj) is None) \ - and (self.default_value is not Undefined): - v = self._validate(obj, self.default_value) - if self.name is not None: - obj._trait_values[self.name] = v - - def get(self, obj, cls=None): + with obj.cross_validation_lock: + if (self._dynamic_default_callable(obj) is None) \ + and (self.default_value is not Undefined): + v = self._validate(obj, self.default_value) + if self.name is not None: + obj._trait_values[self.name] = v + + def get(self, obj, cls=None): try: value = obj._trait_values[self.name] except KeyError: @@ -595,7 +595,7 @@ class TraitType(BaseDescriptor): def _cross_validate(self, obj, value): if self.name in obj._trait_validators: - proposal = Bunch({'trait': self, 'value': value, 'owner': obj}) + proposal = Bunch({'trait': self, 'value': value, 'owner': obj}) value = obj._trait_validators[self.name](obj, proposal) elif hasattr(obj, '_%s_validate' % self.name): meth_name = '_%s_validate' % self.name @@ -633,7 +633,7 @@ class TraitType(BaseDescriptor): msg = "use the instance .help string directly, like x.help" else: msg = "use the instance .metadata dictionary directly, like x.metadata[key] or x.metadata.get(key, default)" - warn("Deprecated in traitlets 4.1, " + msg, DeprecationWarning, stacklevel=2) + warn("Deprecated in traitlets 4.1, " + msg, DeprecationWarning, stacklevel=2) return self.metadata.get(key, default) def set_metadata(self, key, value): @@ -645,7 +645,7 @@ class TraitType(BaseDescriptor): msg = "use the instance .help string directly, like x.help = value" else: msg = "use the instance .metadata dictionary directly, like x.metadata[key] = value" - warn("Deprecated in traitlets 4.1, " + msg, DeprecationWarning, stacklevel=2) + warn("Deprecated in traitlets 4.1, " + msg, DeprecationWarning, stacklevel=2) self.metadata[key] = value def tag(self, **metadata): @@ -655,11 +655,11 @@ class TraitType(BaseDescriptor): >>> Int(0).tag(config=True, sync=True) """ - maybe_constructor_keywords = set(metadata.keys()).intersection({'help','allow_none', 'read_only', 'default_value'}) - if maybe_constructor_keywords: - warn('The following attributes are set in using `tag`, but seem to be constructor keywords arguments: %s '% - maybe_constructor_keywords, UserWarning, stacklevel=2) - + maybe_constructor_keywords = set(metadata.keys()).intersection({'help','allow_none', 'read_only', 'default_value'}) + if maybe_constructor_keywords: + warn('The following attributes are set in using `tag`, but seem to be constructor keywords arguments: %s '% + maybe_constructor_keywords, UserWarning, stacklevel=2) + self.metadata.update(metadata) return self @@ -697,13 +697,13 @@ class _CallbackWrapper(object): if self.nargs == 0: self.cb() elif self.nargs == 1: - self.cb(change.name) + self.cb(change.name) elif self.nargs == 2: - self.cb(change.name, change.new) + self.cb(change.name, change.new) elif self.nargs == 3: - self.cb(change.name, change.old, change.new) + self.cb(change.name, change.old, change.new) elif self.nargs == 4: - self.cb(change.name, change.old, change.new, change.owner) + self.cb(change.name, change.old, change.new, change.owner) def _callback_wrapper(cb): if isinstance(cb, _CallbackWrapper): @@ -721,13 +721,13 @@ class MetaHasDescriptors(type): def __new__(mcls, name, bases, classdict): """Create the HasDescriptors class.""" - for k, v in classdict.items(): + for k, v in classdict.items(): # ---------------------------------------------------------------- # Support of deprecated behavior allowing for TraitType types # to be used instead of TraitType instances. if inspect.isclass(v) and issubclass(v, TraitType): - warn("Traits should be given as instances, not types (for example, `Int()`, not `Int`)." - " Passing types is deprecated in traitlets 4.1.", + warn("Traits should be given as instances, not types (for example, `Int()`, not `Int`)." + " Passing types is deprecated in traitlets 4.1.", DeprecationWarning, stacklevel=2) classdict[k] = v() # ---------------------------------------------------------------- @@ -746,7 +746,7 @@ class MetaHasDescriptors(type): BaseDescriptor in the class dict of the newly created ``cls`` before calling their :attr:`class_init` method. """ - for k, v in classdict.items(): + for k, v in classdict.items(): if isinstance(v, BaseDescriptor): v.class_init(cls, k) @@ -762,10 +762,10 @@ class MetaHasTraits(MetaHasDescriptors): def observe(*names, **kwargs): """A decorator which can be used to observe Traits on a class. - The handler passed to the decorator will be called with one ``change`` - dict argument. The change dictionary at least holds a 'type' key and a - 'name' key, corresponding respectively to the type of notification and the - name of the attribute that triggered the notification. + The handler passed to the decorator will be called with one ``change`` + dict argument. The change dictionary at least holds a 'type' key and a + 'name' key, corresponding respectively to the type of notification and the + name of the attribute that triggered the notification. Other keys may be passed depending on the value of 'type'. In the case where type is 'change', we also have the following keys: @@ -778,27 +778,27 @@ def observe(*names, **kwargs): ---------- *names The str names of the Traits to observe on the object. - type: str, kwarg-only - The type of event to observe (e.g. 'change') + type: str, kwarg-only + The type of event to observe (e.g. 'change') """ - if not names: - raise TypeError("Please specify at least one trait name to observe.") - for name in names: - if name is not All and not isinstance(name, six.string_types): - raise TypeError("trait names to observe must be strings or All, not %r" % name) + if not names: + raise TypeError("Please specify at least one trait name to observe.") + for name in names: + if name is not All and not isinstance(name, six.string_types): + raise TypeError("trait names to observe must be strings or All, not %r" % name) return ObserveHandler(names, type=kwargs.get('type', 'change')) def observe_compat(func): """Backward-compatibility shim decorator for observers - + Use with: - + @observe('name') @observe_compat def _foo_changed(self, change): ... - + With this, `super()._foo_changed(self, name, old, new)` in subclasses will still work. Allows adoption of new observer API without breaking subclasses that override and super. """ @@ -807,15 +807,15 @@ def observe_compat(func): change = change_or_name else: clsname = self.__class__.__name__ - warn("A parent of %s._%s_changed has adopted the new (traitlets 4.1) @observe(change) API" % ( + warn("A parent of %s._%s_changed has adopted the new (traitlets 4.1) @observe(change) API" % ( clsname, change_or_name), DeprecationWarning) - change = Bunch( - type='change', - old=old, - new=new, - name=change_or_name, - owner=self, - ) + change = Bunch( + type='change', + old=old, + new=new, + name=change_or_name, + owner=self, + ) return func(self, change) return compatible_observer @@ -837,18 +837,18 @@ def validate(*names): Notes ----- - Since the owner has access to the ``HasTraits`` instance via the 'owner' key, + Since the owner has access to the ``HasTraits`` instance via the 'owner' key, the registered cross validator could potentially make changes to attributes of the ``HasTraits`` instance. However, we recommend not to do so. The reason is that the cross-validation of attributes may run in arbitrary order when - exiting the ``hold_trait_notifications`` context, and such changes may not + exiting the ``hold_trait_notifications`` context, and such changes may not commute. """ - if not names: - raise TypeError("Please specify at least one trait name to validate.") - for name in names: - if name is not All and not isinstance(name, six.string_types): - raise TypeError("trait names to validate must be strings or All, not %r" % name) + if not names: + raise TypeError("Please specify at least one trait name to validate.") + for name in names: + if name is not All and not isinstance(name, six.string_types): + raise TypeError("trait names to validate must be strings or All, not %r" % name) return ValidateHandler(names) @@ -890,8 +890,8 @@ def default(name): return 3.0 # ignored since it is defined in a # class derived from B.a.this_class. """ - if not isinstance(name, six.string_types): - raise TypeError("Trait name must be a string or All, not %r" % name) + if not isinstance(name, six.string_types): + raise TypeError("Trait name must be a string or All, not %r" % name) return DefaultHandler(name) @@ -902,7 +902,7 @@ class EventHandler(BaseDescriptor): return self def __call__(self, *args, **kwargs): - """Pass `*args` and `**kwargs` to the handler's function if it exists.""" + """Pass `*args` and `**kwargs` to the handler's function if it exists.""" if hasattr(self, 'func'): return self.func(*args, **kwargs) else: @@ -943,26 +943,26 @@ class DefaultHandler(EventHandler): cls._trait_default_generators[self.trait_name] = self -class HasDescriptors(six.with_metaclass(MetaHasDescriptors, object)): +class HasDescriptors(six.with_metaclass(MetaHasDescriptors, object)): """The base class for all classes that have descriptors. """ - def __new__(cls, *args, **kwargs): + def __new__(cls, *args, **kwargs): # This is needed because object.__new__ only accepts # the cls argument. new_meth = super(HasDescriptors, cls).__new__ if new_meth is object.__new__: inst = new_meth(cls) else: - inst = new_meth(cls, *args, **kwargs) - inst.setup_instance(*args, **kwargs) + inst = new_meth(cls, *args, **kwargs) + inst.setup_instance(*args, **kwargs) return inst - def setup_instance(self, *args, **kwargs): - """ - This is called **before** self.__init__ is called. - """ - self._cross_validation_lock = False + def setup_instance(self, *args, **kwargs): + """ + This is called **before** self.__init__ is called. + """ + self._cross_validation_lock = False cls = self.__class__ for key in dir(cls): # Some descriptors raise AttributeError like zope.interface's @@ -977,46 +977,46 @@ class HasDescriptors(six.with_metaclass(MetaHasDescriptors, object)): value.instance_init(self) -class HasTraits(six.with_metaclass(MetaHasTraits, HasDescriptors)): +class HasTraits(six.with_metaclass(MetaHasTraits, HasDescriptors)): - def setup_instance(self, *args, **kwargs): + def setup_instance(self, *args, **kwargs): self._trait_values = {} self._trait_notifiers = {} self._trait_validators = {} - super(HasTraits, self).setup_instance(*args, **kwargs) + super(HasTraits, self).setup_instance(*args, **kwargs) - def __init__(self, *args, **kwargs): + def __init__(self, *args, **kwargs): # Allow trait values to be set using keyword arguments. # We need to use setattr for this to trigger validation and # notifications. - super_args = args - super_kwargs = {} + super_args = args + super_kwargs = {} with self.hold_trait_notifications(): - for key, value in kwargs.items(): - if self.has_trait(key): - setattr(self, key, value) - else: - # passthrough args that don't set traits to super - super_kwargs[key] = value - try: - super(HasTraits, self).__init__(*super_args, **super_kwargs) - except TypeError as e: - arg_s_list = [ repr(arg) for arg in super_args ] - for k, v in super_kwargs.items(): - arg_s_list.append("%s=%r" % (k, v)) - arg_s = ', '.join(arg_s_list) - warn( - "Passing unrecoginized arguments to super({classname}).__init__({arg_s}).\n" - "{error}\n" - "This is deprecated in traitlets 4.2." - "This error will be raised in a future release of traitlets." - .format( - arg_s=arg_s, classname=self.__class__.__name__, - error=e, - ), - DeprecationWarning, - stacklevel=2, - ) + for key, value in kwargs.items(): + if self.has_trait(key): + setattr(self, key, value) + else: + # passthrough args that don't set traits to super + super_kwargs[key] = value + try: + super(HasTraits, self).__init__(*super_args, **super_kwargs) + except TypeError as e: + arg_s_list = [ repr(arg) for arg in super_args ] + for k, v in super_kwargs.items(): + arg_s_list.append("%s=%r" % (k, v)) + arg_s = ', '.join(arg_s_list) + warn( + "Passing unrecoginized arguments to super({classname}).__init__({arg_s}).\n" + "{error}\n" + "This is deprecated in traitlets 4.2." + "This error will be raised in a future release of traitlets." + .format( + arg_s=arg_s, classname=self.__class__.__name__, + error=e, + ), + DeprecationWarning, + stacklevel=2, + ) def __getstate__(self): d = self.__dict__.copy() @@ -1044,27 +1044,27 @@ class HasTraits(six.with_metaclass(MetaHasTraits, HasDescriptors)): if isinstance(value, EventHandler): value.instance_init(self) - @property - @contextlib.contextmanager - def cross_validation_lock(self): - """ - A contextmanager for running a block with our cross validation lock set - to True. - - At the end of the block, the lock's value is restored to its value - prior to entering the block. - """ - if self._cross_validation_lock: - yield - return - else: - try: - self._cross_validation_lock = True - yield - finally: - self._cross_validation_lock = False - + @property @contextlib.contextmanager + def cross_validation_lock(self): + """ + A contextmanager for running a block with our cross validation lock set + to True. + + At the end of the block, the lock's value is restored to its value + prior to entering the block. + """ + if self._cross_validation_lock: + yield + return + else: + try: + self._cross_validation_lock = True + yield + finally: + self._cross_validation_lock = False + + @contextlib.contextmanager def hold_trait_notifications(self): """Context manager for bundling trait change notifications and cross validation. @@ -1073,7 +1073,7 @@ class HasTraits(six.with_metaclass(MetaHasTraits, HasDescriptors)): race conditions in trait notifiers requesting other trait values. All trait notifications will fire after all values have been assigned. """ - if self._cross_validation_lock: + if self._cross_validation_lock: yield return else: @@ -1085,15 +1085,15 @@ class HasTraits(six.with_metaclass(MetaHasTraits, HasDescriptors)): if past_changes is None: return [change] else: - if past_changes[-1]['type'] == 'change' and change.type == 'change': - past_changes[-1]['new'] = change.new + if past_changes[-1]['type'] == 'change' and change.type == 'change': + past_changes[-1]['new'] = change.new else: # In case of changes other than 'change', append the notification. past_changes.append(change) return past_changes def hold(change): - name = change.name + name = change.name cache[name] = compress(cache.get(name), change) try: @@ -1106,24 +1106,24 @@ class HasTraits(six.with_metaclass(MetaHasTraits, HasDescriptors)): for name in list(cache.keys()): trait = getattr(self.__class__, name) value = trait._cross_validate(self, getattr(self, name)) - self.set_trait(name, value) + self.set_trait(name, value) except TraitError as e: # Roll back in case of TraitError during final cross validation. self.notify_change = lambda x: None for name, changes in cache.items(): for change in changes[::-1]: # TODO: Separate in a rollback function per notification type. - if change.type == 'change': - if change.old is not Undefined: - self.set_trait(name, change.old) + if change.type == 'change': + if change.old is not Undefined: + self.set_trait(name, change.old) else: self._trait_values.pop(name) cache = {} raise e finally: self._cross_validation_lock = False - # Restore method retrieval from class - del self.notify_change + # Restore method retrieval from class + del self.notify_change # trigger delayed notifications for changes in cache.values(): @@ -1131,19 +1131,19 @@ class HasTraits(six.with_metaclass(MetaHasTraits, HasDescriptors)): self.notify_change(change) def _notify_trait(self, name, old_value, new_value): - self.notify_change(Bunch( - name=name, - old=old_value, - new=new_value, - owner=self, - type='change', - )) + self.notify_change(Bunch( + name=name, + old=old_value, + new=new_value, + owner=self, + type='change', + )) def notify_change(self, change): - if not isinstance(change, Bunch): - # cast to bunch if given a dict - change = Bunch(change) - name, type = change.name, change.type + if not isinstance(change, Bunch): + # cast to bunch if given a dict + change = Bunch(change) + name, type = change.name, change.type callables = [] callables.extend(self._trait_notifiers.get(name, {}).get(type, [])) @@ -1170,9 +1170,9 @@ class HasTraits(six.with_metaclass(MetaHasTraits, HasDescriptors)): if isinstance(c, _CallbackWrapper): c = c.__call__ - elif isinstance(c, EventHandler) and c.name is not None: + elif isinstance(c, EventHandler) and c.name is not None: c = getattr(self, c.name) - + c(change) def _add_notifiers(self, handler, name, type): @@ -1225,7 +1225,7 @@ class HasTraits(six.with_metaclass(MetaHasTraits, HasDescriptors)): If False (the default), then install the handler. If True then unintall it. """ - warn("on_trait_change is deprecated in traitlets 4.1: use observe instead", + warn("on_trait_change is deprecated in traitlets 4.1: use observe instead", DeprecationWarning, stacklevel=2) if name is None: name = All @@ -1243,8 +1243,8 @@ class HasTraits(six.with_metaclass(MetaHasTraits, HasDescriptors)): ---------- handler : callable A callable that is called when a trait changes. Its - signature should be ``handler(change)``, where ``change`` is a - dictionary. The change dictionary at least holds a 'type' key. + signature should be ``handler(change)``, where ``change`` is a + dictionary. The change dictionary at least holds a 'type' key. * ``type``: the type of notification. Other keys may be passed depending on the value of 'type'. In the case where type is 'change', we also have the following keys: @@ -1267,7 +1267,7 @@ class HasTraits(six.with_metaclass(MetaHasTraits, HasDescriptors)): def unobserve(self, handler, names=All, type='change'): """Remove a trait change handler. - This is used to unregister handlers to trait change notifications. + This is used to unregister handlers to trait change notifications. Parameters ---------- @@ -1297,19 +1297,19 @@ class HasTraits(six.with_metaclass(MetaHasTraits, HasDescriptors)): pass def _register_validator(self, handler, names): - """Setup a handler to be called when a trait should be cross validated. + """Setup a handler to be called when a trait should be cross validated. This is used to setup dynamic notifications for cross-validation. If a validator is already registered for any of the provided names, a - TraitError is raised and no new validator is registered. + TraitError is raised and no new validator is registered. Parameters ---------- handler : callable A callable that is called when the given trait is cross-validated. - Its signature is handler(proposal), where proposal is a Bunch (dictionary with attribute access) - with the following attributes/keys: + Its signature is handler(proposal), where proposal is a Bunch (dictionary with attribute access) + with the following attributes/keys: * ``owner`` : the HasTraits instance * ``value`` : the proposed value for the modified trait attribute * ``trait`` : the TraitType instance associated with the attribute @@ -1326,22 +1326,22 @@ class HasTraits(six.with_metaclass(MetaHasTraits, HasDescriptors)): for name in names: self._trait_validators[name] = handler - def add_traits(self, **traits): - """Dynamically add trait attributes to the HasTraits instance.""" - self.__class__ = type(self.__class__.__name__, (self.__class__,), - traits) - for trait in traits.values(): - trait.instance_init(self) - - def set_trait(self, name, value): - """Forcibly sets trait attribute, including read-only attributes.""" - cls = self.__class__ - if not self.has_trait(name): - raise TraitError("Class %s does not have a trait named %s" % - (cls.__name__, name)) - else: - getattr(cls, name).set(self, value) - + def add_traits(self, **traits): + """Dynamically add trait attributes to the HasTraits instance.""" + self.__class__ = type(self.__class__.__name__, (self.__class__,), + traits) + for trait in traits.values(): + trait.instance_init(self) + + def set_trait(self, name, value): + """Forcibly sets trait attribute, including read-only attributes.""" + cls = self.__class__ + if not self.has_trait(name): + raise TraitError("Class %s does not have a trait named %s" % + (cls.__name__, name)) + else: + getattr(cls, name).set(self, value) + @classmethod def class_trait_names(cls, **metadata): """Get a list of all the names of this class' traits. @@ -1349,7 +1349,7 @@ class HasTraits(six.with_metaclass(MetaHasTraits, HasDescriptors)): This method is just like the :meth:`trait_names` method, but is unbound. """ - return list(cls.class_traits(**metadata)) + return list(cls.class_traits(**metadata)) @classmethod def class_traits(cls, **metadata): @@ -1399,10 +1399,10 @@ class HasTraits(six.with_metaclass(MetaHasTraits, HasDescriptors)): def has_trait(self, name): """Returns True if the object has a trait with the specified name.""" return isinstance(getattr(self.__class__, name, None), TraitType) - + def trait_names(self, **metadata): """Get a list of all the names of this class' traits.""" - return list(self.traits(**metadata)) + return list(self.traits(**metadata)) def traits(self, **metadata): """Get a ``dict`` of all the traits of this class. The dictionary @@ -1443,48 +1443,48 @@ class HasTraits(six.with_metaclass(MetaHasTraits, HasDescriptors)): except AttributeError: raise TraitError("Class %s does not have a trait named %s" % (self.__class__.__name__, traitname)) - metadata_name = '_' + traitname + '_metadata' - if hasattr(self, metadata_name) and key in getattr(self, metadata_name): - return getattr(self, metadata_name).get(key, default) + metadata_name = '_' + traitname + '_metadata' + if hasattr(self, metadata_name) and key in getattr(self, metadata_name): + return getattr(self, metadata_name).get(key, default) else: return trait.metadata.get(key, default) - @classmethod - def class_own_trait_events(cls, name): - """Get a dict of all event handlers defined on this class, not a parent. - - Works like ``event_handlers``, except for excluding traits from parents. - """ - sup = super(cls, cls) - return {n: e for (n, e) in cls.events(name).items() - if getattr(sup, n, None) is not e} - - @classmethod - def trait_events(cls, name=None): - """Get a ``dict`` of all the event handlers of this class. - - Parameters - ---------- - name: str (default: None) - The name of a trait of this class. If name is ``None`` then all - the event handlers of this class will be returned instead. - - Returns - ------- - The event handlers associated with a trait name, or all event handlers. - """ - events = {} - for k, v in getmembers(cls): - if isinstance(v, EventHandler): - if name is None: - events[k] = v - elif name in v.trait_names: - events[k] = v - elif hasattr(v, 'tags'): - if cls.trait_names(**v.tags): - events[k] = v - return events - + @classmethod + def class_own_trait_events(cls, name): + """Get a dict of all event handlers defined on this class, not a parent. + + Works like ``event_handlers``, except for excluding traits from parents. + """ + sup = super(cls, cls) + return {n: e for (n, e) in cls.events(name).items() + if getattr(sup, n, None) is not e} + + @classmethod + def trait_events(cls, name=None): + """Get a ``dict`` of all the event handlers of this class. + + Parameters + ---------- + name: str (default: None) + The name of a trait of this class. If name is ``None`` then all + the event handlers of this class will be returned instead. + + Returns + ------- + The event handlers associated with a trait name, or all event handlers. + """ + events = {} + for k, v in getmembers(cls): + if isinstance(v, EventHandler): + if name is None: + events[k] = v + elif name in v.trait_names: + events[k] = v + elif hasattr(v, 'tags'): + if cls.trait_names(**v.tags): + events[k] = v + return events + #----------------------------------------------------------------------------- # Actual TraitTypes implementations/subclasses #----------------------------------------------------------------------------- @@ -1508,7 +1508,7 @@ class ClassBasedTraitType(TraitType): def error(self, obj, value): kind = type(value) - if six.PY2 and kind is InstanceType: + if six.PY2 and kind is InstanceType: msg = 'class %s' % value.__class__.__name__ else: msg = '%s (i.e. %s)' % ( str( kind )[1:-1], repr( value ) ) @@ -1527,7 +1527,7 @@ class ClassBasedTraitType(TraitType): class Type(ClassBasedTraitType): """A trait whose value must be a subclass of a specified class.""" - def __init__ (self, default_value=Undefined, klass=None, **kwargs): + def __init__ (self, default_value=Undefined, klass=None, **kwargs): """Construct a Type trait A Type trait specifies that its values must be subclasses of @@ -1562,16 +1562,16 @@ class Type(ClassBasedTraitType): else: klass = default_value - if not (inspect.isclass(klass) or isinstance(klass, six.string_types)): + if not (inspect.isclass(klass) or isinstance(klass, six.string_types)): raise TraitError("A Type trait must specify a class.") self.klass = klass - super(Type, self).__init__(new_default_value, **kwargs) + super(Type, self).__init__(new_default_value, **kwargs) def validate(self, obj, value): """Validates that the value is a valid object instance.""" - if isinstance(value, six.string_types): + if isinstance(value, six.string_types): try: value = self._resolve_string(value) except ImportError: @@ -1587,10 +1587,10 @@ class Type(ClassBasedTraitType): def info(self): """ Returns a description of the trait.""" - if isinstance(self.klass, six.string_types): + if isinstance(self.klass, six.string_types): klass = self.klass else: - klass = self.klass.__module__ + '.' + self.klass.__name__ + klass = self.klass.__module__ + '.' + self.klass.__name__ result = "a subclass of '%s'" % klass if self.allow_none: return result + ' or None' @@ -1601,14 +1601,14 @@ class Type(ClassBasedTraitType): super(Type, self).instance_init(obj) def _resolve_classes(self): - if isinstance(self.klass, six.string_types): + if isinstance(self.klass, six.string_types): self.klass = self._resolve_string(self.klass) - if isinstance(self.default_value, six.string_types): + if isinstance(self.default_value, six.string_types): self.default_value = self._resolve_string(self.default_value) def default_value_repr(self): value = self.default_value - if isinstance(value, six.string_types): + if isinstance(value, six.string_types): return repr(value) else: return repr('{}.{}'.format(value.__module__, value.__name__)) @@ -1624,7 +1624,7 @@ class Instance(ClassBasedTraitType): klass = None - def __init__(self, klass=None, args=None, kw=None, **kwargs): + def __init__(self, klass=None, args=None, kw=None, **kwargs): """Construct an Instance trait. This trait allows values that are instances of a particular @@ -1653,8 +1653,8 @@ class Instance(ClassBasedTraitType): """ if klass is None: klass = self.klass - - if (klass is not None) and (inspect.isclass(klass) or isinstance(klass, six.string_types)): + + if (klass is not None) and (inspect.isclass(klass) or isinstance(klass, six.string_types)): self.klass = klass else: raise TraitError('The klass attribute must be a class' @@ -1668,7 +1668,7 @@ class Instance(ClassBasedTraitType): self.default_args = args self.default_kwargs = kw - super(Instance, self).__init__(**kwargs) + super(Instance, self).__init__(**kwargs) def validate(self, obj, value): if isinstance(value, self.klass): @@ -1677,7 +1677,7 @@ class Instance(ClassBasedTraitType): self.error(obj, value) def info(self): - if isinstance(self.klass, six.string_types): + if isinstance(self.klass, six.string_types): klass = self.klass else: klass = self.klass.__name__ @@ -1692,7 +1692,7 @@ class Instance(ClassBasedTraitType): super(Instance, self).instance_init(obj) def _resolve_classes(self): - if isinstance(self.klass, six.string_types): + if isinstance(self.klass, six.string_types): self.klass = self._resolve_string(self.klass) def make_dynamic_default(self): @@ -1742,8 +1742,8 @@ class This(ClassBasedTraitType): info_text = 'an instance of the same type as the receiver or None' - def __init__(self, **kwargs): - super(This, self).__init__(None, **kwargs) + def __init__(self, **kwargs): + super(This, self).__init__(None, **kwargs) def validate(self, obj, value): # What if value is a superclass of obj.__class__? This is @@ -1758,7 +1758,7 @@ class This(ClassBasedTraitType): class Union(TraitType): """A trait type representing a Union type.""" - def __init__(self, trait_types, **kwargs): + def __init__(self, trait_types, **kwargs): """Construct a Union trait. This trait allows values that are allowed by at least one of the @@ -1776,8 +1776,8 @@ class Union(TraitType): with the validation function of Float, then Bool, and finally Int. """ self.trait_types = trait_types - self.info_text = " or ".join([tt.info() for tt in self.trait_types]) - super(Union, self).__init__(**kwargs) + self.info_text = " or ".join([tt.info() for tt in self.trait_types]) + super(Union, self).__init__(**kwargs) def class_init(self, cls, name): for trait_type in self.trait_types: @@ -1790,13 +1790,13 @@ class Union(TraitType): super(Union, self).instance_init(obj) def validate(self, obj, value): - with obj.cross_validation_lock: + with obj.cross_validation_lock: for trait_type in self.trait_types: try: v = trait_type._validate(obj, value) - # In the case of an element trait, the name is None - if self.name is not None: - setattr(obj, '_' + self.name + '_metadata', trait_type.metadata) + # In the case of an element trait, the name is None + if self.name is not None: + setattr(obj, '_' + self.name + '_metadata', trait_type.metadata) return v except TraitError: continue @@ -1808,16 +1808,16 @@ class Union(TraitType): else: return Union(self.trait_types + [other]) - def make_dynamic_default(self): - if self.default_value is not Undefined: - return self.default_value - for trait_type in self.trait_types: - if trait_type.default_value is not Undefined: - return trait_type.default_value - elif hasattr(trait_type, 'make_dynamic_default'): - return trait_type.make_dynamic_default() - - + def make_dynamic_default(self): + if self.default_value is not Undefined: + return self.default_value + for trait_type in self.trait_types: + if trait_type.default_value is not Undefined: + return trait_type.default_value + elif hasattr(trait_type, 'make_dynamic_default'): + return trait_type.make_dynamic_default() + + #----------------------------------------------------------------------------- # Basic TraitTypes implementations/subclasses #----------------------------------------------------------------------------- @@ -1829,37 +1829,37 @@ class Any(TraitType): info_text = 'any value' -def _validate_bounds(trait, obj, value): - """ - Validate that a number to be applied to a trait is between bounds. - - If value is not between min_bound and max_bound, this raises a - TraitError with an error message appropriate for this trait. - """ - if trait.min is not None and value < trait.min: - raise TraitError( - "The value of the '{name}' trait of {klass} instance should " - "not be less than {min_bound}, but a value of {value} was " - "specified".format( - name=trait.name, klass=class_of(obj), - value=value, min_bound=trait.min)) - if trait.max is not None and value > trait.max: - raise TraitError( - "The value of the '{name}' trait of {klass} instance should " - "not be greater than {max_bound}, but a value of {value} was " - "specified".format( - name=trait.name, klass=class_of(obj), - value=value, max_bound=trait.max)) - return value - - +def _validate_bounds(trait, obj, value): + """ + Validate that a number to be applied to a trait is between bounds. + + If value is not between min_bound and max_bound, this raises a + TraitError with an error message appropriate for this trait. + """ + if trait.min is not None and value < trait.min: + raise TraitError( + "The value of the '{name}' trait of {klass} instance should " + "not be less than {min_bound}, but a value of {value} was " + "specified".format( + name=trait.name, klass=class_of(obj), + value=value, min_bound=trait.min)) + if trait.max is not None and value > trait.max: + raise TraitError( + "The value of the '{name}' trait of {klass} instance should " + "not be greater than {max_bound}, but a value of {value} was " + "specified".format( + name=trait.name, klass=class_of(obj), + value=value, max_bound=trait.max)) + return value + + class Int(TraitType): """An int trait.""" default_value = 0 info_text = 'an int' - def __init__(self, default_value=Undefined, allow_none=False, **kwargs): + def __init__(self, default_value=Undefined, allow_none=False, **kwargs): self.min = kwargs.pop('min', None) self.max = kwargs.pop('max', None) super(Int, self).__init__(default_value=default_value, @@ -1868,7 +1868,7 @@ class Int(TraitType): def validate(self, obj, value): if not isinstance(value, int): self.error(obj, value) - return _validate_bounds(self, obj, value) + return _validate_bounds(self, obj, value) class CInt(Int): @@ -1876,49 +1876,49 @@ class CInt(Int): def validate(self, obj, value): try: - value = int(value) + value = int(value) except: self.error(obj, value) - return _validate_bounds(self, obj, value) - + return _validate_bounds(self, obj, value) -if six.PY2: + +if six.PY2: class Long(TraitType): """A long integer trait.""" default_value = 0 info_text = 'a long' - def __init__(self, default_value=Undefined, allow_none=False, **kwargs): - self.min = kwargs.pop('min', None) - self.max = kwargs.pop('max', None) - super(Long, self).__init__( - default_value=default_value, - allow_none=allow_none, **kwargs) - - def _validate_long(self, obj, value): + def __init__(self, default_value=Undefined, allow_none=False, **kwargs): + self.min = kwargs.pop('min', None) + self.max = kwargs.pop('max', None) + super(Long, self).__init__( + default_value=default_value, + allow_none=allow_none, **kwargs) + + def _validate_long(self, obj, value): if isinstance(value, long): return value if isinstance(value, int): return long(value) self.error(obj, value) - def validate(self, obj, value): - value = self._validate_long(obj, value) - return _validate_bounds(self, obj, value) - + def validate(self, obj, value): + value = self._validate_long(obj, value) + return _validate_bounds(self, obj, value) + class CLong(Long): """A casting version of the long integer trait.""" def validate(self, obj, value): try: - value = long(value) + value = long(value) except: self.error(obj, value) - return _validate_bounds(self, obj, value) - + return _validate_bounds(self, obj, value) + class Integer(TraitType): """An integer trait. @@ -1927,14 +1927,14 @@ if six.PY2: default_value = 0 info_text = 'an integer' - def __init__(self, default_value=Undefined, allow_none=False, **kwargs): - self.min = kwargs.pop('min', None) - self.max = kwargs.pop('max', None) - super(Integer, self).__init__( - default_value=default_value, - allow_none=allow_none, **kwargs) - - def _validate_int(self, obj, value): + def __init__(self, default_value=Undefined, allow_none=False, **kwargs): + self.min = kwargs.pop('min', None) + self.max = kwargs.pop('max', None) + super(Integer, self).__init__( + default_value=default_value, + allow_none=allow_none, **kwargs) + + def _validate_int(self, obj, value): if isinstance(value, int): return value if isinstance(value, long): @@ -1948,25 +1948,25 @@ if six.PY2: return int(value) self.error(obj, value) - def validate(self, obj, value): - value = self._validate_int(obj, value) - return _validate_bounds(self, obj, value) - -else: - Long, CLong = Int, CInt - Integer = Int - + def validate(self, obj, value): + value = self._validate_int(obj, value) + return _validate_bounds(self, obj, value) +else: + Long, CLong = Int, CInt + Integer = Int + + class Float(TraitType): """A float trait.""" default_value = 0.0 info_text = 'a float' - def __init__(self, default_value=Undefined, allow_none=False, **kwargs): + def __init__(self, default_value=Undefined, allow_none=False, **kwargs): self.min = kwargs.pop('min', -float('inf')) self.max = kwargs.pop('max', float('inf')) - super(Float, self).__init__(default_value=default_value, + super(Float, self).__init__(default_value=default_value, allow_none=allow_none, **kwargs) def validate(self, obj, value): @@ -1974,7 +1974,7 @@ class Float(TraitType): value = float(value) if not isinstance(value, float): self.error(obj, value) - return _validate_bounds(self, obj, value) + return _validate_bounds(self, obj, value) class CFloat(Float): @@ -1982,12 +1982,12 @@ class CFloat(Float): def validate(self, obj, value): try: - value = float(value) + value = float(value) except: self.error(obj, value) - return _validate_bounds(self, obj, value) - + return _validate_bounds(self, obj, value) + class Complex(TraitType): """A trait for complex numbers.""" @@ -2043,7 +2043,7 @@ class Unicode(TraitType): info_text = 'a unicode string' def validate(self, obj, value): - if isinstance(value, six.text_type): + if isinstance(value, six.text_type): return value if isinstance(value, bytes): try: @@ -2059,7 +2059,7 @@ class CUnicode(Unicode): def validate(self, obj, value): try: - return six.text_type(value) + return six.text_type(value) except: self.error(obj, value) @@ -2070,7 +2070,7 @@ class ObjectName(TraitType): This does not check that the name exists in any scope.""" info_text = "a valid object identifier in Python" - if six.PY2: + if six.PY2: # Python 2: def coerce_str(self, obj, value): "In Python 2, coerce ascii-only unicode to str" @@ -2080,13 +2080,13 @@ class ObjectName(TraitType): except UnicodeEncodeError: self.error(obj, value) return value - else: - coerce_str = staticmethod(lambda _,s: s) + else: + coerce_str = staticmethod(lambda _,s: s) def validate(self, obj, value): value = self.coerce_str(obj, value) - if isinstance(value, six.string_types) and isidentifier(value): + if isinstance(value, six.string_types) and isidentifier(value): return value self.error(obj, value) @@ -2095,8 +2095,8 @@ class DottedObjectName(ObjectName): def validate(self, obj, value): value = self.coerce_str(obj, value) - if isinstance(value, six.string_types) and all(isidentifier(a) - for a in value.split('.')): + if isinstance(value, six.string_types) and all(isidentifier(a) + for a in value.split('.')): return value self.error(obj, value) @@ -2126,11 +2126,11 @@ class CBool(Bool): class Enum(TraitType): """An enum whose value must be in a given sequence.""" - def __init__(self, values, default_value=Undefined, **kwargs): + def __init__(self, values, default_value=Undefined, **kwargs): self.values = values - if kwargs.get('allow_none', False) and default_value is Undefined: + if kwargs.get('allow_none', False) and default_value is Undefined: default_value = None - super(Enum, self).__init__(default_value, **kwargs) + super(Enum, self).__init__(default_value, **kwargs) def validate(self, obj, value): if value in self.values: @@ -2146,15 +2146,15 @@ class Enum(TraitType): class CaselessStrEnum(Enum): """An enum of strings where the case should be ignored.""" - - def __init__(self, values, default_value=Undefined, **kwargs): - values = [cast_unicode_py2(value) for value in values] - super(CaselessStrEnum, self).__init__(values, default_value=default_value, **kwargs) - + + def __init__(self, values, default_value=Undefined, **kwargs): + values = [cast_unicode_py2(value) for value in values] + super(CaselessStrEnum, self).__init__(values, default_value=default_value, **kwargs) + def validate(self, obj, value): if isinstance(value, str): - value = cast_unicode_py2(value) - if not isinstance(value, six.string_types): + value = cast_unicode_py2(value) + if not isinstance(value, six.string_types): self.error(obj, value) for v in self.values: @@ -2172,7 +2172,7 @@ class Container(Instance): _valid_defaults = SequenceTypes _trait = None - def __init__(self, trait=None, default_value=None, **kwargs): + def __init__(self, trait=None, default_value=None, **kwargs): """Create a container trait type from a list, set, or tuple. The default value is created by doing ``List(default_value)``, @@ -2200,7 +2200,7 @@ class Container(Instance): allow_none : bool [ default False ] Whether to allow the value to be None - **kwargs : any + **kwargs : any further keys for extensions to the Trait (e.g. config) """ @@ -2218,14 +2218,14 @@ class Container(Instance): if is_trait(trait): if isinstance(trait, type): - warn("Traits should be given as instances, not types (for example, `Int()`, not `Int`)." - " Passing types is deprecated in traitlets 4.1.", + warn("Traits should be given as instances, not types (for example, `Int()`, not `Int`)." + " Passing types is deprecated in traitlets 4.1.", DeprecationWarning, stacklevel=3) self._trait = trait() if isinstance(trait, type) else trait elif trait is not None: raise TypeError("`trait` must be a Trait or None, got %s" % repr_type(trait)) - super(Container,self).__init__(klass=self.klass, args=args, **kwargs) + super(Container,self).__init__(klass=self.klass, args=args, **kwargs) def element_error(self, obj, element, validator): e = "Element of the '%s' trait of %s instance must be %s, but a value of %s was specified." \ @@ -2272,7 +2272,7 @@ class List(Container): klass = list _cast_types = (tuple,) - def __init__(self, trait=None, default_value=None, minlen=0, maxlen=sys.maxsize, **kwargs): + def __init__(self, trait=None, default_value=None, minlen=0, maxlen=sys.maxsize, **kwargs): """Create a List trait type from a list, set, or tuple. The default value is created by doing ``list(default_value)``, @@ -2306,7 +2306,7 @@ class List(Container): self._minlen = minlen self._maxlen = maxlen super(List, self).__init__(trait=trait, default_value=default_value, - **kwargs) + **kwargs) def length_error(self, obj, value): e = "The '%s' trait of %s instance must be of length %i <= L <= %i, but a value of %s was specified." \ @@ -2333,7 +2333,7 @@ class Set(List): # Redefine __init__ just to make the docstring more accurate. def __init__(self, trait=None, default_value=None, minlen=0, maxlen=sys.maxsize, - **kwargs): + **kwargs): """Create a Set trait type from a list, set, or tuple. The default value is created by doing ``set(default_value)``, @@ -2364,7 +2364,7 @@ class Set(List): maxlen : Int [ default sys.maxsize ] The maximum length of the input list """ - super(Set, self).__init__(trait, default_value, minlen, maxlen, **kwargs) + super(Set, self).__init__(trait, default_value, minlen, maxlen, **kwargs) class Tuple(Container): @@ -2372,7 +2372,7 @@ class Tuple(Container): klass = tuple _cast_types = (list,) - def __init__(self, *traits, **kwargs): + def __init__(self, *traits, **kwargs): """Create a tuple from a list, set, or tuple. Create a fixed-type tuple with Traits: @@ -2402,7 +2402,7 @@ class Tuple(Container): will be cast to a tuple. If ``traits`` are specified, ``default_value`` must conform to the shape and type they specify. """ - default_value = kwargs.pop('default_value', Undefined) + default_value = kwargs.pop('default_value', Undefined) # allow Tuple((values,)): if len(traits) == 1 and default_value is Undefined and not is_trait(traits[0]): default_value = traits[0] @@ -2418,8 +2418,8 @@ class Tuple(Container): self._traits = [] for trait in traits: if isinstance(trait, type): - warn("Traits should be given as instances, not types (for example, `Int()`, not `Int`)" - " Passing types is deprecated in traitlets 4.1.", + warn("Traits should be given as instances, not types (for example, `Int()`, not `Int`)" + " Passing types is deprecated in traitlets 4.1.", DeprecationWarning, stacklevel=2) t = trait() if isinstance(trait, type) else trait self._traits.append(t) @@ -2427,7 +2427,7 @@ class Tuple(Container): if self._traits and default_value is None: # don't allow default to be an empty container if length is specified args = None - super(Container,self).__init__(klass=self.klass, args=args, **kwargs) + super(Container,self).__init__(klass=self.klass, args=args, **kwargs) def validate_elements(self, obj, value): if not self._traits: @@ -2466,22 +2466,22 @@ class Dict(Instance): _trait = None def __init__(self, trait=None, traits=None, default_value=Undefined, - **kwargs): - """Create a dict trait type from a Python dict. + **kwargs): + """Create a dict trait type from a Python dict. The default value is created by doing ``dict(default_value)``, which creates a copy of the ``default_value``. - Parameters - ---------- - + Parameters + ---------- + trait : TraitType [ optional ] - The specified trait type to check and use to restrict contents of - the Container. If unspecified, trait types are not checked. + The specified trait type to check and use to restrict contents of + the Container. If unspecified, trait types are not checked. - traits : Dictionary of trait types [ optional ] - A Python dictionary containing the types that are valid for - restricting the content of the Dict Container for certain keys. + traits : Dictionary of trait types [ optional ] + A Python dictionary containing the types that are valid for + restricting the content of the Dict Container for certain keys. default_value : SequenceType [ optional ] The default value for the Dict. Must be dict, tuple, or None, and @@ -2509,8 +2509,8 @@ class Dict(Instance): # Case where a type of TraitType is provided rather than an instance if is_trait(trait): if isinstance(trait, type): - warn("Traits should be given as instances, not types (for example, `Int()`, not `Int`)" - " Passing types is deprecated in traitlets 4.1.", + warn("Traits should be given as instances, not types (for example, `Int()`, not `Int`)" + " Passing types is deprecated in traitlets 4.1.", DeprecationWarning, stacklevel=2) self._trait = trait() if isinstance(trait, type) else trait elif trait is not None: @@ -2518,7 +2518,7 @@ class Dict(Instance): self._traits = traits - super(Dict, self).__init__(klass=dict, args=args, **kwargs) + super(Dict, self).__init__(klass=dict, args=args, **kwargs) def element_error(self, obj, element, validator): e = "Element of the '%s' trait of %s instance must be %s, but a value of %s was specified." \ @@ -2533,26 +2533,26 @@ class Dict(Instance): return value def validate_elements(self, obj, value): - use_dict = bool(self._traits) - default_to = (self._trait or Any()) - if not use_dict and isinstance(default_to, Any): + use_dict = bool(self._traits) + default_to = (self._trait or Any()) + if not use_dict and isinstance(default_to, Any): return value - + validated = {} for key in value: - if use_dict and key in self._traits: - validate_with = self._traits[key] - else: - validate_with = default_to + if use_dict and key in self._traits: + validate_with = self._traits[key] + else: + validate_with = default_to try: - v = value[key] - if not isinstance(validate_with, Any): - v = validate_with._validate(obj, v) + v = value[key] + if not isinstance(validate_with, Any): + v = validate_with._validate(obj, v) except TraitError: - self.element_error(obj, v, validate_with) + self.element_error(obj, v, validate_with) else: validated[key] = v - + return self.klass(validated) def class_init(self, cls, name): @@ -2584,7 +2584,7 @@ class TCPAddress(TraitType): def validate(self, obj, value): if isinstance(value, tuple): if len(value) == 2: - if isinstance(value[0], six.string_types) and isinstance(value[1], int): + if isinstance(value[0], six.string_types) and isinstance(value[1], int): port = value[1] if port >= 0 and port <= 65535: return value @@ -2603,88 +2603,88 @@ class CRegExp(TraitType): return re.compile(value) except: self.error(obj, value) - - -class UseEnum(TraitType): - """Use a Enum class as model for the data type description. - Note that if no default-value is provided, the first enum-value is used - as default-value. - - .. sourcecode:: python - - # -- SINCE: Python 3.4 (or install backport: pip install enum34) - import enum - from traitlets import HasTraits, UseEnum - - class Color(enum.Enum): - red = 1 # -- IMPLICIT: default_value - blue = 2 - green = 3 - - class MyEntity(HasTraits): - color = UseEnum(Color, default_value=Color.blue) - - entity = MyEntity(color=Color.red) - entity.color = Color.green # USE: Enum-value (preferred) - entity.color = "green" # USE: name (as string) - entity.color = "Color.green" # USE: scoped-name (as string) - entity.color = 3 # USE: number (as int) - assert entity.color is Color.green - """ - default_value = None - info_text = "Trait type adapter to a Enum class" - - def __init__(self, enum_class, default_value=None, **kwargs): - assert issubclass(enum_class, enum.Enum), \ - "REQUIRE: enum.Enum, but was: %r" % enum_class - allow_none = kwargs.get("allow_none", False) - if default_value is None and not allow_none: - default_value = list(enum_class.__members__.values())[0] - super(UseEnum, self).__init__(default_value=default_value, **kwargs) - self.enum_class = enum_class - self.name_prefix = enum_class.__name__ + "." - - def select_by_number(self, value, default=Undefined): - """Selects enum-value by using its number-constant.""" - assert isinstance(value, int) - enum_members = self.enum_class.__members__ - for enum_item in enum_members.values(): - if enum_item.value == value: - return enum_item - # -- NOT FOUND: - return default - - def select_by_name(self, value, default=Undefined): - """Selects enum-value by using its name or scoped-name.""" - assert isinstance(value, six.string_types) - if value.startswith(self.name_prefix): - # -- SUPPORT SCOPED-NAMES, like: "Color.red" => "red" - value = value.replace(self.name_prefix, "", 1) - return self.enum_class.__members__.get(value, default) - - def validate(self, obj, value): - if isinstance(value, self.enum_class): - return value - elif isinstance(value, int): - # -- CONVERT: number => enum_value (item) - value2 = self.select_by_number(value) - if value2 is not Undefined: - return value2 - elif isinstance(value, six.string_types): - # -- CONVERT: name or scoped_name (as string) => enum_value (item) - value2 = self.select_by_name(value) - if value2 is not Undefined: - return value2 - elif value is None: - if self.allow_none: - return None - else: - return self.default_value - self.error(obj, value) - - def info(self): - """Returns a description of this Enum trait (in case of errors).""" - result = "Any of: %s" % ", ".join(self.enum_class.__members__.keys()) - if self.allow_none: - return result + " or None" - return result + + +class UseEnum(TraitType): + """Use a Enum class as model for the data type description. + Note that if no default-value is provided, the first enum-value is used + as default-value. + + .. sourcecode:: python + + # -- SINCE: Python 3.4 (or install backport: pip install enum34) + import enum + from traitlets import HasTraits, UseEnum + + class Color(enum.Enum): + red = 1 # -- IMPLICIT: default_value + blue = 2 + green = 3 + + class MyEntity(HasTraits): + color = UseEnum(Color, default_value=Color.blue) + + entity = MyEntity(color=Color.red) + entity.color = Color.green # USE: Enum-value (preferred) + entity.color = "green" # USE: name (as string) + entity.color = "Color.green" # USE: scoped-name (as string) + entity.color = 3 # USE: number (as int) + assert entity.color is Color.green + """ + default_value = None + info_text = "Trait type adapter to a Enum class" + + def __init__(self, enum_class, default_value=None, **kwargs): + assert issubclass(enum_class, enum.Enum), \ + "REQUIRE: enum.Enum, but was: %r" % enum_class + allow_none = kwargs.get("allow_none", False) + if default_value is None and not allow_none: + default_value = list(enum_class.__members__.values())[0] + super(UseEnum, self).__init__(default_value=default_value, **kwargs) + self.enum_class = enum_class + self.name_prefix = enum_class.__name__ + "." + + def select_by_number(self, value, default=Undefined): + """Selects enum-value by using its number-constant.""" + assert isinstance(value, int) + enum_members = self.enum_class.__members__ + for enum_item in enum_members.values(): + if enum_item.value == value: + return enum_item + # -- NOT FOUND: + return default + + def select_by_name(self, value, default=Undefined): + """Selects enum-value by using its name or scoped-name.""" + assert isinstance(value, six.string_types) + if value.startswith(self.name_prefix): + # -- SUPPORT SCOPED-NAMES, like: "Color.red" => "red" + value = value.replace(self.name_prefix, "", 1) + return self.enum_class.__members__.get(value, default) + + def validate(self, obj, value): + if isinstance(value, self.enum_class): + return value + elif isinstance(value, int): + # -- CONVERT: number => enum_value (item) + value2 = self.select_by_number(value) + if value2 is not Undefined: + return value2 + elif isinstance(value, six.string_types): + # -- CONVERT: name or scoped_name (as string) => enum_value (item) + value2 = self.select_by_name(value) + if value2 is not Undefined: + return value2 + elif value is None: + if self.allow_none: + return None + else: + return self.default_value + self.error(obj, value) + + def info(self): + """Returns a description of this Enum trait (in case of errors).""" + result = "Any of: %s" % ", ".join(self.enum_class.__members__.keys()) + if self.allow_none: + return result + " or None" + return result diff --git a/contrib/python/traitlets/py2/traitlets/utils/bunch.py b/contrib/python/traitlets/py2/traitlets/utils/bunch.py index 2edb830ad6..dc40b5df7d 100644 --- a/contrib/python/traitlets/py2/traitlets/utils/bunch.py +++ b/contrib/python/traitlets/py2/traitlets/utils/bunch.py @@ -1,25 +1,25 @@ -"""Yet another implementation of bunch - -attribute-access of items on a dict. -""" - -# Copyright (c) Jupyter Development Team. -# Distributed under the terms of the Modified BSD License. - -class Bunch(dict): - """A dict with attribute-access""" - def __getattr__(self, key): - try: - return self.__getitem__(key) - except KeyError: - raise AttributeError(key) - - def __setattr__(self, key, value): - self.__setitem__(key, value) - - def __dir__(self): - # py2-compat: can't use super because dict doesn't have __dir__ - names = dir({}) - names.extend(self.keys()) - return names - +"""Yet another implementation of bunch + +attribute-access of items on a dict. +""" + +# Copyright (c) Jupyter Development Team. +# Distributed under the terms of the Modified BSD License. + +class Bunch(dict): + """A dict with attribute-access""" + def __getattr__(self, key): + try: + return self.__getitem__(key) + except KeyError: + raise AttributeError(key) + + def __setattr__(self, key, value): + self.__setitem__(key, value) + + def __dir__(self): + # py2-compat: can't use super because dict doesn't have __dir__ + names = dir({}) + names.extend(self.keys()) + return names + diff --git a/contrib/python/traitlets/py2/traitlets/utils/getargspec.py b/contrib/python/traitlets/py2/traitlets/utils/getargspec.py index 0a047379fe..f23750cbc1 100644 --- a/contrib/python/traitlets/py2/traitlets/utils/getargspec.py +++ b/contrib/python/traitlets/py2/traitlets/utils/getargspec.py @@ -10,7 +10,7 @@ """ import inspect -from six import PY3 +from six import PY3 # Unmodified from sphinx below this line diff --git a/contrib/python/traitlets/py2/traitlets/utils/importstring.py b/contrib/python/traitlets/py2/traitlets/utils/importstring.py index 5b4f643f41..0228367446 100644 --- a/contrib/python/traitlets/py2/traitlets/utils/importstring.py +++ b/contrib/python/traitlets/py2/traitlets/utils/importstring.py @@ -5,8 +5,8 @@ A simple utility to import something by its string name. # Copyright (c) IPython Development Team. # Distributed under the terms of the Modified BSD License. -from ipython_genutils.py3compat import cast_bytes_py2 -from six import string_types +from ipython_genutils.py3compat import cast_bytes_py2 +from six import string_types def import_item(name): """Import and return ``bar`` given the string ``foo.bar``. diff --git a/contrib/python/traitlets/py2/ya.make b/contrib/python/traitlets/py2/ya.make index 4a60107101..1efff6da42 100644 --- a/contrib/python/traitlets/py2/ya.make +++ b/contrib/python/traitlets/py2/ya.make @@ -14,7 +14,7 @@ PEERDIR( contrib/python/decorator contrib/python/enum34 contrib/python/ipython-genutils - contrib/python/six + contrib/python/six ) NO_LINT() @@ -31,7 +31,7 @@ PY_SRCS( traitlets/log.py traitlets/traitlets.py traitlets/utils/__init__.py - traitlets/utils/bunch.py + traitlets/utils/bunch.py traitlets/utils/getargspec.py traitlets/utils/importstring.py traitlets/utils/sentinel.py diff --git a/contrib/python/traitlets/py3/traitlets/config/application.py b/contrib/python/traitlets/py3/traitlets/config/application.py index 99a6ef7ee0..b81fd45b85 100644 --- a/contrib/python/traitlets/py3/traitlets/config/application.py +++ b/contrib/python/traitlets/py3/traitlets/config/application.py @@ -5,7 +5,7 @@ from collections import defaultdict, OrderedDict -from copy import deepcopy +from copy import deepcopy import functools import json import logging @@ -20,7 +20,7 @@ from traitlets.config.loader import ( KVArgParseConfigLoader, PyFileConfigLoader, Config, ArgumentError, ConfigFileNotFound, JSONFileConfigLoader ) from traitlets.traitlets import ( - Bool, Unicode, List, Enum, Dict, Instance, TraitError, observe, observe_compat, default, + Bool, Unicode, List, Enum, Dict, Instance, TraitError, observe, observe_compat, default, ) from ..utils.importstring import import_item @@ -28,7 +28,7 @@ from ..utils import cast_unicode from traitlets.utils.text import indent, wrap_paragraphs from textwrap import dedent - + #----------------------------------------------------------------------------- # Descriptions for the various sections #----------------------------------------------------------------------------- @@ -63,23 +63,23 @@ subcommand 'cmd', do: `{app} cmd -h`. # Application class #----------------------------------------------------------------------------- - - -_envvar = os.environ.get('TRAITLETS_APPLICATION_RAISE_CONFIG_FILE_ERROR','') -if _envvar.lower() in {'1','true'}: - TRAITLETS_APPLICATION_RAISE_CONFIG_FILE_ERROR = True -elif _envvar.lower() in {'0','false',''} : - TRAITLETS_APPLICATION_RAISE_CONFIG_FILE_ERROR = False -else: - raise ValueError("Unsupported value for environment variable: 'TRAITLETS_APPLICATION_RAISE_CONFIG_FILE_ERROR' is set to '%s' which is none of {'0', '1', 'false', 'true', ''}."% _envvar ) - - + + +_envvar = os.environ.get('TRAITLETS_APPLICATION_RAISE_CONFIG_FILE_ERROR','') +if _envvar.lower() in {'1','true'}: + TRAITLETS_APPLICATION_RAISE_CONFIG_FILE_ERROR = True +elif _envvar.lower() in {'0','false',''} : + TRAITLETS_APPLICATION_RAISE_CONFIG_FILE_ERROR = False +else: + raise ValueError("Unsupported value for environment variable: 'TRAITLETS_APPLICATION_RAISE_CONFIG_FILE_ERROR' is set to '%s' which is none of {'0', '1', 'false', 'true', ''}."% _envvar ) + + def catch_config_error(method): """Method decorator for catching invalid config (Trait/ArgumentErrors) during init. On a TraitError (generally caused by bad config), this will print the trait's message, and exit the app. - + For use on init methods, to prevent invoking excepthook on invalid input. """ @functools.wraps(method) @@ -99,16 +99,16 @@ class ApplicationError(Exception): class LevelFormatter(logging.Formatter): """Formatter with additional `highlevel` record - + This field is empty if log level is less than highlevel_limit, otherwise it is formatted with self.highlevel_format. - + Useful for adding 'WARNING' to warning messages, without adding 'INFO' to info, etc. """ highlevel_limit = logging.WARN highlevel_format = " %(levelname)s |" - + def format(self, record): if record.levelno >= self.highlevel_limit: record.highlevel = self.highlevel_format % record.__dict__ @@ -116,7 +116,7 @@ class LevelFormatter(logging.Formatter): record.highlevel = "" return super(LevelFormatter, self).format(record) - + class Application(SingletonConfigurable): """A singleton application with full configuration support.""" @@ -131,7 +131,7 @@ class Application(SingletonConfigurable): option_description = Unicode(option_description) keyvalue_description = Unicode(keyvalue_description) subcommand_description = Unicode(subcommand_description) - + python_config_loader_class = PyFileConfigLoader json_config_loader_class = JSONFileConfigLoader @@ -164,13 +164,13 @@ class Application(SingletonConfigurable): # The version string of this application. version = Unicode('0.0') - + # the argv used to initialize the application argv = List() - # Whether failing to load config files should prevent startup - raise_config_file_errors = Bool(TRAITLETS_APPLICATION_RAISE_CONFIG_FILE_ERROR) - + # Whether failing to load config files should prevent startup + raise_config_file_errors = Bool(TRAITLETS_APPLICATION_RAISE_CONFIG_FILE_ERROR) + # The log level for the application log_level = Enum((0,10,20,30,40,50,'DEBUG','INFO','WARN','ERROR','CRITICAL'), default_value=logging.WARN, @@ -180,15 +180,15 @@ class Application(SingletonConfigurable): @observe_compat def _log_level_changed(self, change): """Adjust the log level when log_level is set.""" - new = change.new + new = change.new if isinstance(new, str): new = getattr(logging, new) self.log_level = new self.log.setLevel(new) - + _log_formatter_cls = LevelFormatter - - log_datefmt = Unicode("%Y-%m-%d %H:%M:%S", + + log_datefmt = Unicode("%Y-%m-%d %H:%M:%S", help="The date format used by logging formatters for %(asctime)s" ).tag(config=True) @@ -209,7 +209,7 @@ class Application(SingletonConfigurable): return _log_formatter = self._log_formatter_cls(fmt=self.log_format, datefmt=self.log_datefmt) _log_handler.setFormatter(_log_formatter) - + @default('log') def _log_default(self): """Start logging for this application. @@ -229,7 +229,7 @@ class Application(SingletonConfigurable): break else: _log = _log.parent - if sys.executable and sys.executable.endswith('pythonw.exe'): + if sys.executable and sys.executable.endswith('pythonw.exe'): # this should really go to a file, but file-logging is only # hooked up in parallel applications _log_handler = logging.StreamHandler(open(os.devnull, 'w')) @@ -279,16 +279,16 @@ class Application(SingletonConfigurable): # extra command-line arguments that don't set config values extra_args = List(Unicode()) - cli_config = Instance(Config, (), {}, - help="""The subset of our configuration that came from the command-line - - We re-load this configuration after loading config files, - to ensure that it maintains highest priority. - """ - ) + cli_config = Instance(Config, (), {}, + help="""The subset of our configuration that came from the command-line + We re-load this configuration after loading config files, + to ensure that it maintains highest priority. + """ + ) + _loaded_config_files = List() - + show_config = Bool( help="Instead of starting the Application, dump configuration to stdout" ).tag(config=True) @@ -311,14 +311,14 @@ class Application(SingletonConfigurable): SingletonConfigurable.__init__(self, **kwargs) # Ensure my class is in self.classes, so my attributes appear in command line # options and config files. - cls = self.__class__ - if cls not in self.classes: - if self.classes is cls.classes: - # class attr, assign instead of insert + cls = self.__class__ + if cls not in self.classes: + if self.classes is cls.classes: + # class attr, assign instead of insert self.classes = [cls] + self.classes - else: - self.classes.insert(0, self.__class__) - + else: + self.classes.insert(0, self.__class__) + @observe('config') @observe_compat def _config_changed(self, change): @@ -394,7 +394,7 @@ class Application(SingletonConfigurable): for c in cls.mro()[:-3]: classdict[c.__name__] = c - for alias, longname in self.aliases.items(): + for alias, longname in self.aliases.items(): try: if isinstance(longname, tuple): longname, fhelp = longname @@ -489,7 +489,7 @@ class Application(SingletonConfigurable): app=self.name)): yield p yield '' - for subc, (cls, help) in self.subcommands.items(): + for subc, (cls, help) in self.subcommands.items(): yield subc if help: yield indent(dedent(help.strip())) @@ -602,10 +602,10 @@ class Application(SingletonConfigurable): # ... and finally initialize subapp. self.subapp.initialize(argv) - + def flatten_flags(self): """Flatten flags and aliases for loaders, so cl-args override as expected. - + This prevents issues such as an alias pointing to InteractiveShell, but a config file setting the same trait in TerminalInteraciveShell getting inappropriate priority over the command-line arg. @@ -613,7 +613,7 @@ class Application(SingletonConfigurable): Only aliases with exactly one descendent in the class list will be promoted. - + """ # build a tree of classes in our list that inherit from a particular # it will be a dict by parent classname of classes in our list @@ -639,13 +639,13 @@ class Application(SingletonConfigurable): alias = (alias, ) for al in alias: aliases[al] = '.'.join([cls,trait]) - + # flatten flags, which are of the form: # { 'key' : ({'Cls' : {'trait' : value}}, 'help')} flags = {} - for key, (flagdict, help) in self.flags.items(): + for key, (flagdict, help) in self.flags.items(): newflag = {} - for cls, subdict in flagdict.items(): + for cls, subdict in flagdict.items(): children = mro_tree[cls] # exactly one descendent, promote flag section if len(children) == 1: @@ -672,7 +672,7 @@ class Application(SingletonConfigurable): assert not isinstance(argv, str) argv = sys.argv[1:] if argv is None else argv self.argv = [cast_unicode(arg) for arg in argv ] - + if argv and argv[0] == 'help': # turn `ipython help notebook` into `ipython notebook -h` argv = argv[1:] + ['-h'] @@ -700,7 +700,7 @@ class Application(SingletonConfigurable): if '--version' in interpreted_argv or '-V' in interpreted_argv: self.print_version() self.exit(0) - + # flatten flags&aliases, so cl-args get appropriate priority: flags, aliases = self.flatten_flags() classes = tuple(self._classes_with_config_traits()) @@ -711,27 +711,27 @@ class Application(SingletonConfigurable): # traitlets 5: no longer print help output on error # help output is huge, and comes after the error raise - self.update_config(self.cli_config) + self.update_config(self.cli_config) # store unparsed args in extra_args self.extra_args = loader.extra_args @classmethod - def _load_config_files(cls, basefilename, path=None, log=None, raise_config_file_errors=False): + def _load_config_files(cls, basefilename, path=None, log=None, raise_config_file_errors=False): """Load config files (py,json) by filename and path. yield each config object in turn. """ - + if not isinstance(path, list): path = [path] for path in path[::-1]: # path list is in descending priority order, so load files backwards: pyloader = cls.python_config_loader_class(basefilename+'.py', path=path, log=log) if log: - log.debug("Looking for %s in %s", basefilename, path or os.getcwd()) + log.debug("Looking for %s in %s", basefilename, path or os.getcwd()) jsonloader = cls.json_config_loader_class(basefilename+'.json', path=path, log=log) - loaded = [] - filenames = [] + loaded = [] + filenames = [] for loader in [pyloader, jsonloader]: config = None try: @@ -743,8 +743,8 @@ class Application(SingletonConfigurable): # unlikely event that the error raised before filefind finished filename = loader.full_filename or basefilename # problem while running the file - if raise_config_file_errors: - raise + if raise_config_file_errors: + raise if log: log.error("Exception while loading config file %s", filename, exc_info=True) @@ -752,16 +752,16 @@ class Application(SingletonConfigurable): if log: log.debug("Loaded config file: %s", loader.full_filename) if config: - for filename, earlier_config in zip(filenames, loaded): - collisions = earlier_config.collisions(config) - if collisions and log: - log.warning("Collisions detected in {0} and {1} config files." - " {1} has higher priority: {2}".format( - filename, loader.full_filename, json.dumps(collisions, indent=2), - )) + for filename, earlier_config in zip(filenames, loaded): + collisions = earlier_config.collisions(config) + if collisions and log: + log.warning("Collisions detected in {0} and {1} config files." + " {1} has higher priority: {2}".format( + filename, loader.full_filename, json.dumps(collisions, indent=2), + )) yield (config, loader.full_filename) - loaded.append(config) - filenames.append(loader.full_filename) + loaded.append(config) + filenames.append(loader.full_filename) @property def loaded_config_files(self): @@ -772,55 +772,55 @@ class Application(SingletonConfigurable): def load_config_file(self, filename, path=None): """Load config files by filename and path.""" filename, ext = os.path.splitext(filename) - new_config = Config() + new_config = Config() for (config, filename) in self._load_config_files(filename, path=path, log=self.log, - raise_config_file_errors=self.raise_config_file_errors, - ): - new_config.merge(config) + raise_config_file_errors=self.raise_config_file_errors, + ): + new_config.merge(config) if filename not in self._loaded_config_files: # only add to list of loaded files if not previously loaded self._loaded_config_files.append(filename) - # add self.cli_config to preserve CLI config priority - new_config.merge(self.cli_config) - self.update_config(new_config) + # add self.cli_config to preserve CLI config priority + new_config.merge(self.cli_config) + self.update_config(new_config) def _classes_with_config_traits(self, classes=None): - """ + """ Yields only classes with configurable traits, and their subclasses. - + :param classes: The list of classes to iterate; if not set, uses :attr:`classes`. - Thus, produced sample config-file will contain all classes - on which a trait-value may be overridden: - - - either on the class owning the trait, - - or on its subclasses, even if those subclasses do not define - any traits themselves. - """ + Thus, produced sample config-file will contain all classes + on which a trait-value may be overridden: + + - either on the class owning the trait, + - or on its subclasses, even if those subclasses do not define + any traits themselves. + """ if classes is None: classes = self.classes - cls_to_config = OrderedDict( (cls, bool(cls.class_own_traits(config=True))) - for cls + cls_to_config = OrderedDict( (cls, bool(cls.class_own_traits(config=True))) + for cls in self._classes_inc_parents(classes)) - - def is_any_parent_included(cls): - return any(b in cls_to_config and cls_to_config[b] for b in cls.__bases__) - - ## Mark "empty" classes for inclusion if their parents own-traits, - # and loop until no more classes gets marked. - # - while True: - to_incl_orig = cls_to_config.copy() - cls_to_config = OrderedDict( (cls, inc_yes or is_any_parent_included(cls)) - for cls, inc_yes - in cls_to_config.items()) - if cls_to_config == to_incl_orig: - break - for cl, inc_yes in cls_to_config.items(): - if inc_yes: - yield cl - + + def is_any_parent_included(cls): + return any(b in cls_to_config and cls_to_config[b] for b in cls.__bases__) + + ## Mark "empty" classes for inclusion if their parents own-traits, + # and loop until no more classes gets marked. + # + while True: + to_incl_orig = cls_to_config.copy() + cls_to_config = OrderedDict( (cls, inc_yes or is_any_parent_included(cls)) + for cls, inc_yes + in cls_to_config.items()) + if cls_to_config == to_incl_orig: + break + for cl, inc_yes in cls_to_config.items(): + if inc_yes: + yield cl + def generate_config_file(self, classes=None): """generate default config file from Configurables""" lines = ["# Configuration file for %s." % self.name] @@ -838,7 +838,7 @@ class Application(SingletonConfigurable): @classmethod def launch_instance(cls, argv=None, **kwargs): """Launch a global instance of this Application - + If a global instance already exists, this reinitializes and starts it """ app = cls.instance(**kwargs) @@ -885,7 +885,7 @@ def boolean_flag(name, configurable, set_help='', unset_help=''): def get_config(): """Get the config object for the global Application instance, if there is one - + otherwise return an empty config object """ if Application.initialized(): diff --git a/contrib/python/traitlets/py3/traitlets/config/configurable.py b/contrib/python/traitlets/py3/traitlets/config/configurable.py index 3b2044a01b..0f80aa3a0b 100644 --- a/contrib/python/traitlets/py3/traitlets/config/configurable.py +++ b/contrib/python/traitlets/py3/traitlets/config/configurable.py @@ -6,7 +6,7 @@ from copy import deepcopy import logging -import warnings +import warnings from .loader import Config, LazyConfigValue, DeferredConfig, _is_section_key from traitlets.traitlets import ( @@ -78,12 +78,12 @@ class Configurable(HasTraits): if kwargs.get('config', None) is None: kwargs['config'] = parent.config self.parent = parent - + config = kwargs.pop('config', None) - + # load kwarg traits, other than config super(Configurable, self).__init__(**kwargs) - + # record traits set by config config_override_names = set() def notice_config_override(change): @@ -109,7 +109,7 @@ class Configurable(HasTraits): # allow _config_default to return something self._load_config(self.config) self.unobserve(notice_config_override) - + for name in config_override_names: setattr(self, name, kwargs[name]) @@ -117,25 +117,25 @@ class Configurable(HasTraits): #------------------------------------------------------------------------- # Static trait notifiations #------------------------------------------------------------------------- - + @classmethod def section_names(cls): """return section names as a list""" return [c.__name__ for c in reversed(cls.__mro__) if issubclass(c, Configurable) and issubclass(cls, c) ] - + def _find_my_config(self, cfg): """extract my config from a global Config object - + will construct a Config object of only the config values that apply to me based on my mro(), as well as those of my parent(s) if they exist. - + If I am Bar and my parent is Foo, and their parent is Tim, this will return merge following config sections, in this order:: - + [Bar, Foo.Bar, Tim.Foo.Bar] - + With the last item being the highest priority. """ cfgs = [cfg] @@ -149,20 +149,20 @@ class Configurable(HasTraits): if c._has_section(sname): my_config.merge(c[sname]) return my_config - + def _load_config(self, cfg, section_names=None, traits=None): """load traits from a Config object""" - + if traits is None: traits = self.traits(config=True) if section_names is None: section_names = self.section_names() - + my_config = self._find_my_config(cfg) - + # hold trait notifications until after all config has been loaded with self.hold_trait_notifications(): - for name, config_value in my_config.items(): + for name, config_value in my_config.items(): if name in traits: if isinstance(config_value, LazyConfigValue): # ConfigValue is a wrapper for using append / update on containers @@ -176,21 +176,21 @@ class Configurable(HasTraits): # config object. If we don't, a mutable config_value will be # shared by all instances, effectively making it a class attribute. setattr(self, name, deepcopy(config_value)) - elif not _is_section_key(name) and not isinstance(config_value, Config): + elif not _is_section_key(name) and not isinstance(config_value, Config): from difflib import get_close_matches - if isinstance(self, LoggingConfigurable): - warn = self.log.warning - else: - warn = lambda msg: warnings.warn(msg, stacklevel=9) + if isinstance(self, LoggingConfigurable): + warn = self.log.warning + else: + warn = lambda msg: warnings.warn(msg, stacklevel=9) matches = get_close_matches(name, traits) msg = "Config option `{option}` not recognized by `{klass}`.".format( - option=name, klass=self.__class__.__name__) - + option=name, klass=self.__class__.__name__) + if len(matches) == 1: msg += " Did you mean `{matches}`?".format(matches=matches[0]) elif len(matches) >= 1: - msg +=" Did you mean one of: `{matches}`?".format(matches=', '.join(sorted(matches))) - warn(msg) + msg +=" Did you mean one of: `{matches}`?".format(matches=', '.join(sorted(matches))) + warn(msg) @observe('config') @observe_compat @@ -208,23 +208,23 @@ class Configurable(HasTraits): # classes that are Configurable subclasses. This starts with Configurable # and works down the mro loading the config for each section. section_names = self.section_names() - self._load_config(change.new, traits=traits, section_names=section_names) + self._load_config(change.new, traits=traits, section_names=section_names) def update_config(self, config): - """Update config and load the new values""" - # traitlets prior to 4.2 created a copy of self.config in order to trigger change events. - # Some projects (IPython < 5) relied upon one side effect of this, - # that self.config prior to update_config was not modified in-place. - # For backward-compatibility, we must ensure that self.config - # is a new object and not modified in-place, - # but config consumers should not rely on this behavior. - self.config = deepcopy(self.config) - # load config - self._load_config(config) - # merge it into self.config + """Update config and load the new values""" + # traitlets prior to 4.2 created a copy of self.config in order to trigger change events. + # Some projects (IPython < 5) relied upon one side effect of this, + # that self.config prior to update_config was not modified in-place. + # For backward-compatibility, we must ensure that self.config + # is a new object and not modified in-place, + # but config consumers should not rely on this behavior. + self.config = deepcopy(self.config) + # load config + self._load_config(config) + # merge it into self.config self.config.merge(config) - # TODO: trigger change event if/when dict-update change events take place - # DO NOT trigger full trait-change + # TODO: trigger change event if/when dict-update change events take place + # DO NOT trigger full trait-change @classmethod def class_get_help(cls, inst=None): @@ -246,7 +246,7 @@ class Configurable(HasTraits): @classmethod def class_get_trait_help(cls, trait, inst=None, helptext=None): """Get the helptext string for a single trait. - + :param inst: If given, it's current trait values will be used in place of the class default. @@ -340,7 +340,7 @@ class Configurable(HasTraits): """return a commented, wrapped block.""" s = '\n\n'.join(wrap_paragraphs(s, 78)) - return '## ' + s.replace('\n', '\n# ') + return '## ' + s.replace('\n', '\n# ') # section header breaker = '#' + '-' * 78 @@ -349,14 +349,14 @@ class Configurable(HasTraits): if issubclass(p, Configurable) ) - s = "# %s(%s) configuration" % (cls.__name__, parent_classes) + s = "# %s(%s) configuration" % (cls.__name__, parent_classes) lines = [breaker, s, breaker] # get the description trait desc = cls.class_traits().get('description') if desc: desc = desc.default_value - if not desc: - # no description from trait, use __doc__ + if not desc: + # no description from trait, use __doc__ desc = getattr(cls, '__doc__', '') if desc: lines.append(c(desc)) diff --git a/contrib/python/traitlets/py3/traitlets/config/loader.py b/contrib/python/traitlets/py3/traitlets/config/loader.py index 5360f889ab..bbab151db8 100644 --- a/contrib/python/traitlets/py3/traitlets/config/loader.py +++ b/contrib/python/traitlets/py3/traitlets/config/loader.py @@ -255,7 +255,7 @@ class Config(dict): def merge(self, other): """merge another config object into this one""" to_update = {} - for k, v in other.items(): + for k, v in other.items(): if k not in self: to_update[k] = v else: # I have this key @@ -542,17 +542,17 @@ class FileConfigLoader(ConfigLoader): self.full_filename = filefind(self.filename, self.path) class JSONFileConfigLoader(FileConfigLoader): - """A JSON file loader for config - - Can also act as a context manager that rewrite the configuration file to disk on exit. - - Example:: - - with JSONFileConfigLoader('myapp.json','/home/jupyter/configurations/') as c: - c.MyNewConfigurable.new_value = 'Updated' - - """ - + """A JSON file loader for config + + Can also act as a context manager that rewrite the configuration file to disk on exit. + + Example:: + + with JSONFileConfigLoader('myapp.json','/home/jupyter/configurations/') as c: + c.MyNewConfigurable.new_value = 'Updated' + + """ + def load_config(self): """Load the config from a file and return it as a Config object.""" self.clear() @@ -579,24 +579,24 @@ class JSONFileConfigLoader(FileConfigLoader): else: raise ValueError('Unknown version of JSON config file: {version}'.format(version=version)) - def __enter__(self): - self.load_config() - return self.config - - def __exit__(self, exc_type, exc_value, traceback): - """ - Exit the context manager but do not handle any errors. - - In case of any error, we do not want to write the potentially broken - configuration to disk. - """ - self.config.version = 1 - json_config = json.dumps(self.config, indent=2) - with open(self.full_filename, 'w') as f: - f.write(json_config) - - - + def __enter__(self): + self.load_config() + return self.config + + def __exit__(self, exc_type, exc_value, traceback): + """ + Exit the context manager but do not handle any errors. + + In case of any error, we do not want to write the potentially broken + configuration to disk. + """ + self.config.version = 1 + json_config = json.dumps(self.config, indent=2) + with open(self.full_filename, 'w') as f: + f.write(json_config) + + + class PyFileConfigLoader(FileConfigLoader): """A config loader for pure python files. @@ -910,7 +910,7 @@ class ArgParseConfigLoader(CommandLineConfigLoader): def _convert_to_config(self): """self.parsed_data->self.config""" - for k, v in vars(self.parsed_data).items(): + for k, v in vars(self.parsed_data).items(): *path, key = k.split(".") section = self.config for p in path: diff --git a/contrib/python/traitlets/py3/traitlets/log.py b/contrib/python/traitlets/py3/traitlets/log.py index af86b325f5..c7166c14c8 100644 --- a/contrib/python/traitlets/py3/traitlets/log.py +++ b/contrib/python/traitlets/py3/traitlets/log.py @@ -9,19 +9,19 @@ _logger = None def get_logger(): """Grab the global logger instance. - + If a global Application is instantiated, grab its logger. Otherwise, grab the root logger. """ global _logger - + if _logger is None: from .config import Application if Application.initialized(): _logger = Application.instance().log else: - _logger = logging.getLogger('traitlets') - # Add a NullHandler to silence warnings about not being - # initialized, per best practice for libraries. - _logger.addHandler(logging.NullHandler()) + _logger = logging.getLogger('traitlets') + # Add a NullHandler to silence warnings about not being + # initialized, per best practice for libraries. + _logger.addHandler(logging.NullHandler()) return _logger diff --git a/contrib/python/traitlets/py3/traitlets/traitlets.py b/contrib/python/traitlets/py3/traitlets/traitlets.py index 6bdf7414d3..7643cbd132 100644 --- a/contrib/python/traitlets/py3/traitlets/traitlets.py +++ b/contrib/python/traitlets/py3/traitlets/traitlets.py @@ -42,17 +42,17 @@ Inheritance diagram: from ast import literal_eval import contextlib import inspect -import os +import os import re import sys import types -import enum +import enum from warnings import warn, warn_explicit from .utils.getargspec import getargspec from .utils.importstring import import_item from .utils.sentinel import Sentinel -from .utils.bunch import Bunch +from .utils.bunch import Bunch from .utils.descriptions import describe, class_of, add_article, repr_type SequenceTypes = (list, tuple, set, frozenset) @@ -113,34 +113,34 @@ class TraitError(Exception): # Utilities #----------------------------------------------------------------------------- -_name_re = re.compile(r"[a-zA-Z_][a-zA-Z0-9_]*$") - -def isidentifier(s): +_name_re = re.compile(r"[a-zA-Z_][a-zA-Z0-9_]*$") + +def isidentifier(s): return s.isidentifier() - -_deprecations_shown = set() -def _should_warn(key): - """Add our own checks for too many deprecation warnings. - - Limit to once per package. - """ - env_flag = os.environ.get('TRAITLETS_ALL_DEPRECATIONS') - if env_flag and env_flag != '0': - return True - - if key not in _deprecations_shown: - _deprecations_shown.add(key) - return True - else: - return False - + +_deprecations_shown = set() +def _should_warn(key): + """Add our own checks for too many deprecation warnings. + + Limit to once per package. + """ + env_flag = os.environ.get('TRAITLETS_ALL_DEPRECATIONS') + if env_flag and env_flag != '0': + return True + + if key not in _deprecations_shown: + _deprecations_shown.add(key) + return True + else: + return False + def _deprecated_method(method, cls, method_name, msg): """Show deprecation warning about a magic method definition. Uses warn_explicit to bind warning to method definition instead of triggering code, which isn't relevant. """ - warn_msg = "{classname}.{method_name} is deprecated in traitlets 4.1: {msg}".format( + warn_msg = "{classname}.{method_name} is deprecated in traitlets 4.1: {msg}".format( classname=cls.__name__, method_name=method_name, msg=msg ) @@ -148,11 +148,11 @@ def _deprecated_method(method, cls, method_name, msg): if method_name in parent.__dict__: cls = parent break - # limit deprecation messages to once per package - package_name = cls.__module__.split('.', 1)[0] - key = (package_name, msg) - if not _should_warn(key): - return + # limit deprecation messages to once per package + package_name = cls.__module__.split('.', 1)[0] + key = (package_name, msg) + if not _should_warn(key): + return try: fname = inspect.getsourcefile(method) or "<unknown>" lineno = inspect.getsourcelines(method)[1] or 0 @@ -197,12 +197,12 @@ def parse_notifier_name(names): """ if names is All or isinstance(names, str): return [names] - else: + else: if not names or All in names: return [All] for n in names: if not isinstance(n, str): - raise TypeError("names must be strings, not %r" % n) + raise TypeError("names must be strings, not %r" % n) return names @@ -358,7 +358,7 @@ class directional_link(object): return with self._busy_updating(): setattr(self.target[0], self.target[1], - self._transform(change.new)) + self._transform(change.new)) def unlink(self): self.source[0].unobserve(self._update, names=self.source[1]) @@ -367,7 +367,7 @@ dlink = directional_link #----------------------------------------------------------------------------- -# Base Descriptor Class +# Base Descriptor Class #----------------------------------------------------------------------------- @@ -447,32 +447,32 @@ class TraitType(BaseDescriptor): """ if default_value is not Undefined: self.default_value = default_value - if allow_none: + if allow_none: self.allow_none = allow_none if read_only is not None: self.read_only = read_only self.help = help if help is not None else '' - if len(kwargs) > 0: + if len(kwargs) > 0: stacklevel = 1 f = inspect.currentframe() # count supers to determine stacklevel for warning while f.f_code.co_name == '__init__': stacklevel += 1 f = f.f_back - mod = f.f_globals.get('__name__') or '' - pkg = mod.split('.', 1)[0] - key = tuple(['metadata-tag', pkg] + sorted(kwargs)) - if _should_warn(key): - warn("metadata %s was set from the constructor. " - "With traitlets 4.1, metadata should be set using the .tag() method, " - "e.g., Int().tag(key1='value1', key2='value2')" % (kwargs,), - DeprecationWarning, stacklevel=stacklevel) + mod = f.f_globals.get('__name__') or '' + pkg = mod.split('.', 1)[0] + key = tuple(['metadata-tag', pkg] + sorted(kwargs)) + if _should_warn(key): + warn("metadata %s was set from the constructor. " + "With traitlets 4.1, metadata should be set using the .tag() method, " + "e.g., Int().tag(key1='value1', key2='value2')" % (kwargs,), + DeprecationWarning, stacklevel=stacklevel) if len(self.metadata) > 0: self.metadata = self.metadata.copy() - self.metadata.update(kwargs) + self.metadata.update(kwargs) else: - self.metadata = kwargs + self.metadata = kwargs else: self.metadata = self.metadata.copy() if config is not None: @@ -519,20 +519,20 @@ class TraitType(BaseDescriptor): """DEPRECATED: Retrieve the static default value for this trait. Use self.default_value instead """ - warn("get_default_value is deprecated in traitlets 4.0: use the .default_value attribute", DeprecationWarning, + warn("get_default_value is deprecated in traitlets 4.0: use the .default_value attribute", DeprecationWarning, stacklevel=2) return self.default_value def init_default_value(self, obj): """DEPRECATED: Set the static default value for the trait type. """ - warn("init_default_value is deprecated in traitlets 4.0, and may be removed in the future", DeprecationWarning, + warn("init_default_value is deprecated in traitlets 4.0, and may be removed in the future", DeprecationWarning, stacklevel=2) value = self._validate(obj, self.default_value) obj._trait_values[self.name] = value return value - def get(self, obj, cls=None): + def get(self, obj, cls=None): try: value = obj._trait_values[self.name] except KeyError: @@ -616,7 +616,7 @@ class TraitType(BaseDescriptor): def _cross_validate(self, obj, value): if self.name in obj._trait_validators: - proposal = Bunch({'trait': self, 'value': value, 'owner': obj}) + proposal = Bunch({'trait': self, 'value': value, 'owner': obj}) value = obj._trait_validators[self.name](obj, proposal) elif hasattr(obj, '_%s_validate' % self.name): meth_name = '_%s_validate' % self.name @@ -700,7 +700,7 @@ class TraitType(BaseDescriptor): msg = "use the instance .help string directly, like x.help" else: msg = "use the instance .metadata dictionary directly, like x.metadata[key] or x.metadata.get(key, default)" - warn("Deprecated in traitlets 4.1, " + msg, DeprecationWarning, stacklevel=2) + warn("Deprecated in traitlets 4.1, " + msg, DeprecationWarning, stacklevel=2) return self.metadata.get(key, default) def set_metadata(self, key, value): @@ -712,7 +712,7 @@ class TraitType(BaseDescriptor): msg = "use the instance .help string directly, like x.help = value" else: msg = "use the instance .metadata dictionary directly, like x.metadata[key] = value" - warn("Deprecated in traitlets 4.1, " + msg, DeprecationWarning, stacklevel=2) + warn("Deprecated in traitlets 4.1, " + msg, DeprecationWarning, stacklevel=2) self.metadata[key] = value def tag(self, **metadata): @@ -722,11 +722,11 @@ class TraitType(BaseDescriptor): >>> Int(0).tag(config=True, sync=True) """ - maybe_constructor_keywords = set(metadata.keys()).intersection({'help','allow_none', 'read_only', 'default_value'}) - if maybe_constructor_keywords: - warn('The following attributes are set in using `tag`, but seem to be constructor keywords arguments: %s '% - maybe_constructor_keywords, UserWarning, stacklevel=2) - + maybe_constructor_keywords = set(metadata.keys()).intersection({'help','allow_none', 'read_only', 'default_value'}) + if maybe_constructor_keywords: + warn('The following attributes are set in using `tag`, but seem to be constructor keywords arguments: %s '% + maybe_constructor_keywords, UserWarning, stacklevel=2) + self.metadata.update(metadata) return self @@ -764,13 +764,13 @@ class _CallbackWrapper(object): if self.nargs == 0: self.cb() elif self.nargs == 1: - self.cb(change.name) + self.cb(change.name) elif self.nargs == 2: - self.cb(change.name, change.new) + self.cb(change.name, change.new) elif self.nargs == 3: - self.cb(change.name, change.old, change.new) + self.cb(change.name, change.old, change.new) elif self.nargs == 4: - self.cb(change.name, change.old, change.new, change.owner) + self.cb(change.name, change.old, change.new, change.owner) def _callback_wrapper(cb): if isinstance(cb, _CallbackWrapper): @@ -788,13 +788,13 @@ class MetaHasDescriptors(type): def __new__(mcls, name, bases, classdict): """Create the HasDescriptors class.""" - for k, v in classdict.items(): + for k, v in classdict.items(): # ---------------------------------------------------------------- # Support of deprecated behavior allowing for TraitType types # to be used instead of TraitType instances. if inspect.isclass(v) and issubclass(v, TraitType): - warn("Traits should be given as instances, not types (for example, `Int()`, not `Int`)." - " Passing types is deprecated in traitlets 4.1.", + warn("Traits should be given as instances, not types (for example, `Int()`, not `Int`)." + " Passing types is deprecated in traitlets 4.1.", DeprecationWarning, stacklevel=2) classdict[k] = v() # ---------------------------------------------------------------- @@ -813,7 +813,7 @@ class MetaHasDescriptors(type): BaseDescriptor in the class dict of the newly created ``cls`` before calling their :attr:`class_init` method. """ - for k, v in classdict.items(): + for k, v in classdict.items(): if isinstance(v, BaseDescriptor): v.class_init(cls, k) @@ -833,10 +833,10 @@ class MetaHasTraits(MetaHasDescriptors): def observe(*names, type="change"): """A decorator which can be used to observe Traits on a class. - The handler passed to the decorator will be called with one ``change`` - dict argument. The change dictionary at least holds a 'type' key and a - 'name' key, corresponding respectively to the type of notification and the - name of the attribute that triggered the notification. + The handler passed to the decorator will be called with one ``change`` + dict argument. The change dictionary at least holds a 'type' key and a + 'name' key, corresponding respectively to the type of notification and the + name of the attribute that triggered the notification. Other keys may be passed depending on the value of 'type'. In the case where type is 'change', we also have the following keys: @@ -850,26 +850,26 @@ def observe(*names, type="change"): *names The str names of the Traits to observe on the object. type : str, kwarg-only - The type of event to observe (e.g. 'change') + The type of event to observe (e.g. 'change') """ - if not names: - raise TypeError("Please specify at least one trait name to observe.") - for name in names: + if not names: + raise TypeError("Please specify at least one trait name to observe.") + for name in names: if name is not All and not isinstance(name, str): - raise TypeError("trait names to observe must be strings or All, not %r" % name) + raise TypeError("trait names to observe must be strings or All, not %r" % name) return ObserveHandler(names, type=type) def observe_compat(func): """Backward-compatibility shim decorator for observers - + Use with: - + @observe('name') @observe_compat def _foo_changed(self, change): ... - + With this, `super()._foo_changed(self, name, old, new)` in subclasses will still work. Allows adoption of new observer API without breaking subclasses that override and super. """ @@ -878,15 +878,15 @@ def observe_compat(func): change = change_or_name else: clsname = self.__class__.__name__ - warn("A parent of %s._%s_changed has adopted the new (traitlets 4.1) @observe(change) API" % ( + warn("A parent of %s._%s_changed has adopted the new (traitlets 4.1) @observe(change) API" % ( clsname, change_or_name), DeprecationWarning) - change = Bunch( - type='change', - old=old, - new=new, - name=change_or_name, - owner=self, - ) + change = Bunch( + type='change', + old=old, + new=new, + name=change_or_name, + owner=self, + ) return func(self, change) return compatible_observer @@ -909,18 +909,18 @@ def validate(*names): Notes ----- - Since the owner has access to the ``HasTraits`` instance via the 'owner' key, + Since the owner has access to the ``HasTraits`` instance via the 'owner' key, the registered cross validator could potentially make changes to attributes of the ``HasTraits`` instance. However, we recommend not to do so. The reason is that the cross-validation of attributes may run in arbitrary order when - exiting the ``hold_trait_notifications`` context, and such changes may not + exiting the ``hold_trait_notifications`` context, and such changes may not commute. """ - if not names: - raise TypeError("Please specify at least one trait name to validate.") - for name in names: + if not names: + raise TypeError("Please specify at least one trait name to validate.") + for name in names: if name is not All and not isinstance(name, str): - raise TypeError("trait names to validate must be strings or All, not %r" % name) + raise TypeError("trait names to validate must be strings or All, not %r" % name) return ValidateHandler(names) @@ -961,7 +961,7 @@ def default(name): # class derived from B.a.this_class. """ if not isinstance(name, str): - raise TypeError("Trait name must be a string or All, not %r" % name) + raise TypeError("Trait name must be a string or All, not %r" % name) return DefaultHandler(name) @@ -972,7 +972,7 @@ class EventHandler(BaseDescriptor): return self def __call__(self, *args, **kwargs): - """Pass `*args` and `**kwargs` to the handler's function if it exists.""" + """Pass `*args` and `**kwargs` to the handler's function if it exists.""" if hasattr(self, 'func'): return self.func(*args, **kwargs) else: @@ -1028,19 +1028,19 @@ class HasDescriptors(metaclass=MetaHasDescriptors): if new_meth is object.__new__: inst = new_meth(cls) else: - inst = new_meth(cls, *args, **kwargs) - inst.setup_instance(*args, **kwargs) + inst = new_meth(cls, *args, **kwargs) + inst.setup_instance(*args, **kwargs) return inst def setup_instance(*args, **kwargs): - """ - This is called **before** self.__init__ is called. - """ + """ + This is called **before** self.__init__ is called. + """ # Pass self as args[0] to allow "self" as keyword argument self = args[0] args = args[1:] - self._cross_validation_lock = False + self._cross_validation_lock = False cls = self.__class__ for key in dir(cls): # Some descriptors raise AttributeError like zope.interface's @@ -1065,40 +1065,40 @@ class HasTraits(HasDescriptors, metaclass=MetaHasTraits): self._trait_values = {} self._trait_notifiers = {} self._trait_validators = {} - super(HasTraits, self).setup_instance(*args, **kwargs) + super(HasTraits, self).setup_instance(*args, **kwargs) - def __init__(self, *args, **kwargs): + def __init__(self, *args, **kwargs): # Allow trait values to be set using keyword arguments. # We need to use setattr for this to trigger validation and # notifications. - super_args = args - super_kwargs = {} + super_args = args + super_kwargs = {} with self.hold_trait_notifications(): - for key, value in kwargs.items(): - if self.has_trait(key): - setattr(self, key, value) - else: - # passthrough args that don't set traits to super - super_kwargs[key] = value - try: - super(HasTraits, self).__init__(*super_args, **super_kwargs) - except TypeError as e: - arg_s_list = [ repr(arg) for arg in super_args ] - for k, v in super_kwargs.items(): - arg_s_list.append("%s=%r" % (k, v)) - arg_s = ', '.join(arg_s_list) - warn( + for key, value in kwargs.items(): + if self.has_trait(key): + setattr(self, key, value) + else: + # passthrough args that don't set traits to super + super_kwargs[key] = value + try: + super(HasTraits, self).__init__(*super_args, **super_kwargs) + except TypeError as e: + arg_s_list = [ repr(arg) for arg in super_args ] + for k, v in super_kwargs.items(): + arg_s_list.append("%s=%r" % (k, v)) + arg_s = ', '.join(arg_s_list) + warn( "Passing unrecognized arguments to super({classname}).__init__({arg_s}).\n" - "{error}\n" - "This is deprecated in traitlets 4.2." - "This error will be raised in a future release of traitlets." - .format( - arg_s=arg_s, classname=self.__class__.__name__, - error=e, - ), - DeprecationWarning, - stacklevel=2, - ) + "{error}\n" + "This is deprecated in traitlets 4.2." + "This error will be raised in a future release of traitlets." + .format( + arg_s=arg_s, classname=self.__class__.__name__, + error=e, + ), + DeprecationWarning, + stacklevel=2, + ) def __getstate__(self): d = self.__dict__.copy() @@ -1129,27 +1129,27 @@ class HasTraits(HasDescriptors, metaclass=MetaHasTraits): if isinstance(value, EventHandler): value.instance_init(self) - @property - @contextlib.contextmanager - def cross_validation_lock(self): - """ - A contextmanager for running a block with our cross validation lock set - to True. - - At the end of the block, the lock's value is restored to its value - prior to entering the block. - """ - if self._cross_validation_lock: - yield - return - else: - try: - self._cross_validation_lock = True - yield - finally: - self._cross_validation_lock = False - + @property @contextlib.contextmanager + def cross_validation_lock(self): + """ + A contextmanager for running a block with our cross validation lock set + to True. + + At the end of the block, the lock's value is restored to its value + prior to entering the block. + """ + if self._cross_validation_lock: + yield + return + else: + try: + self._cross_validation_lock = True + yield + finally: + self._cross_validation_lock = False + + @contextlib.contextmanager def hold_trait_notifications(self): """Context manager for bundling trait change notifications and cross validation. @@ -1158,7 +1158,7 @@ class HasTraits(HasDescriptors, metaclass=MetaHasTraits): race conditions in trait notifiers requesting other trait values. All trait notifications will fire after all values have been assigned. """ - if self._cross_validation_lock: + if self._cross_validation_lock: yield return else: @@ -1170,15 +1170,15 @@ class HasTraits(HasDescriptors, metaclass=MetaHasTraits): if past_changes is None: return [change] else: - if past_changes[-1]['type'] == 'change' and change.type == 'change': - past_changes[-1]['new'] = change.new + if past_changes[-1]['type'] == 'change' and change.type == 'change': + past_changes[-1]['new'] = change.new else: # In case of changes other than 'change', append the notification. past_changes.append(change) return past_changes def hold(change): - name = change.name + name = change.name cache[name] = compress(cache.get(name), change) try: @@ -1191,24 +1191,24 @@ class HasTraits(HasDescriptors, metaclass=MetaHasTraits): for name in list(cache.keys()): trait = getattr(self.__class__, name) value = trait._cross_validate(self, getattr(self, name)) - self.set_trait(name, value) + self.set_trait(name, value) except TraitError as e: # Roll back in case of TraitError during final cross validation. self.notify_change = lambda x: None for name, changes in cache.items(): for change in changes[::-1]: # TODO: Separate in a rollback function per notification type. - if change.type == 'change': - if change.old is not Undefined: - self.set_trait(name, change.old) + if change.type == 'change': + if change.old is not Undefined: + self.set_trait(name, change.old) else: self._trait_values.pop(name) cache = {} raise e finally: self._cross_validation_lock = False - # Restore method retrieval from class - del self.notify_change + # Restore method retrieval from class + del self.notify_change # trigger delayed notifications for changes in cache.values(): @@ -1216,13 +1216,13 @@ class HasTraits(HasDescriptors, metaclass=MetaHasTraits): self.notify_change(change) def _notify_trait(self, name, old_value, new_value): - self.notify_change(Bunch( - name=name, - old=old_value, - new=new_value, - owner=self, - type='change', - )) + self.notify_change(Bunch( + name=name, + old=old_value, + new=new_value, + owner=self, + type='change', + )) def notify_change(self, change): """Notify observers of a change event""" @@ -1231,7 +1231,7 @@ class HasTraits(HasDescriptors, metaclass=MetaHasTraits): def _notify_observers(self, event): """Notify observers of any event""" if not isinstance(event, Bunch): - # cast to bunch if given a dict + # cast to bunch if given a dict event = Bunch(event) name, type = event.name, event.type @@ -1260,9 +1260,9 @@ class HasTraits(HasDescriptors, metaclass=MetaHasTraits): if isinstance(c, _CallbackWrapper): c = c.__call__ - elif isinstance(c, EventHandler) and c.name is not None: + elif isinstance(c, EventHandler) and c.name is not None: c = getattr(self, c.name) - + c(event) def _add_notifiers(self, handler, name, type): @@ -1315,7 +1315,7 @@ class HasTraits(HasDescriptors, metaclass=MetaHasTraits): If False (the default), then install the handler. If True then unintall it. """ - warn("on_trait_change is deprecated in traitlets 4.1: use observe instead", + warn("on_trait_change is deprecated in traitlets 4.1: use observe instead", DeprecationWarning, stacklevel=2) if name is None: name = All @@ -1333,8 +1333,8 @@ class HasTraits(HasDescriptors, metaclass=MetaHasTraits): ---------- handler : callable A callable that is called when a trait changes. Its - signature should be ``handler(change)``, where ``change`` is a - dictionary. The change dictionary at least holds a 'type' key. + signature should be ``handler(change)``, where ``change`` is a + dictionary. The change dictionary at least holds a 'type' key. * ``type``: the type of notification. Other keys may be passed depending on the value of 'type'. In the case where type is 'change', we also have the following keys: @@ -1357,7 +1357,7 @@ class HasTraits(HasDescriptors, metaclass=MetaHasTraits): def unobserve(self, handler, names=All, type='change'): """Remove a trait change handler. - This is used to unregister handlers to trait change notifications. + This is used to unregister handlers to trait change notifications. Parameters ---------- @@ -1387,19 +1387,19 @@ class HasTraits(HasDescriptors, metaclass=MetaHasTraits): pass def _register_validator(self, handler, names): - """Setup a handler to be called when a trait should be cross validated. + """Setup a handler to be called when a trait should be cross validated. This is used to setup dynamic notifications for cross-validation. If a validator is already registered for any of the provided names, a - TraitError is raised and no new validator is registered. + TraitError is raised and no new validator is registered. Parameters ---------- handler : callable A callable that is called when the given trait is cross-validated. - Its signature is handler(proposal), where proposal is a Bunch (dictionary with attribute access) - with the following attributes/keys: + Its signature is handler(proposal), where proposal is a Bunch (dictionary with attribute access) + with the following attributes/keys: * ``owner`` : the HasTraits instance * ``value`` : the proposed value for the modified trait attribute * ``trait`` : the TraitType instance associated with the attribute @@ -1416,8 +1416,8 @@ class HasTraits(HasDescriptors, metaclass=MetaHasTraits): for name in names: self._trait_validators[name] = handler - def add_traits(self, **traits): - """Dynamically add trait attributes to the HasTraits instance.""" + def add_traits(self, **traits): + """Dynamically add trait attributes to the HasTraits instance.""" cls = self.__class__ attrs = {"__module__": cls.__module__} if hasattr(cls, "__qualname__"): @@ -1425,18 +1425,18 @@ class HasTraits(HasDescriptors, metaclass=MetaHasTraits): attrs["__qualname__"] = cls.__qualname__ attrs.update(traits) self.__class__ = type(cls.__name__, (cls,), attrs) - for trait in traits.values(): - trait.instance_init(self) - - def set_trait(self, name, value): - """Forcibly sets trait attribute, including read-only attributes.""" - cls = self.__class__ - if not self.has_trait(name): - raise TraitError("Class %s does not have a trait named %s" % - (cls.__name__, name)) - else: - getattr(cls, name).set(self, value) - + for trait in traits.values(): + trait.instance_init(self) + + def set_trait(self, name, value): + """Forcibly sets trait attribute, including read-only attributes.""" + cls = self.__class__ + if not self.has_trait(name): + raise TraitError("Class %s does not have a trait named %s" % + (cls.__name__, name)) + else: + getattr(cls, name).set(self, value) + @classmethod def class_trait_names(cls, **metadata): """Get a list of all the names of this class' traits. @@ -1444,7 +1444,7 @@ class HasTraits(HasDescriptors, metaclass=MetaHasTraits): This method is just like the :meth:`trait_names` method, but is unbound. """ - return list(cls.class_traits(**metadata)) + return list(cls.class_traits(**metadata)) @classmethod def class_traits(cls, **metadata): @@ -1494,7 +1494,7 @@ class HasTraits(HasDescriptors, metaclass=MetaHasTraits): def has_trait(self, name): """Returns True if the object has a trait with the specified name.""" return isinstance(getattr(self.__class__, name, None), TraitType) - + def trait_has_value(self, name): """Returns True if the specified trait has a value. @@ -1589,7 +1589,7 @@ class HasTraits(HasDescriptors, metaclass=MetaHasTraits): def trait_names(self, **metadata): """Get a list of all the names of this class' traits.""" - return list(self.traits(**metadata)) + return list(self.traits(**metadata)) def traits(self, **metadata): """Get a ``dict`` of all the traits of this class. The dictionary @@ -1630,48 +1630,48 @@ class HasTraits(HasDescriptors, metaclass=MetaHasTraits): except AttributeError: raise TraitError("Class %s does not have a trait named %s" % (self.__class__.__name__, traitname)) - metadata_name = '_' + traitname + '_metadata' - if hasattr(self, metadata_name) and key in getattr(self, metadata_name): - return getattr(self, metadata_name).get(key, default) + metadata_name = '_' + traitname + '_metadata' + if hasattr(self, metadata_name) and key in getattr(self, metadata_name): + return getattr(self, metadata_name).get(key, default) else: return trait.metadata.get(key, default) - @classmethod - def class_own_trait_events(cls, name): - """Get a dict of all event handlers defined on this class, not a parent. - - Works like ``event_handlers``, except for excluding traits from parents. - """ - sup = super(cls, cls) - return {n: e for (n, e) in cls.events(name).items() - if getattr(sup, n, None) is not e} - - @classmethod - def trait_events(cls, name=None): - """Get a ``dict`` of all the event handlers of this class. - - Parameters - ---------- + @classmethod + def class_own_trait_events(cls, name): + """Get a dict of all event handlers defined on this class, not a parent. + + Works like ``event_handlers``, except for excluding traits from parents. + """ + sup = super(cls, cls) + return {n: e for (n, e) in cls.events(name).items() + if getattr(sup, n, None) is not e} + + @classmethod + def trait_events(cls, name=None): + """Get a ``dict`` of all the event handlers of this class. + + Parameters + ---------- name : str (default: None) - The name of a trait of this class. If name is ``None`` then all - the event handlers of this class will be returned instead. - - Returns - ------- - The event handlers associated with a trait name, or all event handlers. - """ - events = {} - for k, v in getmembers(cls): - if isinstance(v, EventHandler): - if name is None: - events[k] = v - elif name in v.trait_names: - events[k] = v - elif hasattr(v, 'tags'): - if cls.trait_names(**v.tags): - events[k] = v - return events - + The name of a trait of this class. If name is ``None`` then all + the event handlers of this class will be returned instead. + + Returns + ------- + The event handlers associated with a trait name, or all event handlers. + """ + events = {} + for k, v in getmembers(cls): + if isinstance(v, EventHandler): + if name is None: + events[k] = v + elif name in v.trait_names: + events[k] = v + elif hasattr(v, 'tags'): + if cls.trait_names(**v.tags): + events[k] = v + return events + #----------------------------------------------------------------------------- # Actual TraitTypes implementations/subclasses #----------------------------------------------------------------------------- @@ -1762,7 +1762,7 @@ class Type(ClassBasedTraitType): if isinstance(self.klass, str): klass = self.klass else: - klass = self.klass.__module__ + '.' + self.klass.__name__ + klass = self.klass.__module__ + '.' + self.klass.__name__ result = "a subclass of '%s'" % klass if self.allow_none: return result + ' or None' @@ -1796,7 +1796,7 @@ class Instance(ClassBasedTraitType): klass = None - def __init__(self, klass=None, args=None, kw=None, **kwargs): + def __init__(self, klass=None, args=None, kw=None, **kwargs): """Construct an Instance trait. This trait allows values that are instances of a particular @@ -1827,7 +1827,7 @@ class Instance(ClassBasedTraitType): """ if klass is None: klass = self.klass - + if (klass is not None) and (inspect.isclass(klass) or isinstance(klass, str)): self.klass = klass else: @@ -1842,7 +1842,7 @@ class Instance(ClassBasedTraitType): self.default_args = args self.default_kwargs = kw - super(Instance, self).__init__(**kwargs) + super(Instance, self).__init__(**kwargs) def validate(self, obj, value): if isinstance(value, self.klass): @@ -1917,8 +1917,8 @@ class This(ClassBasedTraitType): info_text = 'an instance of the same type as the receiver or None' - def __init__(self, **kwargs): - super(This, self).__init__(None, **kwargs) + def __init__(self, **kwargs): + super(This, self).__init__(None, **kwargs) def validate(self, obj, value): # What if value is a superclass of obj.__class__? This is @@ -1933,7 +1933,7 @@ class This(ClassBasedTraitType): class Union(TraitType): """A trait type representing a Union type.""" - def __init__(self, trait_types, **kwargs): + def __init__(self, trait_types, **kwargs): """Construct a Union trait. This trait allows values that are allowed by at least one of the @@ -1951,8 +1951,8 @@ class Union(TraitType): with the validation function of Float, then Bool, and finally Int. """ self.trait_types = list(trait_types) - self.info_text = " or ".join([tt.info() for tt in self.trait_types]) - super(Union, self).__init__(**kwargs) + self.info_text = " or ".join([tt.info() for tt in self.trait_types]) + super(Union, self).__init__(**kwargs) def default(self, obj=None): default = super(Union, self).default(obj) @@ -1974,13 +1974,13 @@ class Union(TraitType): super(Union, self).instance_init(obj) def validate(self, obj, value): - with obj.cross_validation_lock: + with obj.cross_validation_lock: for trait_type in self.trait_types: try: v = trait_type._validate(obj, value) - # In the case of an element trait, the name is None - if self.name is not None: - setattr(obj, '_' + self.name + '_metadata', trait_type.metadata) + # In the case of an element trait, the name is None + if self.name is not None: + setattr(obj, '_' + self.name + '_metadata', trait_type.metadata) return v except TraitError: continue @@ -1992,7 +1992,7 @@ class Union(TraitType): else: return Union(self.trait_types + [other]) - + #----------------------------------------------------------------------------- # Basic TraitTypes implementations/subclasses #----------------------------------------------------------------------------- @@ -2005,37 +2005,37 @@ class Any(TraitType): info_text = 'any value' -def _validate_bounds(trait, obj, value): - """ - Validate that a number to be applied to a trait is between bounds. - - If value is not between min_bound and max_bound, this raises a - TraitError with an error message appropriate for this trait. - """ - if trait.min is not None and value < trait.min: - raise TraitError( - "The value of the '{name}' trait of {klass} instance should " - "not be less than {min_bound}, but a value of {value} was " - "specified".format( - name=trait.name, klass=class_of(obj), - value=value, min_bound=trait.min)) - if trait.max is not None and value > trait.max: - raise TraitError( - "The value of the '{name}' trait of {klass} instance should " - "not be greater than {max_bound}, but a value of {value} was " - "specified".format( - name=trait.name, klass=class_of(obj), - value=value, max_bound=trait.max)) - return value - - +def _validate_bounds(trait, obj, value): + """ + Validate that a number to be applied to a trait is between bounds. + + If value is not between min_bound and max_bound, this raises a + TraitError with an error message appropriate for this trait. + """ + if trait.min is not None and value < trait.min: + raise TraitError( + "The value of the '{name}' trait of {klass} instance should " + "not be less than {min_bound}, but a value of {value} was " + "specified".format( + name=trait.name, klass=class_of(obj), + value=value, min_bound=trait.min)) + if trait.max is not None and value > trait.max: + raise TraitError( + "The value of the '{name}' trait of {klass} instance should " + "not be greater than {max_bound}, but a value of {value} was " + "specified".format( + name=trait.name, klass=class_of(obj), + value=value, max_bound=trait.max)) + return value + + class Int(TraitType): """An int trait.""" default_value = 0 info_text = 'an int' - def __init__(self, default_value=Undefined, allow_none=False, **kwargs): + def __init__(self, default_value=Undefined, allow_none=False, **kwargs): self.min = kwargs.pop('min', None) self.max = kwargs.pop('max', None) super(Int, self).__init__(default_value=default_value, @@ -2044,7 +2044,7 @@ class Int(TraitType): def validate(self, obj, value): if not isinstance(value, int): self.error(obj, value) - return _validate_bounds(self, obj, value) + return _validate_bounds(self, obj, value) def from_string(self, s): if self.allow_none and s == 'None': @@ -2057,12 +2057,12 @@ class CInt(Int): def validate(self, obj, value): try: - value = int(value) + value = int(value) except Exception: self.error(obj, value) - return _validate_bounds(self, obj, value) - + return _validate_bounds(self, obj, value) + Long, CLong = Int, CInt Integer = Int @@ -2073,10 +2073,10 @@ class Float(TraitType): default_value = 0.0 info_text = 'a float' - def __init__(self, default_value=Undefined, allow_none=False, **kwargs): + def __init__(self, default_value=Undefined, allow_none=False, **kwargs): self.min = kwargs.pop('min', -float('inf')) self.max = kwargs.pop('max', float('inf')) - super(Float, self).__init__(default_value=default_value, + super(Float, self).__init__(default_value=default_value, allow_none=allow_none, **kwargs) def validate(self, obj, value): @@ -2084,7 +2084,7 @@ class Float(TraitType): value = float(value) if not isinstance(value, float): self.error(obj, value) - return _validate_bounds(self, obj, value) + return _validate_bounds(self, obj, value) def from_string(self, s): if self.allow_none and s == 'None': @@ -2097,12 +2097,12 @@ class CFloat(Float): def validate(self, obj, value): try: - value = float(value) + value = float(value) except Exception: self.error(obj, value) - return _validate_bounds(self, obj, value) - + return _validate_bounds(self, obj, value) + class Complex(TraitType): """A trait for complex numbers.""" @@ -2243,7 +2243,7 @@ class DottedObjectName(ObjectName): value = self.coerce_str(obj, value) if isinstance(value, str) and all(isidentifier(a) - for a in value.split('.')): + for a in value.split('.')): return value self.error(obj, value) @@ -2289,11 +2289,11 @@ class CBool(Bool): class Enum(TraitType): """An enum whose value must be in a given sequence.""" - def __init__(self, values, default_value=Undefined, **kwargs): + def __init__(self, values, default_value=Undefined, **kwargs): self.values = values - if kwargs.get('allow_none', False) and default_value is Undefined: + if kwargs.get('allow_none', False) and default_value is Undefined: default_value = None - super(Enum, self).__init__(default_value, **kwargs) + super(Enum, self).__init__(default_value, **kwargs) def validate(self, obj, value): if value in self.values: @@ -2331,10 +2331,10 @@ class Enum(TraitType): class CaselessStrEnum(Enum): """An enum of strings where the case should be ignored.""" - - def __init__(self, values, default_value=Undefined, **kwargs): + + def __init__(self, values, default_value=Undefined, **kwargs): super().__init__(values, default_value=default_value, **kwargs) - + def validate(self, obj, value): if not isinstance(value, str): self.error(obj, value) @@ -2444,7 +2444,7 @@ class Container(Instance): will be cast to the container type. allow_none : bool [ default False ] Whether to allow the value to be None - **kwargs : any + **kwargs : any further keys for extensions to the Trait (e.g. config) """ @@ -2630,7 +2630,7 @@ class List(Container): self._minlen = minlen self._maxlen = maxlen super(List, self).__init__(trait=trait, default_value=default_value, - **kwargs) + **kwargs) def length_error(self, obj, value): e = "The '%s' trait of %s instance must be of length %i <= L <= %i, but a value of %s was specified." \ @@ -2693,7 +2693,7 @@ class Set(List): maxlen : Int [ default sys.maxsize ] The maximum length of the input list """ - super(Set, self).__init__(trait, default_value, minlen, maxlen, **kwargs) + super(Set, self).__init__(trait, default_value, minlen, maxlen, **kwargs) def default_value_repr(self): # Ensure default value is sorted for a reproducible build @@ -2709,7 +2709,7 @@ class Tuple(Container): klass = tuple _cast_types = (list,) - def __init__(self, *traits, **kwargs): + def __init__(self, *traits, **kwargs): """Create a tuple from a list, set, or tuple. Create a fixed-type tuple with Traits: @@ -2849,14 +2849,14 @@ class Dict(Instance): _key_trait = None def __init__(self, value_trait=None, per_key_traits=None, key_trait=None, default_value=Undefined, - **kwargs): - """Create a dict trait type from a Python dict. + **kwargs): + """Create a dict trait type from a Python dict. The default value is created by doing ``dict(default_value)``, which creates a copy of the ``default_value``. - Parameters - ---------- + Parameters + ---------- value_trait : TraitType [ optional ] The specified trait type to check and use to restrict the values of the dict. If unspecified, values are not checked. @@ -2871,7 +2871,7 @@ class Dict(Instance): The default value for the Dict. Must be dict, tuple, or None, and will be cast to a dict if not None. If any key or value traits are specified, the `default_value` must conform to the constraints. - + Examples -------- >>> d = Dict(Unicode()) @@ -2934,8 +2934,8 @@ class Dict(Instance): # Case where a type of TraitType is provided rather than an instance if is_trait(value_trait): if isinstance(value_trait, type): - warn("Traits should be given as instances, not types (for example, `Int()`, not `Int`)" - " Passing types is deprecated in traitlets 4.1.", + warn("Traits should be given as instances, not types (for example, `Int()`, not `Int`)" + " Passing types is deprecated in traitlets 4.1.", DeprecationWarning, stacklevel=2) value_trait = value_trait() self._value_trait = value_trait @@ -2954,7 +2954,7 @@ class Dict(Instance): self._per_key_traits = per_key_traits - super(Dict, self).__init__(klass=dict, args=args, **kwargs) + super(Dict, self).__init__(klass=dict, args=args, **kwargs) def element_error(self, obj, element, validator, side='Values'): e = side + " of the '%s' trait of %s instance must be %s, but a value of %s was specified." \ @@ -2974,7 +2974,7 @@ class Dict(Instance): value_trait = self._value_trait if not (key_trait or value_trait or per_key_override): return value - + validated = {} for key in value: v = value[key] @@ -2990,7 +2990,7 @@ class Dict(Instance): except TraitError: self.element_error(obj, v, active_value_trait, 'Values') validated[key] = v - + return self.klass(validated) def class_init(self, cls, name): @@ -3127,85 +3127,85 @@ class CRegExp(TraitType): return re.compile(value) except Exception: self.error(obj, value) - - -class UseEnum(TraitType): - """Use a Enum class as model for the data type description. - Note that if no default-value is provided, the first enum-value is used - as default-value. - - .. sourcecode:: python - - # -- SINCE: Python 3.4 (or install backport: pip install enum34) - import enum - from traitlets import HasTraits, UseEnum - - class Color(enum.Enum): - red = 1 # -- IMPLICIT: default_value - blue = 2 - green = 3 - - class MyEntity(HasTraits): - color = UseEnum(Color, default_value=Color.blue) - - entity = MyEntity(color=Color.red) - entity.color = Color.green # USE: Enum-value (preferred) - entity.color = "green" # USE: name (as string) - entity.color = "Color.green" # USE: scoped-name (as string) - entity.color = 3 # USE: number (as int) - assert entity.color is Color.green - """ - default_value = None - info_text = "Trait type adapter to a Enum class" - - def __init__(self, enum_class, default_value=None, **kwargs): - assert issubclass(enum_class, enum.Enum), \ - "REQUIRE: enum.Enum, but was: %r" % enum_class - allow_none = kwargs.get("allow_none", False) - if default_value is None and not allow_none: - default_value = list(enum_class.__members__.values())[0] - super(UseEnum, self).__init__(default_value=default_value, **kwargs) - self.enum_class = enum_class - self.name_prefix = enum_class.__name__ + "." - - def select_by_number(self, value, default=Undefined): - """Selects enum-value by using its number-constant.""" - assert isinstance(value, int) - enum_members = self.enum_class.__members__ - for enum_item in enum_members.values(): - if enum_item.value == value: - return enum_item - # -- NOT FOUND: - return default - - def select_by_name(self, value, default=Undefined): - """Selects enum-value by using its name or scoped-name.""" + + +class UseEnum(TraitType): + """Use a Enum class as model for the data type description. + Note that if no default-value is provided, the first enum-value is used + as default-value. + + .. sourcecode:: python + + # -- SINCE: Python 3.4 (or install backport: pip install enum34) + import enum + from traitlets import HasTraits, UseEnum + + class Color(enum.Enum): + red = 1 # -- IMPLICIT: default_value + blue = 2 + green = 3 + + class MyEntity(HasTraits): + color = UseEnum(Color, default_value=Color.blue) + + entity = MyEntity(color=Color.red) + entity.color = Color.green # USE: Enum-value (preferred) + entity.color = "green" # USE: name (as string) + entity.color = "Color.green" # USE: scoped-name (as string) + entity.color = 3 # USE: number (as int) + assert entity.color is Color.green + """ + default_value = None + info_text = "Trait type adapter to a Enum class" + + def __init__(self, enum_class, default_value=None, **kwargs): + assert issubclass(enum_class, enum.Enum), \ + "REQUIRE: enum.Enum, but was: %r" % enum_class + allow_none = kwargs.get("allow_none", False) + if default_value is None and not allow_none: + default_value = list(enum_class.__members__.values())[0] + super(UseEnum, self).__init__(default_value=default_value, **kwargs) + self.enum_class = enum_class + self.name_prefix = enum_class.__name__ + "." + + def select_by_number(self, value, default=Undefined): + """Selects enum-value by using its number-constant.""" + assert isinstance(value, int) + enum_members = self.enum_class.__members__ + for enum_item in enum_members.values(): + if enum_item.value == value: + return enum_item + # -- NOT FOUND: + return default + + def select_by_name(self, value, default=Undefined): + """Selects enum-value by using its name or scoped-name.""" assert isinstance(value, str) - if value.startswith(self.name_prefix): - # -- SUPPORT SCOPED-NAMES, like: "Color.red" => "red" - value = value.replace(self.name_prefix, "", 1) - return self.enum_class.__members__.get(value, default) - - def validate(self, obj, value): - if isinstance(value, self.enum_class): - return value - elif isinstance(value, int): - # -- CONVERT: number => enum_value (item) - value2 = self.select_by_number(value) - if value2 is not Undefined: - return value2 + if value.startswith(self.name_prefix): + # -- SUPPORT SCOPED-NAMES, like: "Color.red" => "red" + value = value.replace(self.name_prefix, "", 1) + return self.enum_class.__members__.get(value, default) + + def validate(self, obj, value): + if isinstance(value, self.enum_class): + return value + elif isinstance(value, int): + # -- CONVERT: number => enum_value (item) + value2 = self.select_by_number(value) + if value2 is not Undefined: + return value2 elif isinstance(value, str): - # -- CONVERT: name or scoped_name (as string) => enum_value (item) - value2 = self.select_by_name(value) - if value2 is not Undefined: - return value2 - elif value is None: - if self.allow_none: - return None - else: - return self.default_value - self.error(obj, value) - + # -- CONVERT: name or scoped_name (as string) => enum_value (item) + value2 = self.select_by_name(value) + if value2 is not Undefined: + return value2 + elif value is None: + if self.allow_none: + return None + else: + return self.default_value + self.error(obj, value) + def _choices_str(self, as_rst=False): """ Returns a description of the trait choices (not none).""" choices = self.enum_class.__members__.keys() @@ -3221,7 +3221,7 @@ class UseEnum(TraitType): '') return 'any of %s%s' % (self._choices_str(as_rst), none) - def info(self): + def info(self): return self._info(as_rst=False) def info_rst(self): diff --git a/contrib/python/traitlets/py3/traitlets/utils/bunch.py b/contrib/python/traitlets/py3/traitlets/utils/bunch.py index 2edb830ad6..dc40b5df7d 100644 --- a/contrib/python/traitlets/py3/traitlets/utils/bunch.py +++ b/contrib/python/traitlets/py3/traitlets/utils/bunch.py @@ -1,25 +1,25 @@ -"""Yet another implementation of bunch - -attribute-access of items on a dict. -""" - -# Copyright (c) Jupyter Development Team. -# Distributed under the terms of the Modified BSD License. - -class Bunch(dict): - """A dict with attribute-access""" - def __getattr__(self, key): - try: - return self.__getitem__(key) - except KeyError: - raise AttributeError(key) - - def __setattr__(self, key, value): - self.__setitem__(key, value) - - def __dir__(self): - # py2-compat: can't use super because dict doesn't have __dir__ - names = dir({}) - names.extend(self.keys()) - return names - +"""Yet another implementation of bunch + +attribute-access of items on a dict. +""" + +# Copyright (c) Jupyter Development Team. +# Distributed under the terms of the Modified BSD License. + +class Bunch(dict): + """A dict with attribute-access""" + def __getattr__(self, key): + try: + return self.__getitem__(key) + except KeyError: + raise AttributeError(key) + + def __setattr__(self, key, value): + self.__setitem__(key, value) + + def __dir__(self): + # py2-compat: can't use super because dict doesn't have __dir__ + names = dir({}) + names.extend(self.keys()) + return names + diff --git a/contrib/python/traitlets/py3/ya.make b/contrib/python/traitlets/py3/ya.make index 46980f21b3..99460fa8ed 100644 --- a/contrib/python/traitlets/py3/ya.make +++ b/contrib/python/traitlets/py3/ya.make @@ -9,7 +9,7 @@ OWNER(borman nslus g:python-contrib) VERSION(5.1.1) LICENSE(BSD-3-Clause) - + NO_LINT() PY_SRCS( @@ -28,7 +28,7 @@ PY_SRCS( traitlets/tests/utils.py traitlets/traitlets.py traitlets/utils/__init__.py - traitlets/utils/bunch.py + traitlets/utils/bunch.py traitlets/utils/decorators.py traitlets/utils/descriptions.py traitlets/utils/getargspec.py diff --git a/contrib/python/ya.make b/contrib/python/ya.make index d01ced9f3a..9fefcae7a4 100644 --- a/contrib/python/ya.make +++ b/contrib/python/ya.make @@ -124,7 +124,7 @@ RECURSE( braceexpand bravado bravado-core - bsddb3 + bsddb3 bson bz2file cached-property @@ -151,7 +151,7 @@ RECURSE( clang clang/example cli-helpers - click + click click-didyoumean click-plugins click-repl @@ -160,7 +160,7 @@ RECURSE( clickhouse-sqlalchemy cloudpickle color - colorama + colorama coloredlogs colorhash colorlog @@ -202,7 +202,7 @@ RECURSE( DAWG-Python dbf_light debian-inspector - decorator + decorator deepdiff deepmerge defusedxml @@ -210,7 +210,7 @@ RECURSE( Deprecated dictpath diff-match-patch - directio + directio distro django django-admin-inline-paginator @@ -315,7 +315,7 @@ RECURSE( dm.xmlsec.binding dnspython docker - docopt + docopt docstring-parser docutils dohq-teamcity @@ -405,7 +405,7 @@ RECURSE( Flask-RESTful flask-restplus flask-restx - Flask-Script + Flask-Script flask-shell-ipython Flask-Shelve Flask-SQLAlchemy @@ -425,7 +425,7 @@ RECURSE( funcparserlib funcsigs functools32 - furl + furl future futures gast @@ -463,11 +463,11 @@ RECURSE( graphql-relay graphviz greenify - greenlet + greenlet grequests grpcio-opentracing gspread - gunicorn + gunicorn h11 h2 h3 @@ -505,7 +505,7 @@ RECURSE( icalendar idna idna-ssl - ijson + ijson imagesize IMAPClient imgkit @@ -524,12 +524,12 @@ RECURSE( intbitset intspan invoke - ipaddr + ipaddr ipaddress ipadic ipdb ipykernel - ipython + ipython ipython-genutils ipython-sql ipywidgets @@ -543,7 +543,7 @@ RECURSE( jaraco.functools javaproperties jdcal - jedi + jedi Jinja2 jinja2-time jmespath @@ -604,7 +604,7 @@ RECURSE( Mako marisa_trie markdown2 - Markdown + Markdown MarkupSafe marshmallow marshmallow_dataclass @@ -651,9 +651,9 @@ RECURSE( mypy-extensions mypy-protobuf mypy-zope - MySQL-python + MySQL-python mysqlclient-python - namedlist + namedlist natsort nbclient nbconvert @@ -670,7 +670,7 @@ RECURSE( nose notebook num2words - numpy + numpy oauth2client oauthlib objgraph @@ -692,7 +692,7 @@ RECURSE( opt-einsum option ordered-set - orderedmultidict + orderedmultidict orderedset os-fast-reservoir packageurl-python @@ -733,12 +733,12 @@ RECURSE( peewee/playhouse pefile pem - pexpect + pexpect pgcli PGPy pgspecial phonenumbers - pickleshare + pickleshare pika Pillow pip @@ -758,7 +758,7 @@ RECURSE( pq pql prance - premailer + premailer preshed pretend prettytable @@ -774,14 +774,14 @@ RECURSE( protobuf_to_dict psutil psycogreen - psycopg2 - ptpython - ptyprocess + psycopg2 + ptpython + ptyprocess publicsuffix2 pure-eval pure-python-adb pure-sasl - py + py py-asciimath py-expression-eval py-radix @@ -799,7 +799,7 @@ RECURSE( pycollada pycountry pycparser - pycrypto + pycrypto pycryptodome pycurl pycurl/example @@ -831,7 +831,7 @@ RECURSE( pylzma pymaven-patch PyMeeus - pymongo + pymongo pymorphy2 pymorphy2-dicts-ru pymqi @@ -922,7 +922,7 @@ RECURSE( pyudev pyusb PyWavelets - PyYAML + PyYAML pyzmq qemu qrcode @@ -983,7 +983,7 @@ RECURSE( seaborn selectors2 selenium - semantic-version + semantic-version semver Send2Trash sentinels @@ -1081,7 +1081,7 @@ RECURSE( tqdm trace_event traceback2 - traitlets + traitlets transfer_manager_client transitions transliterate @@ -1110,7 +1110,7 @@ RECURSE( umongo unicodecsv Unidecode - unidiff + unidiff uplink uritemplate uritools |